Compare commits
2 Commits
eff2fd913e
...
a481d31fb2
Author | SHA1 | Date |
---|---|---|
|
a481d31fb2 | |
|
1169908e50 |
|
@ -32,3 +32,4 @@ pnpm-debug.log*
|
|||
/.vscode/
|
||||
/.history/
|
||||
/svn clear.bat
|
||||
/dist.zip
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
<BasicTable @register="registerTable" style="margin-top:-20px;">
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
<!--字段回显插槽-->
|
||||
<template #htmlSlot="{text}">
|
||||
<template #htmlSlot="{ text }">
|
||||
<div v-html="text"></div>
|
||||
</template>
|
||||
<!--省市区字段回显插槽-->
|
||||
|
@ -49,157 +49,162 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" name="zyInfoStudent-zyInfoStudent" setup>
|
||||
import { ref, reactive,defineExpose,unref } from 'vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { columnsKccyStu } from '/@/views/zy/zyInfoStudent/ZyInfoStudent.data';
|
||||
import { stuKccyList } from '/@/views/zy/zyInfoStudent/ZyInfoStudent.api';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { ref, reactive, defineExpose, unref } from 'vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { columnsKccyStu } from '/@/views/zy/zyInfoStudent/ZyInfoStudent.data';
|
||||
import { stuKccyList } from '/@/views/zy/zyInfoStudent/ZyInfoStudent.api';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
|
||||
import WjxWjxxTmlbDjModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjModal.vue'
|
||||
import WjxWjxxTmlbDjjgModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjjgModal.vue'
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { JInput } from '/@/components/Form';
|
||||
import { useRouter } from 'vue-router';
|
||||
import WjxWjxxTmlbDjModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjModal.vue'
|
||||
import WjxWjxxTmlbDjjgModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjjgModal.vue'
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { JInput } from '/@/components/Form';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const { currentRoute } = useRouter();
|
||||
const { query } = unref(currentRoute);
|
||||
const { rwbh,xqxn,type,teano } = query;//获取传递参数
|
||||
const { currentRoute } = useRouter();
|
||||
const { query } = unref(currentRoute);
|
||||
const { rwbh, xqxn, type, teano } = query;//获取传递参数
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const queryParam = ref<any>({rwbh,xqxn,teano,atype:'6'});
|
||||
const queryParam = ref<any>({ rwbh, xqxn, teano, atype: '6' });
|
||||
|
||||
const WjxWjxxTmlbDjModalPage = ref();
|
||||
const WjxWjxxTmlbDjjgModalPage = ref();
|
||||
const WjxWjxxTmlbDjModalPage = ref();
|
||||
const WjxWjxxTmlbDjjgModalPage = ref();
|
||||
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext} = useListPage({
|
||||
tableProps: {
|
||||
api: stuKccyList,
|
||||
columns:columnsKccyStu,
|
||||
canResize:false,
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: '150px',
|
||||
fixed: 'right',
|
||||
},
|
||||
showTableSetting: true,
|
||||
defSort: {
|
||||
field: 'name',
|
||||
order: 'ascend',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
params.column = 'createTime',params.order = 'desc';//新生成的默认不带排序
|
||||
return Object.assign(params, queryParam.value);
|
||||
},
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: stuKccyList,
|
||||
columns: columnsKccyStu,
|
||||
canResize: false,
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: '150px',
|
||||
fixed: 'right',
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
const labelCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 7 },
|
||||
});
|
||||
const wrapperCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
});
|
||||
showTableSetting: true,
|
||||
defSort: {
|
||||
field: 'name',
|
||||
order: 'ascend',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
params.column = 'createTime', params.order = 'desc';//新生成的默认不带排序
|
||||
return Object.assign(params, queryParam.value);
|
||||
},
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
const labelCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 7 },
|
||||
});
|
||||
const wrapperCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDj(record: Recordable) {
|
||||
let timestamp = new Date().getTime();
|
||||
let startTimestamp = Date.parse(record.startTime);
|
||||
if(timestamp<startTimestamp){
|
||||
createMessage.error('还未到答卷时间!');
|
||||
return;
|
||||
}
|
||||
let endTimestamp = Date.parse(record.endTime+" 23:59:59");
|
||||
if(timestamp>endTimestamp){
|
||||
createMessage.error('答卷时间已过!');
|
||||
return;
|
||||
}
|
||||
WjxWjxxTmlbDjModalPage.value.disableSubmit = false;
|
||||
WjxWjxxTmlbDjModalPage.value.edit(record,false,"6",'xs');
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDj(record: Recordable) {
|
||||
let timestamp = new Date().getTime();
|
||||
let startTimestamp = Date.parse(record.startTime);
|
||||
if (timestamp < startTimestamp) {
|
||||
createMessage.error('还未到答卷时间!');
|
||||
return;
|
||||
}
|
||||
let endTimestamp = Date.parse(record.endTime + " 23:59:59");
|
||||
if (timestamp > endTimestamp) {
|
||||
createMessage.error('答卷时间已过!');
|
||||
return;
|
||||
}
|
||||
// WjxWjxxTmlbDjModalPage.value.disableSubmit = false;
|
||||
// WjxWjxxTmlbDjModalPage.value.edit(record, false, "6", 'xs');
|
||||
|
||||
var url = "/site/studentDjcy?cytitle=" + record.title + "&cyid=" + record.id + "&cyatype=6&sfzd=0&sfbs=xs";
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDjjg(record: Recordable) {
|
||||
WjxWjxxTmlbDjjgModalPage.value.disableSubmit = true;
|
||||
WjxWjxxTmlbDjjgModalPage.value.edit(record.djId, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
selectedRowKeys.value = [];
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
|
||||
|
||||
// <a-button type="primary" @click="handleDj(item)" style="margin-left:5px;padding: 0px 8px;background:rgb(28, 132, 198);" v-if="item.flag=='-1'">开始测验</a-button>
|
||||
// <a-button type="primary" style="margin-left:5px;padding: 0px 8px;background:rgb(28, 132, 198);color:#ffffff" v-if="item.flag=='0'" disabled>正在批卷</a-button>
|
||||
// <a-button type="primary" @click="handleDjjg(item)" style="margin-left:5px;padding: 0px 8px;background:rgb(28, 132, 198);" v-if="item.flag=='1'">查看结果</a-button>
|
||||
if (record.flag == '-1') {
|
||||
var list = [
|
||||
{
|
||||
label: '开始测验',
|
||||
onClick: handleDj.bind(null, record),
|
||||
},
|
||||
];
|
||||
return list;
|
||||
} else if (record.flag == '0') {
|
||||
return null;
|
||||
} else {
|
||||
var list = [
|
||||
{
|
||||
label: '查看结果',
|
||||
onClick: handleDjjg.bind(null, record),
|
||||
},
|
||||
];
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDjjg(record: Recordable) {
|
||||
WjxWjxxTmlbDjjgModalPage.value.disableSubmit = true;
|
||||
WjxWjxxTmlbDjjgModalPage.value.edit(record.djId,false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
selectedRowKeys.value = [];
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
|
||||
|
||||
// <a-button type="primary" @click="handleDj(item)" style="margin-left:5px;padding: 0px 8px;background:rgb(28, 132, 198);" v-if="item.flag=='-1'">开始测验</a-button>
|
||||
// <a-button type="primary" style="margin-left:5px;padding: 0px 8px;background:rgb(28, 132, 198);color:#ffffff" v-if="item.flag=='0'" disabled>正在批卷</a-button>
|
||||
// <a-button type="primary" @click="handleDjjg(item)" style="margin-left:5px;padding: 0px 8px;background:rgb(28, 132, 198);" v-if="item.flag=='1'">查看结果</a-button>
|
||||
if(record.flag == '-1'){
|
||||
var list = [
|
||||
{
|
||||
label: '开始测验',
|
||||
onClick: handleDj.bind(null, record),
|
||||
},
|
||||
];
|
||||
return list;
|
||||
}else if(record.flag == '0'){
|
||||
return null;
|
||||
}else{
|
||||
var list = [
|
||||
{
|
||||
label: '查看结果',
|
||||
onClick: handleDjjg.bind(null, record),
|
||||
},
|
||||
];
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function searchQuery() {
|
||||
selectedRowKeys.value = [];
|
||||
reload();
|
||||
}
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function searchQuery() {
|
||||
selectedRowKeys.value = [];
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.jeecg-basic-table-form-container {
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
width: calc(50% - 15px);
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
.jeecg-basic-table-form-container {
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.query-group-cust {
|
||||
width: calc(50% - 15px);
|
||||
min-width: 100px !important;
|
||||
}
|
||||
|
||||
.query-group-split-cust {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -30,39 +30,44 @@
|
|||
</a-form>
|
||||
</div>
|
||||
<a-row>
|
||||
<a-col :span="24" v-for="(item, index) in tableData" :key="index" style="padding: 0px 0px 5px 5px;overflow:hidden;">
|
||||
<a-col :span="24" v-for="(item, index) in tableData" :key="index"
|
||||
style="padding: 0px 0px 5px 5px;overflow:hidden;">
|
||||
<div style="width: 100%; "></div>
|
||||
<a-card style="height: 130px;border: 1px solid #eef1f2; border-radius:5px; margin:3px 5px">
|
||||
<div class="rotate" :style="classFun(item.flag)">{{getStatus(item.flag)}}</div>
|
||||
<div class="rotate" :style="classFun(item.flag)">{{ getStatus(item.flag) }}</div>
|
||||
<a-row style="top: -48px;position: relative;">
|
||||
<a-col :lg="{span:0}" :span="4" :push="20">
|
||||
<a-col :lg="{ span: 0 }" :span="4" :push="20">
|
||||
<div class="wczt-sm" :style="classFun_sm(item.flag)">{{ getStatus(item.flag) }}</div>
|
||||
</a-col>
|
||||
<a-col :span="24" style="margin-bottom: 10px;height:53px;overflow:hidden;">
|
||||
<div style="font-size: 18px;font-weight: bold;">{{item.title}}</div>
|
||||
<div style="font-size: 18px;font-weight: bold;">{{ item.title }}</div>
|
||||
</a-col>
|
||||
<a-col :span="24" class="zyCon">
|
||||
<a-row>
|
||||
<a-col :span="18" class="zyCon" style=" color: #666;">
|
||||
时间:{{dayjs(item.startTime).format('MM.DD HH-mm')}} - {{dayjs(item.endTime).format('MM.DD HH-mm')}}
|
||||
时间:{{ dayjs(item.startTime).format('MM.DD HH-mm') }} - {{ dayjs(item.endTime).format('MM.DD HH-mm') }}
|
||||
</a-col>
|
||||
<a-col :span="6" style="text-align:center;">
|
||||
<a-button type="primary" @click="handleDj(item)" style="margin-left:5px;padding: 0px 8px;background:#1ab394;" v-if="item.flag=='-1'">开始测验</a-button>
|
||||
<a-button type="primary" style="margin-left:5px;padding: 0px 8px;background:#1ab394;color:#ffffff" v-if="item.flag=='0'" disabled>正在批卷</a-button>
|
||||
<a-button type="primary" @click="handleDjjg(item)" style="margin-left:5px;padding: 0px 8px;background:#1ab394;" v-if="item.flag=='1'">查看结果</a-button>
|
||||
<a-button type="primary" @click="handleDj(item, true)"
|
||||
style="margin-left:5px;padding: 0px 8px;background:#1ab394;" v-if="item.flag == '-1'">开始测验</a-button>
|
||||
<a-button type="primary" style="margin-left:5px;padding: 0px 8px;background:#1ab394;color:#ffffff"
|
||||
v-if="item.flag == '0'" disabled>正在批卷</a-button>
|
||||
<a-button type="primary" @click="handleDjjg(item)"
|
||||
style="margin-left:5px;padding: 0px 8px;background:#1ab394;" v-if="item.flag == '1'">查看结果</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
|
||||
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<div v-show="tableData.length>0">
|
||||
<a-pagination v-model="current" :total="total" @change="handlePageChange" :pageSize="pageSize" style="text-align: right;"/>
|
||||
<div v-show="tableData.length > 0">
|
||||
<a-pagination v-model="current" :total="total" @change="handlePageChange" :pageSize="pageSize"
|
||||
style="text-align: right;" />
|
||||
</div>
|
||||
<div v-show="tableData.length==0">
|
||||
<a-empty/>
|
||||
<div v-show="tableData.length == 0">
|
||||
<a-empty />
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -72,198 +77,211 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" name="wjxWjxx-wjxWjxx" setup>
|
||||
import {ref, reactive, defineExpose, unref, onMounted} from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
|
||||
import WjxWjxxTmlbDjModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjModal.vue'
|
||||
import WjxWjxxTmlbDjjgModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjjgModal.vue'
|
||||
import {useRouter} from "vue-router";
|
||||
import {useMessage} from "/@/hooks/web/useMessage";
|
||||
import dayjs from 'dayjs';
|
||||
import { ref, reactive, defineExpose, unref, onMounted } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
|
||||
import WjxWjxxTmlbDjModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjModal.vue'
|
||||
import WjxWjxxTmlbDjjgModal from '/@/views/kc/wjxWjxx/components/WjxWjxxTmlbDjjgModal.vue'
|
||||
import { useRouter } from "vue-router";
|
||||
import { useMessage } from "/@/hooks/web/useMessage";
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
//当前路由信息
|
||||
const { currentRoute } = useRouter();
|
||||
const { query } = unref(currentRoute);
|
||||
const { rwbh,xqxn,type,teano } = query;//获取传递参数
|
||||
const { createMessage } = useMessage();
|
||||
const APagination = Pagination;
|
||||
const queryParam = ref<any>({});
|
||||
const current = ref<number>(0);
|
||||
const total = ref<number>(0);
|
||||
const pageNo = ref<number>(0);
|
||||
const pageSize = ref<number>(6);
|
||||
const tableData = ref<any>([]);
|
||||
//当前路由信息
|
||||
const { currentRoute } = useRouter();
|
||||
const { query } = unref(currentRoute);
|
||||
const { rwbh, xqxn, type, teano } = query;//获取传递参数
|
||||
const { createMessage } = useMessage();
|
||||
const APagination = Pagination;
|
||||
const queryParam = ref<any>({});
|
||||
const current = ref<number>(0);
|
||||
const total = ref<number>(0);
|
||||
const pageNo = ref<number>(0);
|
||||
const pageSize = ref<number>(6);
|
||||
const tableData = ref<any>([]);
|
||||
|
||||
const WjxWjxxTmlbDjModalPage = ref();
|
||||
const WjxWjxxTmlbDjjgModalPage = ref();
|
||||
const WjxWjxxTmlbDjModalPage = ref();
|
||||
const WjxWjxxTmlbDjjgModalPage = ref();
|
||||
|
||||
const labelCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 7 },
|
||||
});
|
||||
const wrapperCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
const labelCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 7 },
|
||||
});
|
||||
const wrapperCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDj(record: Recordable, isTesting = false) {
|
||||
let timestamp = new Date().getTime();
|
||||
let startTimestamp = Date.parse(record.startTime);
|
||||
if (timestamp < startTimestamp) {
|
||||
createMessage.error('还未到答卷时间!');
|
||||
return;
|
||||
}
|
||||
let endTimestamp = Date.parse(record.endTime);
|
||||
if (timestamp > endTimestamp) {
|
||||
createMessage.error('答卷时间已过!');
|
||||
return;
|
||||
}
|
||||
// WjxWjxxTmlbDjModalPage.value.disableSubmit = false;
|
||||
// WjxWjxxTmlbDjModalPage.value.edit(record,false,"6",'xs');
|
||||
// cytitle, cyid, cyatype, sfzd, sfbs
|
||||
var url = "/site/studentDjcy?cytitle=" + record.title + "&cyid=" + record.id + "&cyatype=6&sfzd=0&sfbs=xs";
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDjjg(record: Recordable) {
|
||||
WjxWjxxTmlbDjjgModalPage.value.disableSubmit = true;
|
||||
WjxWjxxTmlbDjjgModalPage.value.edit(record.djId, false);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
queryParam.value.pageNo = current.value;
|
||||
queryParam.value.pageSize = pageSize.value;
|
||||
queryParam.value.rwbh = rwbh;
|
||||
queryParam.value.xqxn = xqxn;
|
||||
queryParam.value.teano = teano;
|
||||
queryParam.value.atype = "6";
|
||||
defHttp.get({ url: '/wjxWjxx/wjxWjxx/stuList', params: queryParam.value }).then(res => {
|
||||
// console.log(`🚀 ~ defHttp.get ~ res:`, res)
|
||||
total.value = res.total;
|
||||
pageNo.value = res.pages;
|
||||
current.value = res.current;
|
||||
tableData.value = res.records;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDj(record: Recordable) {
|
||||
let timestamp = new Date().getTime();
|
||||
let startTimestamp = Date.parse(record.startTime);
|
||||
if(timestamp<startTimestamp){
|
||||
createMessage.error('还未到答卷时间!');
|
||||
return;
|
||||
}
|
||||
let endTimestamp = Date.parse(record.endTime);
|
||||
if(timestamp>endTimestamp){
|
||||
createMessage.error('答卷时间已过!');
|
||||
return;
|
||||
}
|
||||
// WjxWjxxTmlbDjModalPage.value.disableSubmit = false;
|
||||
// WjxWjxxTmlbDjModalPage.value.edit(record,false,"6",'xs');
|
||||
// cytitle, cyid, cyatype, sfzd, sfbs
|
||||
var url ="/site/studentDjcy?cytitle="+record.title+"&cyid="+record.id+"&cyatype=6&sfzd=0&sfbs=xs";
|
||||
window.open(url,'_blank')
|
||||
}
|
||||
|
||||
/**
|
||||
* 答卷详情
|
||||
*/
|
||||
function handleDjjg(record: Recordable) {
|
||||
WjxWjxxTmlbDjjgModalPage.value.disableSubmit = true;
|
||||
WjxWjxxTmlbDjjgModalPage.value.edit(record.djId,false);
|
||||
}
|
||||
|
||||
function reload(){
|
||||
queryParam.value.pageNo = current.value;
|
||||
queryParam.value.pageSize = pageSize.value;
|
||||
queryParam.value.rwbh = rwbh;
|
||||
queryParam.value.xqxn = xqxn;
|
||||
queryParam.value.teano = teano;
|
||||
queryParam.value.atype = "6";
|
||||
defHttp.get({ url: '/wjxWjxx/wjxWjxx/stuList', params: queryParam.value }).then(res => {
|
||||
// console.log(`🚀 ~ defHttp.get ~ res:`, res)
|
||||
total.value = res.total;
|
||||
pageNo.value = res.pages;
|
||||
current.value = res.current;
|
||||
tableData.value = res.records;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function searchQuery() {
|
||||
total.value = 1;
|
||||
handlePageChange(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function searchReset() {
|
||||
queryParam.value = {};
|
||||
total.value = 1;
|
||||
handlePageChange(1);
|
||||
}
|
||||
|
||||
function handlePageChange(record){
|
||||
current.value = record;
|
||||
reload();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
searchQuery();
|
||||
});
|
||||
|
||||
function classFun(type){
|
||||
if(type == '-1'){
|
||||
return 'background: linear-gradient(180deg, #63c4e4, #24a7d5);';
|
||||
}else if(type == '0'){
|
||||
return 'background: linear-gradient(180deg, #fea317, #ff7d28);';
|
||||
}else if(type == '1'){
|
||||
return 'background: linear-gradient(180deg, #fb8c7f, #f56670)';
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function searchQuery() {
|
||||
total.value = 1;
|
||||
handlePageChange(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function searchReset() {
|
||||
queryParam.value = {};
|
||||
total.value = 1;
|
||||
handlePageChange(1);
|
||||
}
|
||||
|
||||
function handlePageChange(record) {
|
||||
current.value = record;
|
||||
reload();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
searchQuery();
|
||||
});
|
||||
|
||||
function classFun(type) {
|
||||
if (type == '-1') {
|
||||
return 'background: linear-gradient(180deg, #63c4e4, #24a7d5);';
|
||||
} else if (type == '0') {
|
||||
return 'background: linear-gradient(180deg, #fea317, #ff7d28);';
|
||||
} else if (type == '1') {
|
||||
return 'background: linear-gradient(180deg, #fb8c7f, #f56670)';
|
||||
}
|
||||
}
|
||||
|
||||
function classFun_sm(type) {
|
||||
if (type == '-1') {
|
||||
return 'color: rgb(215, 72, 82);'; // 深红色
|
||||
} else if (type == '0') {
|
||||
return 'color: rgb(225, 95, 10);'; // 深橙色
|
||||
} else if (type == '1') {
|
||||
return 'color: rgb(5, 136, 182);'; // 深天蓝色
|
||||
}
|
||||
return 'color: rgb(215, 72, 82);'; // 深红色
|
||||
} else if (type == '0') {
|
||||
return 'color: rgb(225, 95, 10);'; // 深橙色
|
||||
} else if (type == '1') {
|
||||
return 'color: rgb(5, 136, 182);'; // 深天蓝色
|
||||
}
|
||||
}
|
||||
|
||||
function getStatus(flag){
|
||||
if(flag == '-1'){
|
||||
return "待提交";
|
||||
}else if(flag == '0'){
|
||||
return "待评分";
|
||||
}else if(flag == '1'){
|
||||
return "已完成";
|
||||
}
|
||||
function getStatus(flag) {
|
||||
if (flag == '-1') {
|
||||
return "待提交";
|
||||
} else if (flag == '0') {
|
||||
return "待评分";
|
||||
} else if (flag == '1') {
|
||||
return "已完成";
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.wczt-sm {
|
||||
border-radius: 3px;
|
||||
color: rgb(0, 0, 0); /* 设置文字颜色为白色 */
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: center; /* 水平居中 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
height: 100%; /* 确保容器有高度,否则垂直居中可能不会按预期工作 */
|
||||
text-align: center; /* 如果有多行文本,保证它们也居中 */
|
||||
.wczt-sm {
|
||||
border-radius: 3px;
|
||||
color: rgb(0, 0, 0);
|
||||
/* 设置文字颜色为白色 */
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
/* 水平居中 */
|
||||
align-items: center;
|
||||
/* 垂直居中 */
|
||||
height: 100%;
|
||||
/* 确保容器有高度,否则垂直居中可能不会按预期工作 */
|
||||
text-align: center;
|
||||
/* 如果有多行文本,保证它们也居中 */
|
||||
}
|
||||
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
width: 99%;
|
||||
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
width: 99%;
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
width: calc(50% - 15px);
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
.query-group-cust {
|
||||
width: calc(50% - 15px);
|
||||
min-width: 100px !important;
|
||||
}
|
||||
|
||||
.jeecg-basic-table-form-container .ant-form {
|
||||
padding: 12px 10px 0px 10px;
|
||||
margin-bottom: 0px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
.query-group-split-cust {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
overflow: hidden; /* 确保超出容器的内容被裁剪 */
|
||||
white-space: nowrap; /* 确保文本在一行内显示 */
|
||||
text-overflow: ellipsis; /* 超出部分显示省略号 */
|
||||
}
|
||||
.zyCon{
|
||||
line-height: 30px;
|
||||
}
|
||||
.rotate {
|
||||
.jeecg-basic-table-form-container .ant-form {
|
||||
padding: 12px 10px 0px 10px;
|
||||
margin-bottom: 0px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.ellipsis {
|
||||
overflow: hidden;
|
||||
/* 确保超出容器的内容被裁剪 */
|
||||
white-space: nowrap;
|
||||
/* 确保文本在一行内显示 */
|
||||
text-overflow: ellipsis;
|
||||
/* 超出部分显示省略号 */
|
||||
}
|
||||
|
||||
.zyCon {
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.rotate {
|
||||
transform: rotate(45deg);
|
||||
background: linear-gradient(90deg, #93d861, #8ddc53, #35c495);
|
||||
color: #fff;
|
||||
|
|
|
@ -144,14 +144,25 @@
|
|||
valueFormat="YYYY-MM-DD HH:mm"
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
style="width: 100%"
|
||||
:disabled="editDisabled"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24" class="jbxx-cytm">
|
||||
<a-form-item label="防作弊">
|
||||
<a-radio-group v-model:value="zyInfo.fzbms" :options="fzbOptions" :disabled="editDisabled"/><span style="color:#AAAAAA;">防作弊功能仅限PC端,不支持文件题测验。</span>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24" class="jbxx-cytm">
|
||||
<a-form-item label="作答时限">
|
||||
<a-input-number id="inputNumber" v-model:value="zyInfo.zdsx" :min="0" :max="120" :controls="false" :precision="0" :disabled="editDisabled"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24" class="jbxx-ms">
|
||||
<a-form-item label="描述" v-bind="validateInfos.content">
|
||||
<j-editor v-model:value="zyInfo.content" v-if="zyyqShow" @blur="handleZyyqShow(0)" />
|
||||
<div style="color: #777777" v-html="zyInfo.content" v-if="!zyyqShow"></div>
|
||||
<div @click="handleZyyqShow(1)" class="tishi" style="width: 100%" :disabled="!editDisabled">温馨提示:点击可编辑描述</div>
|
||||
<div v-show="!editDisabled" @click="handleZyyqShow(1)" class="tishi" style="width: 100%" :disabled="!editDisabled">温馨提示:点击可编辑描述</div>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</div>
|
||||
|
@ -611,7 +622,7 @@
|
|||
</a-col>
|
||||
|
||||
<a-col :span="24" style="text-align: center; margin-top: 10px; margin-bottom: 40px">
|
||||
<a-button type="primary" @click="submitForm" v-if="!editDisabled">保存</a-button>
|
||||
<a-button type="primary" @click="submitForm" v-if="!editDisabled">保存2</a-button>
|
||||
<a-button type="primary" @click="reloadZy" style="margin-left: 15px">返回</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -1331,7 +1342,7 @@ const total = ref<number>(0);
|
|||
const pageNo = ref<number>(0);
|
||||
const pageSize = ref<number>(100);
|
||||
const editDisabled = ref<boolean>(false);
|
||||
const zyInfo = ref<any>({});
|
||||
const zyInfo = ref<any>({fzbms:'N'});
|
||||
const dataKhnr = ref<any>([]);
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
const zyyqShow = ref<boolean>(false);
|
||||
|
@ -1393,7 +1404,10 @@ const labelCol4 = reactive({
|
|||
const wrapperCol4 = reactive({
|
||||
sm: { span: 12 },
|
||||
});
|
||||
|
||||
const fzbOptions = ref([
|
||||
{ label: '关闭', value: 'N' },
|
||||
{ label: '开启', value: 'Y' },
|
||||
]);
|
||||
//分享给他人
|
||||
function handleFenxiang(record){
|
||||
console.log(record);
|
||||
|
@ -2323,6 +2337,18 @@ async function submitForm() {
|
|||
confirmLoading.value = false;
|
||||
return;
|
||||
}
|
||||
// 如果有文件题 且 开启了防作弊 需要关掉防作弊 并提示用户
|
||||
if (zyInfo.value.fzbms == 'Y') {
|
||||
let falg = true
|
||||
tiganData.value.forEach(item => {
|
||||
if (item.wjType == 8) falg = false
|
||||
});
|
||||
if (!falg) {
|
||||
createMessage.error('包含文件题时,无法启用防作弊模式,请主动关闭!');
|
||||
confirmLoading.value = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
model.list = values;
|
||||
console.log('😨', model);
|
||||
|
@ -2365,6 +2391,7 @@ function handleEdit(record, type) {
|
|||
}
|
||||
editDisabled.value = type;
|
||||
zyInfo.value = record;
|
||||
if(!zyInfo.value.fzbms)zyInfo.value.fzbms = 'N'
|
||||
dataKhnr.value = [];
|
||||
mainId.value = record.id;
|
||||
|
||||
|
|
|
@ -148,6 +148,16 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24" class="jbxx-cytm">
|
||||
<a-form-item label="防作弊">
|
||||
<a-radio-group v-model:value="zyInfo.fzbms" :options="fzbOptions" :disabled="editDisabled"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24" class="jbxx-cytm">
|
||||
<a-form-item label="作答时限">
|
||||
<a-input-number id="inputNumber" v-model:value="zyInfo.zdsx" :min="0" :max="120" :controls="false" :precision="0" :disabled="editDisabled"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24" class="jbxx-ms">
|
||||
<a-form-item label="描述" v-bind="validateInfos.content">
|
||||
<p v-html="zyInfo.content"></p>
|
||||
|
@ -1334,6 +1344,10 @@ const kczyzb = ref<number>(0);
|
|||
const qmkszb = ref<number>(0);
|
||||
const ktcyzb = ref<number>(0);
|
||||
const importOpen = ref<boolean>(false);
|
||||
const fzbOptions = ref([
|
||||
{ label: '关闭', value: 'N' },
|
||||
{ label: '开启', value: 'Y' },
|
||||
]);
|
||||
|
||||
//设置测验删除功能
|
||||
const disabledDate = (current: Dayjs) => {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from "/@/hooks/web/useMessage";
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
|
||||
enum Api {
|
||||
list = '/wjxDjxxFzbtj/wjxDjxxFzbtj/list',
|
||||
save='/wjxDjxxFzbtj/wjxDjxxFzbtj/add',
|
||||
edit='/wjxDjxxFzbtj/wjxDjxxFzbtj/edit',
|
||||
deleteOne = '/wjxDjxxFzbtj/wjxDjxxFzbtj/delete',
|
||||
deleteBatch = '/wjxDjxxFzbtj/wjxDjxxFzbtj/deleteBatch',
|
||||
importExcel = '/wjxDjxxFzbtj/wjxDjxxFzbtj/importExcel',
|
||||
exportXls = '/wjxDjxxFzbtj/wjxDjxxFzbtj/exportXls',
|
||||
getExamTime = '/wjxDjxxFzbtj/wjxDjxxFzbtj/getExamTime'
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出api
|
||||
* @param params
|
||||
*/
|
||||
export const getExportUrl = Api.exportXls;
|
||||
|
||||
/**
|
||||
* 导入api
|
||||
*/
|
||||
export const getImportUrl = Api.importExcel;
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||
|
||||
/**
|
||||
* 删除单个
|
||||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const deleteOne = (params,handleSuccess) => {
|
||||
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const batchDelete = (params, handleSuccess) => {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认删除',
|
||||
content: '是否删除选中数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或者更新
|
||||
* @param params
|
||||
* @param isUpdate
|
||||
*/
|
||||
export const saveOrUpdate = (params, isUpdate) => {
|
||||
let url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或者更新
|
||||
* @param params
|
||||
* @param isUpdate
|
||||
*/
|
||||
export const fzbSaveOrUpdate = (params, isUpdate) => {
|
||||
let url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* 从redis中获取答题结束时间
|
||||
* @param params
|
||||
* @param isUpdate
|
||||
*/
|
||||
export const getExamTime = (params) => {
|
||||
return defHttp.post({ url: Api.getExamTime, data:params }, { isTransformResponse: false });
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
import {BasicColumn} from '/@/components/Table';
|
||||
import {FormSchema} from '/@/components/Table';
|
||||
import { rules} from '/@/utils/helper/validator';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: 'wjx_djxx表id',
|
||||
align: "center",
|
||||
dataIndex: 'djxxId'
|
||||
},
|
||||
{
|
||||
title: '学生姓名',
|
||||
align: "center",
|
||||
dataIndex: 'studentName'
|
||||
},
|
||||
{
|
||||
title: '问卷编号(提交问卷、查询问卷会用到)',
|
||||
align: "center",
|
||||
dataIndex: 'vid'
|
||||
},
|
||||
{
|
||||
title: '答卷编号',
|
||||
align: "center",
|
||||
dataIndex: 'jid'
|
||||
},
|
||||
// 作弊类型 1、退出全屏2、切屏3、考试超时4、开始答题
|
||||
{
|
||||
title: '作弊类型',
|
||||
align: "center",
|
||||
dataIndex: 'type'
|
||||
},
|
||||
{
|
||||
title: '作弊内容:XX时间,XX操作;',
|
||||
align: "center",
|
||||
dataIndex: 'content'
|
||||
},
|
||||
];
|
||||
|
||||
//查询数据
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
];
|
||||
|
||||
//表单数据
|
||||
export const formSchema: FormSchema[] = [
|
||||
{
|
||||
label: 'wjx_djxx表id',
|
||||
field: 'djxxId',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '学生姓名',
|
||||
field: 'studentName',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '问卷编号(提交问卷、查询问卷会用到)',
|
||||
field: 'vid',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '答卷编号',
|
||||
field: 'jid',
|
||||
component: 'Input',
|
||||
},
|
||||
// // 作弊类型 1、退出全屏2、切屏3、考试超时4、开始答题
|
||||
{
|
||||
label: '作弊类型',
|
||||
field: 'type',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
label: '作弊内容:XX时间,XX操作;',
|
||||
field: 'content',
|
||||
component: 'InputTextArea',
|
||||
},
|
||||
// TODO 主键隐藏字段,目前写死为ID
|
||||
{
|
||||
label: '',
|
||||
field: 'id',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
];
|
|
@ -0,0 +1,215 @@
|
|||
<template>
|
||||
<div>
|
||||
<!--查询区域-->
|
||||
<div class="jeecg-basic-table-form-container">
|
||||
<a-form @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-row :gutter="24">
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="batchHandleDelete">
|
||||
<Icon icon="ant-design:delete-outlined"></Icon>
|
||||
删除
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
|
||||
</template>
|
||||
<!--字段回显插槽-->
|
||||
<template #htmlSlot="{text}">
|
||||
<div v-html="text"></div>
|
||||
</template>
|
||||
<!--省市区字段回显插槽-->
|
||||
<!--<template #pcaSlot="{text}">
|
||||
{{ getAreaTextByCode(text) }}
|
||||
</template>-->
|
||||
<template #fileSlot="{text}">
|
||||
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
|
||||
<a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<WjxDjxxFzbtjModal ref="registerModal" @success="handleSuccess"></WjxDjxxFzbtjModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="wjxDjxxFzbtj-wjxDjxxFzbtj" setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { columns } from './WjxDjxxFzbtj.data';
|
||||
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './WjxDjxxFzbtj.api';
|
||||
import { downloadFile } from '/@/utils/common/renderUtils';
|
||||
import WjxDjxxFzbtjModal from './components/WjxDjxxFzbtjModal.vue'
|
||||
|
||||
const queryParam = ref<any>({});
|
||||
const toggleSearchStatus = ref<boolean>(false);
|
||||
const registerModal = ref();
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
title: 'wjx_djxx_fzbtj',
|
||||
api: list,
|
||||
columns,
|
||||
canResize:false,
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
params.column = '',params.order = '';//新生成的默认不带排序
|
||||
return Object.assign(params, queryParam.value);
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
name: "wjx_djxx_fzbtj",
|
||||
url: getExportUrl,
|
||||
},
|
||||
importConfig: {
|
||||
url: getImportUrl,
|
||||
success: handleSuccess
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
const labelCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 7 },
|
||||
});
|
||||
const wrapperCol = reactive({
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
});
|
||||
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
function handleAdd() {
|
||||
registerModal.value.disableSubmit = false;
|
||||
registerModal.value.add();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
function handleEdit(record: Recordable) {
|
||||
registerModal.value.disableSubmit = false;
|
||||
registerModal.value.edit(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
function handleDetail(record: Recordable) {
|
||||
registerModal.value.disableSubmit = true;
|
||||
registerModal.value.edit(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
await deleteOne({ id: record.id }, handleSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
async function batchHandleDelete() {
|
||||
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
(selectedRowKeys.value = []) && reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
}, {
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function searchQuery() {
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function searchReset() {
|
||||
queryParam.value = {};
|
||||
selectedRowKeys.value = [];
|
||||
//刷新数据
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.jeecg-basic-table-form-container {
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust{
|
||||
width: calc(50% - 15px);
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust{
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,157 @@
|
|||
<template>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="wjx_djxx表id" v-bind="validateInfos.djxxId">
|
||||
<a-input v-model:value="formData.djxxId" placeholder="请输入wjx_djxx表id" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="学生姓名" v-bind="validateInfos.studentName">
|
||||
<a-input v-model:value="formData.studentName" placeholder="请输入学生姓名" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="问卷编号(提交问卷、查询问卷会用到)" v-bind="validateInfos.vid">
|
||||
<a-input v-model:value="formData.vid" placeholder="请输入问卷编号(提交问卷、查询问卷会用到)" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="答卷编号" v-bind="validateInfos.jid">
|
||||
<a-input v-model:value="formData.jid" placeholder="请输入答卷编号" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="作弊类型" v-bind="validateInfos.type">
|
||||
<a-input-number v-model:value="formData.type" placeholder="请输入作弊类型" style="width: 100%" :disabled="disabled"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="作弊内容:XX时间,XX操作;" v-bind="validateInfos.content">
|
||||
<a-textarea v-model:value="formData.content" rows="4" placeholder="请输入作弊内容:XX时间,XX操作;" :disabled="disabled"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { getValueType } from '/@/utils';
|
||||
import { saveOrUpdate } from '../WjxDjxxFzbtj.api';
|
||||
import { Form } from 'ant-design-vue';
|
||||
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
formData: { type: Object, default: ()=>{} },
|
||||
formBpm: { type: Boolean, default: true }
|
||||
});
|
||||
const formRef = ref();
|
||||
const useForm = Form.useForm;
|
||||
const emit = defineEmits(['register', 'ok']);
|
||||
const formData = reactive<Record<string, any>>({
|
||||
id: '',
|
||||
djxxId: '',
|
||||
studentName: '',
|
||||
vid: '',
|
||||
jid: '',
|
||||
type: undefined,
|
||||
content: '',
|
||||
});
|
||||
const { createMessage } = useMessage();
|
||||
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
|
||||
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
//表单验证
|
||||
const validatorRules = {
|
||||
};
|
||||
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: true });
|
||||
|
||||
// 表单禁用
|
||||
const disabled = computed(()=>{
|
||||
if(props.formBpm === true){
|
||||
if(props.formData.disabled === false){
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return props.formDisabled;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
function add() {
|
||||
edit({});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
function edit(record) {
|
||||
nextTick(() => {
|
||||
resetFields();
|
||||
//赋值
|
||||
Object.assign(formData, record);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交数据
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
let model = formData;
|
||||
if (model.id) {
|
||||
isUpdate.value = true;
|
||||
}
|
||||
//循环数据
|
||||
for (let data in model) {
|
||||
//如果该数据是数组并且是字符串类型
|
||||
if (model[data] instanceof Array) {
|
||||
let valueType = getValueType(formRef.value.getProps, data);
|
||||
//如果是字符串类型的需要变成以逗号分割的字符串
|
||||
if (valueType === 'string') {
|
||||
model[data] = model[data].join(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
await saveOrUpdate(model, isUpdate.value)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
createMessage.success(res.message);
|
||||
emit('ok');
|
||||
} else {
|
||||
createMessage.warning(res.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
confirmLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
defineExpose({
|
||||
add,
|
||||
edit,
|
||||
submitForm,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
min-height: 500px !important;
|
||||
overflow-y: auto;
|
||||
padding: 24px 24px 24px 24px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<WjxDjxxFzbtjForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></WjxDjxxFzbtjForm>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineExpose } from 'vue';
|
||||
import WjxDjxxFzbtjForm from './WjxDjxxFzbtjForm.vue'
|
||||
|
||||
const title = ref<string>('');
|
||||
const width = ref<number>(800);
|
||||
const visible = ref<boolean>(false);
|
||||
const disableSubmit = ref<boolean>(false);
|
||||
const registerForm = ref();
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
function add() {
|
||||
title.value = '新增';
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
registerForm.value.add();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param record
|
||||
*/
|
||||
function edit(record) {
|
||||
title.value = disableSubmit.value ? '详情' : '编辑';
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
registerForm.value.edit(record);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定按钮点击事件
|
||||
*/
|
||||
function handleOk() {
|
||||
registerForm.value.submitForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* form保存回调事件
|
||||
*/
|
||||
function submitCallback() {
|
||||
handleCancel();
|
||||
emit('success');
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消按钮回调事件
|
||||
*/
|
||||
function handleCancel() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
add,
|
||||
edit,
|
||||
disableSubmit,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/**隐藏样式-modal确定按钮 */
|
||||
.jee-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
|
@ -5,34 +5,66 @@
|
|||
<!-- 页头 -->
|
||||
<headerPage />
|
||||
<!-- 主体部分 -->
|
||||
<a-layout-content>
|
||||
<a-layout-content v-show="loadTestInfo" class="ts_container">
|
||||
<div>
|
||||
<strong class="ts_title" style="font-size: 17px;"><a-spin />正在加载考试信息,请稍等。</strong>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
<a-layout-content v-show="!loadTestInfo && !showContent" class="ts_container">
|
||||
<div>
|
||||
<strong class="ts_title" style="font-size: 17px;color:#8B0000;">考试须知</strong>
|
||||
<ol class="ts_rules-list">
|
||||
<li><strong>1、保持全屏模式:</strong>在考试过程中,请始终保持全屏模式。避免使用ESC键或点击出现在屏幕顶部的退出全屏按钮,以防意外退出考试界面。</li>
|
||||
<li><strong>2、禁止切换屏幕:</strong>考试期间,请勿进行任何切屏操作,以确保考试的连续性和公正性。</li>
|
||||
<li v-show="zdsx && !finishTime"><strong>
|
||||
3、</strong><strong style="color: red;">作答时限:
|
||||
</strong>点击开始测验后开始计时,本次作答时限为:<span style="color: red;">{{ zdsx }}分钟</span>。
|
||||
</li>
|
||||
<li v-show="zdsx && !!finishTime"><strong>
|
||||
3、</strong><strong style="color: red;">作答时限:
|
||||
</strong>本次测验于:<span style="color: red;">{{ finishTime }}</span><span>结束。</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<a-button type="primary" @click="fsFUNC()" class="ts_center-button">{{ testingTips }}</a-button>
|
||||
</a-layout-content>
|
||||
<a-layout-content v-show="!loadTestInfo && showContent">
|
||||
<a-spin :spinning="confirmLoading" v-if="showType == 1">
|
||||
<a-row style="min-height: calc(80vh); background: #fcfcfc">
|
||||
<a-col :span="24" style="overflow-y: scroll;width: 100%; word-wrap: break-word; white-space: normal;">
|
||||
<div style="text-align: center; width: 100%; font-weight: bold; font-size: 20px;margin-top: 50px;margin-bottom: 40px;"> {{ title }}</div>
|
||||
<div style="text-align: center; width: 100%; font-weight: bold; font-size: 20px;color:red;" v-if="sfsxs"> 您不是此测验的学生,不能进行提交</div>
|
||||
|
||||
<div
|
||||
style="text-align: center; width: 100%; font-weight: bold; font-size: 20px;margin-top: 50px;margin-bottom: 40px;">
|
||||
{{ title }}</div>
|
||||
<div style="text-align: center; width: 100%; font-weight: bold; font-size: 20px;color:red;"
|
||||
v-if="sfsxs"> 您不是此测验的学生,不能进行提交</div>
|
||||
|
||||
<div class="con-class" v-html="content"></div>
|
||||
<!-- 题干信息 -->
|
||||
<div style="width: 100%; padding: 0 10px; margin: 0 auto" v-for="(item, index) in tiganData" :key="index">
|
||||
<div style="width: 100%; padding: 0 10px; margin: 0 auto" v-for="(item, index) in tiganData"
|
||||
:key="index">
|
||||
<!-- 单选题 -->
|
||||
<div style="width: 100%" v-if="(item.wjType == 3 || item.wjType == '3') && item.wjSubtype==null">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">单选题</div>
|
||||
<div style="width: 100%" v-if="(item.wjType == 3 || item.wjType == '3') && item.wjSubtype == null">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">
|
||||
单选题</div>
|
||||
<a-card>
|
||||
<template #title>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span
|
||||
v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
<div v-if="item.picPath">
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled :maxCount="item.picPath.split(',').length" :buttonVisible="true" ></j-upload>
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled
|
||||
:maxCount="item.picPath.split(',').length" :buttonVisible="true"></j-upload>
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</div>
|
||||
</template>
|
||||
<!-- <template #extra>
|
||||
<span style="margin-left: 40px" v-if="isShow"
|
||||
>题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</span
|
||||
>
|
||||
</template> -->
|
||||
<a-radio-group v-model:value="item.itemSelected" style="width: 100%" size="default" :disabled="disabled">
|
||||
<a-radio-group v-model:value="item.itemSelected" style="width: 100%" size="default"
|
||||
:disabled="disabled">
|
||||
<div style="width: 100%" v-for="(tmxx, index) in item.wjxWjxxTmxxList" :key="index">
|
||||
<a-radio :value="tmxx.itemIndex + ``" style="width: 100%; margin-bottom: 5px">
|
||||
<span v-html="tmxx.itemTitle" style="width: 80%; font-size: 16px"></span>
|
||||
|
@ -43,17 +75,22 @@
|
|||
</div>
|
||||
<!-- 判断题 -->
|
||||
<div style="width: 100%" v-else-if="item.wjType == 3 && item.wjSubtype == 305">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">判断题</div>
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">
|
||||
判断题</div>
|
||||
<a-card>
|
||||
<template #title>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span
|
||||
v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
<div v-if="item.picPath">
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled :maxCount="item.picPath.split(',').length" :buttonVisible="true" ></j-upload>
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled
|
||||
:maxCount="item.picPath.split(',').length" :buttonVisible="true"></j-upload>
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</div>
|
||||
</template>
|
||||
<a-radio-group v-model:value="item.itemSelected" style="width: 100%" size="default" :disabled="disabled">
|
||||
<a-radio-group v-model:value="item.itemSelected" style="width: 100%" size="default"
|
||||
:disabled="disabled">
|
||||
<div style="width: 100%" v-for="(tmxx, index) in item.wjxWjxxTmxxList" :key="index">
|
||||
<a-radio :value="tmxx.itemIndex + ``" style="width: 100%; margin-bottom: 5px">
|
||||
<span v-html="tmxx.itemTitle" style="width: 80%; font-size: 16px"></span>
|
||||
|
@ -64,17 +101,22 @@
|
|||
</div>
|
||||
<!-- 多选题 -->
|
||||
<div style="width: 100%" v-else-if="item.wjType == 4">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">多选题</div>
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">
|
||||
多选题</div>
|
||||
<a-card>
|
||||
<template #title>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span
|
||||
v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
<div v-if="item.picPath">
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled :maxCount="item.picPath.split(',').length" :buttonVisible="true" ></j-upload>
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled
|
||||
:maxCount="item.picPath.split(',').length" :buttonVisible="true"></j-upload>
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</div>
|
||||
</template>
|
||||
<a-checkbox-group v-model:value="item.itemSelected" style="width: 100%" size="default" :disabled="disabled">
|
||||
<a-checkbox-group v-model:value="item.itemSelected" style="width: 100%" size="default"
|
||||
:disabled="disabled">
|
||||
<a-row>
|
||||
<a-col :span="24" v-for="(tmxx, index) in item.wjxWjxxTmxxList" :key="index">
|
||||
<a-checkbox :value="tmxx.itemIndex" style="width: 100%; margin-bottom: 5px">
|
||||
|
@ -86,115 +128,102 @@
|
|||
</a-card>
|
||||
</div>
|
||||
<!-- 填空题 -->
|
||||
<div style="width: 100%" v-else-if="item.wjType == 5 && item.wjSubtype==null">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">填空题</div>
|
||||
<div style="width: 100%" v-else-if="item.wjType == 5 && item.wjSubtype == null">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">
|
||||
填空题</div>
|
||||
<a-card>
|
||||
<template #title>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span
|
||||
v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
<div v-if="item.picPath">
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled :maxCount="item.picPath.split(',').length" :buttonVisible="true" ></j-upload>
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled
|
||||
:maxCount="item.picPath.split(',').length" :buttonVisible="true"></j-upload>
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</div>
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-textarea
|
||||
placeholder="请填写答案"
|
||||
v-model:value="item.wjAnswer"
|
||||
style="width: 100%"
|
||||
:auto-size="{ minRows: 2, maxRows: 5 }"
|
||||
:disabled="disabled"
|
||||
/>
|
||||
<a-textarea placeholder="请填写答案" v-model:value="item.wjAnswer" style="width: 100%"
|
||||
:auto-size="{ minRows: 2, maxRows: 5 }" :disabled="disabled" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
<!-- 简答题 -->
|
||||
<div style="width: 100%" v-else-if="item.wjType == 5 && item.wjSubtype == 5">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">简答题</div>
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">
|
||||
简答题</div>
|
||||
<a-card>
|
||||
<template #title>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span
|
||||
v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
<div v-if="item.picPath">
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled :maxCount="item.picPath.split(',').length" :buttonVisible="true" ></j-upload>
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled
|
||||
:maxCount="item.picPath.split(',').length" :buttonVisible="true"></j-upload>
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</div>
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-textarea
|
||||
placeholder="请填写答案"
|
||||
v-model:value="item.wjAnswer"
|
||||
style="width: 100%"
|
||||
:auto-size="{ minRows: 2, maxRows: 5 }"
|
||||
:disabled="disabled"
|
||||
/>
|
||||
<a-textarea placeholder="请填写答案" v-model:value="item.wjAnswer" style="width: 100%"
|
||||
:auto-size="{ minRows: 2, maxRows: 5 }" :disabled="disabled" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
<!-- 文件题 -->
|
||||
<div style="width: 100%" v-else-if="item.wjType == 8">
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">文件题</div>
|
||||
<div style="text-align: left; width: 100%; font-weight: bold; line-height: 80px; font-size: 18px">
|
||||
文件题</div>
|
||||
<a-card>
|
||||
<template #title>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
|
||||
<div style="white-space: pre-wrap; word-wrap: break-word"><span>{{ index + 1 }}、</span><span
|
||||
v-html="item.wjTitle" style="white-space: pre-wrap; word-wrap: break-word"></span></div>
|
||||
<div v-if="item.picPath">
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled :maxCount="item.picPath.split(',').length" :buttonVisible="true" ></j-upload>
|
||||
<j-upload v-model:value="item.picPath" fileType="image" disabled
|
||||
:maxCount="item.picPath.split(',').length" :buttonVisible="true"></j-upload>
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分
|
||||
</div>
|
||||
<div style="text-align: right;">题目分值: <span class="answer-word">{{ item.wjScore }}</span> 分</div>
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
|
||||
<!-- -{{item.picPath.split(',')}}- -->
|
||||
|
||||
<!-- -{{item.picPath.split(',')}}- -->
|
||||
<!-- <JImageUpload v-model:value="item.picPath" disabled></JImageUpload> -->
|
||||
<!-- <j-image-upload v-model:value="item.picPath" :disabled="disabled"></j-image-upload> -->
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<j-upload v-model:value="item.wjAnswer" :max-count="1" :disabled="disabled" accept=".doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.zip,.ppt,.pptx,.rar,.excel" ></j-upload>
|
||||
<j-upload v-model:value="item.wjAnswer" :max-count="1" :disabled="disabled"
|
||||
accept=".doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.zip,.ppt,.pptx,.rar,.excel"></j-upload>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
<div v-else> 无对应类型-{{item.wjType}}-{{item.wjSubtype}}=</div>
|
||||
<div v-else> 无对应类型-{{ item.wjType }}-{{ item.wjSubtype }}=</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="24" style="text-align: center" v-if="!sfsxs">
|
||||
|
||||
|
||||
<a-button type="primary" @click="submitForm">提交</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-spin>
|
||||
<div v-if="showType == 2" style="width: 100%; background: #fff; text-align: center; min-height: 500px">
|
||||
<div style="padding-top: 200px">
|
||||
<img class="work-img-img" src="../../../../assets/images/homework.png" /> <span style="color: #666">您已提交了测验,请勿重复提交!</span
|
||||
><br /><a-button
|
||||
type="primary"
|
||||
@click="
|
||||
() => {
|
||||
router.push({ path: '/site/index' });
|
||||
}
|
||||
"
|
||||
>返回</a-button
|
||||
>
|
||||
<img class="work-img-img" src="../../../../assets/images/homework.png" /> <span
|
||||
style="color: #666">您已提交了测验,请勿重复提交!</span><br /><a-button type="primary" @click="goBack()">返回</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showType == 3" style="width: 100%; text-align: center; min-height: 500px">
|
||||
<div style="padding-top: 200px">
|
||||
<img class="work-img-img" src="../../../../assets/images/homework.png" />
|
||||
<span style="color: #666">提交成功,请返回首页!</span><br /><a-button
|
||||
type="primary"
|
||||
@click="
|
||||
() => {
|
||||
router.push({ path: '/site/index' });
|
||||
}
|
||||
"
|
||||
>返回</a-button
|
||||
>
|
||||
<span style="color: #666">提交成功,请返回首页!</span><br /><a-button type="primary" @click="goBack()">返回</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div v-if="showType == 3" style="width: 100%; text-align: center">
|
||||
|
@ -219,18 +248,21 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" name="wjxWjxx-add" setup>
|
||||
import { ref, nextTick, unref, defineExpose, onMounted } from 'vue';
|
||||
import { ref, nextTick, unref, defineExpose, onMounted, onUnmounted } from 'vue';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { queryWjxWjxxTmxxListByMainId, queryDataById, saveOrUpdate, djtj } from '/@/views/kc/wjxWjxxTmlb/WjxWjxxTmlb.api';
|
||||
import { fzbSaveOrUpdate, getExamTime } from '/@/views/kc/wjxDjxxFzbtj/WjxDjxxFzbtj.api';
|
||||
import headerPage from '/@/views/site/common/header.vue';
|
||||
import footerPage from '/@/views/site/common/footer.vue';
|
||||
import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
|
||||
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
|
||||
|
||||
|
||||
const title = ref<string>('');
|
||||
const content = ref<string>('');
|
||||
const content = ref<string>('');
|
||||
const infoDataRef = ref<string>('');
|
||||
const mainId = ref<string>('');
|
||||
const isShow = ref<boolean>(false);
|
||||
const disabled = ref<boolean>(false);
|
||||
|
@ -249,8 +281,11 @@ const { currentRoute } = useRouter();
|
|||
const router = useRouter();
|
||||
const { query } = unref(currentRoute);
|
||||
const { rwbh, xqxn, type, teano, cytitle, cyid, cyatype, sfzd, sfbs } = query; //获取传递参数
|
||||
|
||||
const it = ref('') //等于fs时代表开启了防作弊模式
|
||||
const zdsx = ref(null) //作答时限
|
||||
const loadTestInfo = ref(true) //获取考试信息loading
|
||||
const sfsxs = ref<boolean>(false);
|
||||
const showContent = ref(false)
|
||||
//初始化
|
||||
function edit(record, isDisabled, type, flag) {
|
||||
console.log('👨👨👦', record, isDisabled, type, flag);
|
||||
|
@ -266,7 +301,6 @@ function edit(record, isDisabled, type, flag) {
|
|||
mainId.value = record.id;
|
||||
if (flag == 'ls') {
|
||||
defHttp.get({ url: '/wjxWjxxTmlb/wjxWjxxTmlb/queryByMainId', params: { id: record.id } }).then((res) => {
|
||||
// console.log(`🚀 ~ defHttp.get ~ res:`, res)
|
||||
let list = res;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let par = list[i];
|
||||
|
@ -279,12 +313,10 @@ function edit(record, isDisabled, type, flag) {
|
|||
}
|
||||
}
|
||||
tiganData.value = res;
|
||||
console.log("🚀 ~ defHttp.get1111 ~ tiganData.value:", tiganData.value)
|
||||
});
|
||||
} else {
|
||||
defHttp.get({ url: '/wjxWjxxTmlb/wjxWjxxTmlb/queryDjByMainId', params: { id: record.id } }).then((res) => {
|
||||
tiganData.value = res;
|
||||
console.log("🚀 ~ defHttp.get2222 ~ tiganData.value:", tiganData.value)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -293,26 +325,25 @@ function edit(record, isDisabled, type, flag) {
|
|||
async function submitForm() {
|
||||
const data = tiganData.value;
|
||||
const values = Object.assign([], data);
|
||||
console.log("🚀 ~ submitForm ~ values:", values)
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
let param = values[i];
|
||||
if (param.wjType == 3 || param.wjType == 4) {
|
||||
if (param.itemSelected == null) {
|
||||
emit('closeLoading');
|
||||
createMessage.warning('第'+(i+1)+'题没有作答,请检查试卷,完成所有作答!');
|
||||
createMessage.warning('第' + (i + 1) + '题没有作答,请检查试卷,完成所有作答!');
|
||||
return;
|
||||
}
|
||||
values[i].itemSelected = param.itemSelected + '';
|
||||
} else if (param.wjType == 5) {
|
||||
if (param.wjAnswer == null || param.wjAnswer == '') {
|
||||
emit('closeLoading');
|
||||
createMessage.warning('第'+(i+1)+'题没有作答,请检查试卷,完成所有作答!');
|
||||
createMessage.warning('第' + (i + 1) + '题没有作答,请检查试卷,完成所有作答!');
|
||||
return;
|
||||
}
|
||||
} else if (param.wjType == 8) {
|
||||
if (param.wjAnswer == null || param.wjAnswer == '') {
|
||||
emit('closeLoading');
|
||||
createMessage.warning('第'+(i+1)+'题没有作答,请检查试卷,完成所有作答!');
|
||||
createMessage.warning('第' + (i + 1) + '题没有作答,请检查试卷,完成所有作答!');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -321,8 +352,28 @@ async function submitForm() {
|
|||
const isUpdate = false;
|
||||
console.log('👨🚒', values);
|
||||
showType.value = 3;
|
||||
|
||||
//超时记录存储
|
||||
if (!!zdsx.value) {
|
||||
let finishDate = new Date(finishTime.value.replace(' ', 'T'));
|
||||
let now = new Date();
|
||||
if (now > finishDate) {
|
||||
//答题超时需要记录
|
||||
fzbSaveOrUpdate(Object.assign({}, { djxxId: infoDataRef.value.id, vid: infoDataRef.value.vid, type: 3 }), false)
|
||||
}
|
||||
}
|
||||
|
||||
//保存成功
|
||||
await djtj(values, isUpdate);
|
||||
|
||||
if (it.value == 'fs') {
|
||||
//防作弊模式最后需要统计总得作弊次数,保存到djxx表中
|
||||
defHttp.post({ url: '/wjxDjxx/upZbcs', data: { id: infoDataRef.value.id, vid: infoDataRef.value.vid, createBy: infoDataRef.value.createBy } })
|
||||
}
|
||||
|
||||
//切换至返回界面
|
||||
showContent.value = true
|
||||
it.value == ''
|
||||
}
|
||||
|
||||
function getCurrentTimeFormat() {
|
||||
|
@ -340,14 +391,116 @@ function getCurrentTimeFormat() {
|
|||
function padZero(num) {
|
||||
return num < 10 ? `0${num}` : `${num}`;
|
||||
}
|
||||
// 防作弊 >>>
|
||||
const zbtj = ref({
|
||||
tcqp: 0,
|
||||
qp: 0
|
||||
})
|
||||
const testingTips = ref('开始测验')
|
||||
const finishTime = ref('')
|
||||
|
||||
const element = document.documentElement;
|
||||
//进入全屏
|
||||
function inFullScreen() {
|
||||
if (element.requestFullscreen) {
|
||||
element.requestFullscreen();
|
||||
} else if (element.mozRequestFullScreen) { // Firefox
|
||||
element.mozRequestFullScreen();
|
||||
} else if (element.webkitRequestFullscreen) { // Chrome, Safari and Opera
|
||||
element.webkitRequestFullscreen();
|
||||
} else if (element.msRequestFullscreen) { // IE/Edge
|
||||
element.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
//退出全屏
|
||||
function outFullScreen() {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) { // Firefox
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera
|
||||
document.webkitExitFullscreen();
|
||||
} else if (document.msExitFullscreen) { // IE/Edge
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
const isFullscreen = ref(false);
|
||||
// 定义处理全屏变化的函数
|
||||
const handleFullscreenChange = () => {
|
||||
isFullscreen.value = !!document.fullscreenElement;
|
||||
if (it.value == 'fs' && !isFullscreen.value) {
|
||||
showContent.value = false
|
||||
testingTips.value = '继续测验'
|
||||
zbtj.value.tcqp += 1
|
||||
fzbSaveOrUpdate(Object.assign({}, { djxxId: infoDataRef.value.id, vid: infoDataRef.value.vid, type: 1 }), false)
|
||||
// alert('防作弊触发')
|
||||
}
|
||||
};
|
||||
|
||||
function recordTime() {
|
||||
//如果有作答时限,点击开始测验时,如果第一次答题则向wjx_djxx_fzbtj中增加开始作答记录
|
||||
if (!!zdsx.value) {
|
||||
fzbSaveOrUpdate(Object.assign({}, { djxxId: infoDataRef.value.id, vid: infoDataRef.value.vid, type: 4, zdsx: zdsx.value, endTime: infoDataRef.value.endTime }), false).then(res => {
|
||||
finishTime.value = res.result.finishTime
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function fsFUNC() {
|
||||
if (it.value && it.value == 'fs') {
|
||||
inFullScreen()
|
||||
showContent.value = true
|
||||
}
|
||||
// else{
|
||||
//如果出现错误也暂时处理为非全屏答题,避免系统原因导致学生无法测验
|
||||
showContent.value = true
|
||||
// }
|
||||
|
||||
recordTime()
|
||||
}
|
||||
|
||||
const isPageVisible = ref(true);
|
||||
// 定义处理页面可见性变化的函数
|
||||
const handleVisibilityChange = () => {
|
||||
isPageVisible.value = !document.hidden;
|
||||
if (it.value == 'fs' && showContent.value && !isPageVisible.value) {
|
||||
zbtj.value.qp += 1
|
||||
fzbSaveOrUpdate(Object.assign({}, { djxxId: infoDataRef.value.id, vid: infoDataRef.value.vid, type: 2 }), false)
|
||||
// alert('防作弊触发')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//移除监听事件
|
||||
function removeListening() {
|
||||
//移除全屏监听事件
|
||||
document.removeEventListener('fullscreenchange', handleFullscreenChange);
|
||||
document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);
|
||||
document.removeEventListener('mozfullscreenchange', handleFullscreenChange);
|
||||
document.removeEventListener('MSFullscreenChange', handleFullscreenChange);
|
||||
//移除切屏监听
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
}
|
||||
// 防作弊 <<<
|
||||
|
||||
function goBack() {
|
||||
removeListening()
|
||||
outFullScreen()
|
||||
router.push({ path: '/site/index' });
|
||||
}
|
||||
|
||||
async function refreshFT() {
|
||||
const finishTimeData = await getExamTime('ktcy:' + infoDataRef.value.vid)
|
||||
finishTime.value = finishTimeData.result
|
||||
}
|
||||
|
||||
// 自动请求并暴露内部方法
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
//获取是否答过题
|
||||
defHttp.get({ url: '/wjxWjxx/wjxWjxx/querySfdtById', params: { id: cyid } }).then((res) => {
|
||||
console.log('🎅', res);
|
||||
var num = res.num;
|
||||
console.log('🧛', num);
|
||||
console.log('🧛', res);
|
||||
if (num && parseInt(num) > 0) {
|
||||
showType.value = 2;
|
||||
} else {
|
||||
|
@ -356,25 +509,58 @@ onMounted(() => {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
defHttp.get({ url: '/wjxWjxx/wjxWjxx/queryById', params: { id: cyid } }).then((res) => {
|
||||
console.log('🎅11111111', res);
|
||||
content.value = res.content
|
||||
|
||||
});
|
||||
//查询本次答题信息,调整防作弊内容
|
||||
{
|
||||
const infoData = await defHttp.get({ url: '/wjxWjxx/wjxWjxx/queryById', params: { id: cyid } })
|
||||
content.value = infoData.contentf
|
||||
infoDataRef.value = infoData
|
||||
await refreshFT()
|
||||
//先给zdsx赋值再调用recordTime()
|
||||
if (!!infoData.zdsx) {
|
||||
zdsx.value = infoData.zdsx
|
||||
}
|
||||
|
||||
if (infoData.fzbms == 'Y') {
|
||||
it.value = 'fs'
|
||||
} else {
|
||||
//未开启防作弊则每次进入都记录一次作答时间
|
||||
recordTime()
|
||||
}
|
||||
//it=='fs'是点击了开始测验按钮进来的,此时需要先让用户主动触发点击才能进入全屏,否则非用户主动行为进入浏览器全屏就会被浏览器阻止
|
||||
if (it.value && it.value == 'fs') {
|
||||
//全屏变化监听
|
||||
document.addEventListener('fullscreenchange', handleFullscreenChange);
|
||||
document.addEventListener('webkitfullscreenchange', handleFullscreenChange); // Safari
|
||||
document.addEventListener('mozfullscreenchange', handleFullscreenChange); // Firefox
|
||||
document.addEventListener('MSFullscreenChange', handleFullscreenChange); // IE/Edge
|
||||
//切屏监听
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
showContent.value = false
|
||||
loadTestInfo.value = false
|
||||
} else {
|
||||
showContent.value = true
|
||||
loadTestInfo.value = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
defHttp.get({ url: '/wjxWjxx/wjxWjxx/getSfxs', params: { id: cyid } }).then((res) => {
|
||||
console.log('🙂', res);
|
||||
var num = res.num;
|
||||
if(num=='1'){
|
||||
if (num == '1') {
|
||||
sfsxs.value = false;
|
||||
}else{
|
||||
} else {
|
||||
sfsxs.value = true;
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 在组件卸载时移除事件监听器
|
||||
onUnmounted(() => {
|
||||
removeListening()
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
edit,
|
||||
submitForm,
|
||||
|
@ -398,7 +584,7 @@ defineExpose({
|
|||
|
||||
|
||||
|
||||
/deep/span.ant-radio + * {
|
||||
/deep/span.ant-radio+* {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -416,7 +602,8 @@ defineExpose({
|
|||
cursor: pointer;
|
||||
width: 80%;
|
||||
}
|
||||
/deep/.ant-checkbox + span {
|
||||
|
||||
/deep/.ant-checkbox+span {
|
||||
padding-right: 8px;
|
||||
padding-left: 8px;
|
||||
width: 100%;
|
||||
|
@ -426,11 +613,13 @@ defineExpose({
|
|||
// font-size: ;
|
||||
// height: 100%;
|
||||
background: #f3f3f4;
|
||||
|
||||
#maxSite {
|
||||
//最大宽度
|
||||
max-width: 1170px;
|
||||
//居中
|
||||
margin: 0 auto;
|
||||
|
||||
.rowGutter {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -440,30 +629,68 @@ defineExpose({
|
|||
color: #fff;
|
||||
background: #1ab394;
|
||||
}
|
||||
|
||||
.ant-layout-footer {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
color: #fff;
|
||||
background: #3ba0e9;
|
||||
}
|
||||
|
||||
.ant-layout-content {
|
||||
min-height: 120px;
|
||||
color: #000;
|
||||
background: #f3f3f4;
|
||||
}
|
||||
|
||||
.dictBox :deep(.ant-select) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.answer-word {
|
||||
color: #ff8710;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.work-img-img {
|
||||
margin: 0 auto;
|
||||
width: 180px;
|
||||
height: 139px;
|
||||
}
|
||||
|
||||
.ts_container {
|
||||
padding: 35px;
|
||||
/* 根据需要调整padding值 */
|
||||
}
|
||||
|
||||
.ts_title {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
/* 可选:根据需要调整间距 */
|
||||
}
|
||||
|
||||
.ts_rules-list {
|
||||
text-align: left;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 80%;
|
||||
/* 让列表占据容器的80%,居中显示 */
|
||||
}
|
||||
|
||||
.ts_rules-list li {
|
||||
text-align: left;
|
||||
margin-left: 20px;
|
||||
/* 根据需要调整缩进 */
|
||||
}
|
||||
|
||||
.ts_center-button {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from "/@/hooks/web/useMessage";
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
|
||||
enum Api {
|
||||
list = '/grab/xxhbbks/getXsxkbList',
|
||||
save='/grab/xxhbbks/add',
|
||||
edit='/grab/xxhbbks/edit',
|
||||
save = '/grab/xxhbbks/add',
|
||||
edit = '/grab/xxhbbks/edit',
|
||||
deleteOne = '/grab/xxhbbks/delete',
|
||||
deleteBatch = '/grab/xxhbbks/deleteBatch',
|
||||
importExcel = '/grab/xxhbbks/importExcel',
|
||||
exportXls = '/grab/xxhbbks/exportXls',
|
||||
getXKRY = '/grab/xxhbbks/getXKRY',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,11 +36,11 @@ export const list = (params) => defHttp.get({ url: Api.list, params });
|
|||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const deleteOne = (params,handleSuccess) => {
|
||||
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
|
||||
export const deleteOne = (params, handleSuccess) => {
|
||||
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
|
@ -54,12 +55,12 @@ export const batchDelete = (params, handleSuccess) => {
|
|||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
|
||||
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存或者更新
|
||||
|
@ -69,4 +70,14 @@ export const batchDelete = (params, handleSuccess) => {
|
|||
export const saveOrUpdate = (params, isUpdate) => {
|
||||
let url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取学课人员
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export const getXKRY = (params) => {
|
||||
return defHttp.post({ url: Api.getXKRY, data: params }, { isTransformResponse: false });
|
||||
};
|
||||
|
||||
|
|
|
@ -328,7 +328,18 @@ function handleDetail(record: Recordable) {
|
|||
}
|
||||
|
||||
//上传作业附件
|
||||
function handleShangchuan(record) {
|
||||
async function handleShangchuan(record) {
|
||||
//小组形式提交作业时 只有组长才能提交作业
|
||||
let stuZyIds = []
|
||||
if(record.xzxstjzy == 'Y'){
|
||||
stuZyIds = await defHttp.post({ url: '/zyInfoStudent/zyInfoStudent/getZyStuId', data: { zyinfoId: record.id, xh: record.stuId } })
|
||||
const own = stuZyIds.filter(stu => stu.id == record.stuId)
|
||||
if(own[0].sfzz == 'N'){
|
||||
createMessage.error('您不是组长,无法提交作业!')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let timestamp = new Date().getTime();
|
||||
let startTimestamp = Date.parse(record.startTime);
|
||||
if (timestamp < startTimestamp) {
|
||||
|
@ -342,7 +353,7 @@ function handleShangchuan(record) {
|
|||
}
|
||||
|
||||
ZyInfoStudentModalPage.value.disableSubmit = false;
|
||||
var param = { id: record.id,stuId:record.stuId, zyfj: record.filePath };
|
||||
var param = { id: record.id, stuId: record.stuId, zyfj: record.filePath, xzxstjzy: record.xzxstjzy,stuZyIds };
|
||||
console.log('------->',param);
|
||||
ZyInfoStudentModalPage.value.edit(param);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ enum Api {
|
|||
deleteBatch = '/zyInfo/zyInfo/deleteBatch',
|
||||
importExcel = '/zyInfo/zyInfo/importExcel',
|
||||
exportXls = '/zyInfo/zyInfo/exportXls',
|
||||
getxzxx = '/zyInfo/zyInfo/getxzxx',
|
||||
saveData = '/zyInfo/zyInfo/saveData',
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,3 +78,19 @@ export const saveOrUpdate = (params, isUpdate) => {
|
|||
let url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取课程下信息
|
||||
* @param params
|
||||
*/
|
||||
export const getxzxx = (params) => {
|
||||
return defHttp.post({ url: Api.getxzxx, params }, { isTransformResponse: false });
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储数据
|
||||
* @param params
|
||||
*/
|
||||
export const saveData = (params) => {
|
||||
return defHttp.post({ url: Api.saveData, params }, { isTransformResponse: false });
|
||||
}
|
|
@ -899,6 +899,7 @@ function handleBohui(record: Recordable) {
|
|||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
defHttp.post({ url: '/zyInfoStudent/zyInfoStudent/editBohui', params: { id: record.id } }).then((res) => {
|
||||
createMessage.success('作业驳回成功!')
|
||||
handleSuccess();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -159,6 +159,17 @@
|
|||
</a-form-item>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="小组形式提交作业" >
|
||||
<a-radio-group v-model:value="zyInfo.xzxstjzy" @change="xztjzyxsFunc(zyInfo.xzxstjzy)" :options="xzxstjzyOptions" :disabled="editDisabled"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="小组信息" >
|
||||
<a-button type="primary" @click="bjxzxxFunc(true)" v-show="!editDisabled" :disabled="zyInfo.xzxstjzy=='N'" >设置小组信息</a-button>
|
||||
<a-button type="primary" @click="bjxzxxFunc(false)" v-show="editDisabled" >查看小组信息</a-button>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
|
@ -479,6 +490,10 @@
|
|||
<a @click="handleFenxiang(item)" class="home-status">
|
||||
<Icon icon="ant-design:share-alt-outlined" />分享
|
||||
</a>
|
||||
<a-divider type="vertical"/>
|
||||
<a @click="ckxzxxFunc(item)" v-if="item.dpynum == 0 && item.ypynum == 0" class="home-status">
|
||||
<Icon icon="fluent:people-team-16-regular" />查看分组
|
||||
</a>
|
||||
<a-divider type="vertical" />
|
||||
<a @click="handleChehui(item)" v-if="item.dpynum == 0 && item.ypynum == 0" class="home-status">
|
||||
<Icon icon="ant-design:import-outlined" />撤回作业
|
||||
|
@ -546,6 +561,7 @@
|
|||
<XxhbbksListModal ref="XxhbbksListModalPage"></XxhbbksListModal>
|
||||
<YyzyListModal ref="YyzyListModalPage" @success="handleCallYinyong"></YyzyListModal>
|
||||
<ZyCyFenxiangListModal ref="ZyCyFenxiangListModalpage"></ZyCyFenxiangListModal>
|
||||
<Xzxx ref="XzxxRef" :studentsQP="queryParam" @saveSuccess="xzxxSaveSuccess"></Xzxx>
|
||||
|
||||
<a-modal v-model:visible="imgvisible" title="图片预览" width="800px" :cancelText="`关闭`"
|
||||
:okButtonProps="{ class: { 'jee-hidden': true } }">
|
||||
|
@ -565,7 +581,7 @@ import { ref, reactive, onMounted, unref , onUnmounted, watchEffect} from 'vue';
|
|||
import { list, deleteOne } from './ZyInfo.api';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
|
||||
import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
|
||||
import { Input, Popover, Pagination, Empty, message } from 'ant-design-vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
@ -597,6 +613,7 @@ import XxhbbksListModal from '/@/views/kc/xxhbbks/XxhbbksListModal.vue';
|
|||
import ZyInfoEditModal from './components/ZyInfoEditModal.vue';
|
||||
import YyzyListModal from '/@/views/zy/zyInfo/YyzyListModal.vue';
|
||||
import ZyCyFenxiangListModal from '/@/views/zy/zyCyFenxiang/ZyCyFenxiangListModal.vue';
|
||||
import Xzxx from './components/Xzxx.vue';
|
||||
import { encryptByBase64 } from '/@/utils/cipher';
|
||||
|
||||
const globSetting = useGlobSetting();
|
||||
|
@ -623,7 +640,7 @@ const qmkszb = ref<number>(0);
|
|||
const ktcyzb = ref<number>(0);
|
||||
|
||||
const zycsDisabled = ref<boolean>(false);
|
||||
const zyInfo = ref<any>({});
|
||||
const zyInfo = ref<any>({xzxstjzy:'N'});
|
||||
const formRef = ref();
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
const zyyqShow = ref<boolean>(false);
|
||||
|
@ -652,6 +669,7 @@ const registerDetialModal = ref();
|
|||
const registerPiyueModal = ref();
|
||||
const YyzyListModalPage = ref();
|
||||
const ZyCyFenxiangListModalpage = ref();
|
||||
const XzxxRef = ref()
|
||||
const pdfUrl = ref('/downPath/ylhpsf.pdf');
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
||||
|
@ -693,7 +711,10 @@ const disabledDate = (current: Dayjs) => {
|
|||
return current && current < dayjs().subtract(1, 'days').endOf('day');
|
||||
};
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const xzxstjzyOptions = ref([
|
||||
{ label: '关闭', value: 'N' },
|
||||
{ label: '开启', value: 'Y' },
|
||||
])
|
||||
//引用作业
|
||||
function handleYyzy() {
|
||||
var params = { xqxn, rwbh };
|
||||
|
@ -710,7 +731,7 @@ function handleCallYinyong(record) {
|
|||
record.id = zyid;
|
||||
record.sort = zysort;
|
||||
record.zyLeixing = '0'; //作业类型,课程作业
|
||||
zyInfo.value = record;
|
||||
setZyInfo(record)
|
||||
zyInfo.value.createBy = createBy
|
||||
zyInfo.value.rwbh = rwbh
|
||||
zyInfo.value.zyStatus = "0"
|
||||
|
@ -870,6 +891,7 @@ function searchQueryZyxq() {
|
|||
|
||||
// queryParam.value.mainId = zyInfo.value.id;
|
||||
queryParam.value.queryType = queryType.value;
|
||||
console.log('queryParam.value',queryParam.value)
|
||||
reload();
|
||||
}
|
||||
|
||||
|
@ -937,17 +959,20 @@ function yulanFile(record) {
|
|||
}
|
||||
}
|
||||
//驳回
|
||||
function handleBohui(record: Recordable) {
|
||||
async function handleBohui(record: Recordable) {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '驳回',
|
||||
content: '您确定驳回此作业吗,驳回后需要学生重新提交?',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
defHttp.post({ url: '/zyInfoStudent/zyInfoStudent/editBohui', params: { id: record.id } }).then((res) => {
|
||||
handleSuccess();
|
||||
});
|
||||
onOk: async () => {
|
||||
let stuZyIds = await defHttp.post({ url: '/zyInfoStudent/zyInfoStudent/getZyStuIdById', data: { zyinfoId: record.mainId, xh: record.createBy } })
|
||||
stuZyIds.forEach(async stu => {
|
||||
await defHttp.post({ url: '/zyInfoStudent/zyInfoStudent/editBohui', params: { id: stu.id } })
|
||||
})
|
||||
createMessage.success('作业驳回成功!')
|
||||
handleSuccess();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -1171,7 +1196,7 @@ function handlePfbzShow(type) {
|
|||
}
|
||||
//尚未布置作业题目及具体要求
|
||||
function handleSzzynr(record) {
|
||||
zyInfo.value = record;
|
||||
setZyInfo(record)
|
||||
dataKhnr.value = [];
|
||||
handleShowType(2);
|
||||
}
|
||||
|
@ -1367,6 +1392,12 @@ async function submitForm() {
|
|||
var sfcc = model.sfcc;
|
||||
console.log('🚶♂️', model);
|
||||
if (sfcc == '1') {
|
||||
var xzxstjzy = model.xzxstjzy
|
||||
if(xzxstjzy == 'Y'){
|
||||
createMessage.warning('由于设置了小组形式提交作业,因此无法开启查重功能!');
|
||||
confirmLoading.value = false;
|
||||
return;
|
||||
}
|
||||
//开启查重再进行验证,否则不进行验证
|
||||
if (wwtgl) {
|
||||
if ((wwcc == false && xncc == false && nwcc == false && aigccc == false) || (!wwcc && !xncc && !nwcc && !aigccc)) {
|
||||
|
@ -1620,7 +1651,7 @@ function handleEdit(record, type) {
|
|||
record.xssfck = '1';
|
||||
}
|
||||
editDisabled.value = type;
|
||||
zyInfo.value = record;
|
||||
setZyInfo(record)
|
||||
console.log('👨👦', zyInfo.value);
|
||||
if (zyInfo.value.xncc == 'false') {
|
||||
zyInfo.value.xncc = null;
|
||||
|
@ -1644,6 +1675,11 @@ function handleEdit(record, type) {
|
|||
handleShowType(2);
|
||||
}
|
||||
|
||||
function setZyInfo(record){
|
||||
zyInfo.value = record;
|
||||
if(!zyInfo.value.xzxstjzy)zyInfo.value.xzxstjzy = 'N'
|
||||
}
|
||||
|
||||
function handleBjzy(record) {
|
||||
registerEditModal.value.disableSubmit = false;
|
||||
registerEditModal.value.edit(record);
|
||||
|
@ -1686,7 +1722,7 @@ function handleZyxx(record, type) {
|
|||
}
|
||||
}
|
||||
|
||||
zyInfo.value = record;
|
||||
setZyInfo(record)
|
||||
handleShowType(3);
|
||||
queryType.value = type;
|
||||
rowSelection.value = [];
|
||||
|
@ -1821,6 +1857,27 @@ function handlePageChange(record) {
|
|||
reloadZy();
|
||||
}
|
||||
|
||||
//编辑小组信息
|
||||
function bjxzxxFunc(isEdit){
|
||||
XzxxRef.value.showModal(zyInfo.value,tableData.value,isEdit)
|
||||
}
|
||||
|
||||
function ckxzxxFunc(item){
|
||||
XzxxRef.value.showModal(item,tableData.value,false)
|
||||
}
|
||||
|
||||
//小组形式提交作业选项变更
|
||||
function xztjzyxsFunc(val){
|
||||
if(val == 'Y') createMessage.warning('开启小组形式提交作业后,将无法使用查重功能!');
|
||||
}
|
||||
|
||||
const xzxxSaveSuccess = (id,data) => {
|
||||
tableData.value.forEach(item => {
|
||||
if(item.id == id) item.xzrs = data.rs
|
||||
});
|
||||
// createMessage.success('保存成功!')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
searchQuery();
|
||||
});
|
||||
|
|
|
@ -182,6 +182,16 @@
|
|||
</a-form-item>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="小组形式提交作业" >
|
||||
<a-radio-group v-model:value="zyInfo.xzxstjzy" @change="xztjzyxsFunc(zyInfo.xzxstjzy)" :options="xzxstjzyOptions" :disabled="true"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="小组信息" >
|
||||
<a-button type="primary" @click="bjxzxxFunc(false)" >查看小组信息</a-button>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
|
@ -530,6 +540,10 @@
|
|||
<a @click="handleFenxiang(item)" class="home-status"><Icon icon="ant-design:share-alt-outlined" />分享</a> -->
|
||||
<!-- <a-divider type="vertical" />
|
||||
<a @click="handleChehui(item)" v-if="item.dpynum == 0 && item.ypynum == 0" class="home-status"><Icon icon="ant-design:import-outlined" />撤回作业</a> -->
|
||||
<a-divider type="vertical"/>
|
||||
<a @click="ckxzxxFunc(item)" v-if="item.ytjnum <= 0" class="home-status">
|
||||
<Icon icon="fluent:people-team-16-regular" />查看分组
|
||||
</a>
|
||||
<a-divider type="vertical" />
|
||||
<a @click="handleZyxx(item, '')" class="home-status"><Icon icon="ant-design:file-done-outlined" />查看作业</a>
|
||||
<!-- <a-divider type="vertical" v-if="item.dpynum == 0 && item.ypynum == 0"/>
|
||||
|
@ -585,6 +599,7 @@
|
|||
<XxhbbksListModal ref="XxhbbksListModalPage"></XxhbbksListModal>
|
||||
<YyzyListModal ref="YyzyListModalPage" @success="handleCallYinyong"></YyzyListModal>
|
||||
<ZyCyFenxiangListModal ref="ZyCyFenxiangListModalpage"></ZyCyFenxiangListModal>
|
||||
<Xzxx ref="XzxxRef" :studentsQP="queryParam" ></Xzxx>
|
||||
|
||||
<a-modal v-model:visible="imgvisible" title="图片预览" width="800px" :cancelText="`关闭`" :okButtonProps="{ class: { 'jee-hidden': true } }">
|
||||
<div style="padding: 10px 20px">
|
||||
|
@ -636,6 +651,7 @@ import ZyInfoEditModal from './components/ZyInfoEditModal.vue';
|
|||
import YyzyListModal from '/@/views/zy/zyInfo/YyzyListModal.vue';
|
||||
import ZyCyFenxiangListModal from '/@/views/zy/zyCyFenxiang/ZyCyFenxiangListModal.vue';
|
||||
import { encryptByBase64 } from '/@/utils/cipher';
|
||||
import Xzxx from './components/Xzxx.vue';
|
||||
|
||||
const globSetting = useGlobSetting();
|
||||
const baseApiUrl = globSetting.domainUrl;
|
||||
|
@ -691,6 +707,11 @@ const registerPiyueModal = ref();
|
|||
const YyzyListModalPage = ref();
|
||||
const ZyCyFenxiangListModalpage = ref();
|
||||
const pdfUrl = ref('/downPath/ylhpsf.pdf');
|
||||
const XzxxRef = ref()
|
||||
const xzxstjzyOptions = ref([
|
||||
{ label: '关闭', value: 'N' },
|
||||
{ label: '开启', value: 'Y' },
|
||||
])
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
|
@ -1807,6 +1828,10 @@ function handleZySuccess(zyid) {
|
|||
defHttp.get({ url: '/zyInfo/zyInfo/sendZyWechat', params: { id: zyid } }).then((res) => {});
|
||||
}
|
||||
|
||||
function ckxzxxFunc(item){
|
||||
XzxxRef.value.showModal(item,tableData.value,false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
|
@ -1854,6 +1879,11 @@ function reloadZy() {
|
|||
});
|
||||
}
|
||||
|
||||
//编辑小组信息
|
||||
function bjxzxxFunc(isEdit){
|
||||
XzxxRef.value.showModal(zyInfo.value,tableData.value,false)
|
||||
}
|
||||
|
||||
function handlePageChange(record) {
|
||||
current.value = record;
|
||||
reloadZy();
|
||||
|
|
|
@ -0,0 +1,715 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- 学生分配模态框 -->
|
||||
<a-modal v-model:visible="open" title="配置小组信息" :style="{ height: '85vh' }" width="80%" :okText="isEdit ? '保存' : '确定'"
|
||||
:cancelText="`关闭`" @ok="handleOk" :maskClosable="false">
|
||||
<a-row style="height: 20%; overflow-y: auto;" v-show="isEdit">
|
||||
<a-col :span="6" style="padding-right: 16px;height: 100%;">
|
||||
<!-- 筛选条件 -->
|
||||
<a-input-search v-model:value="searchQuery" placeholder="请输入人名或学号进行筛选"
|
||||
style="margin-bottom: 16px; position: sticky; top: 0; background-color: white; z-index: 10;" />
|
||||
</a-col>
|
||||
<a-col :span="18" style="border-left: 1px solid rgb(240,240,240); padding-left: 16px;height: 100%;">
|
||||
<span style="font-weight: 700;margin-top: 20px;">
|
||||
<span style="color: red;">说明:</span>1.先设置小组人数; 2.点击自动分组可根据小组人数进行自动划分; 3.若需要手动分组直接在左侧人员展示处进行手动划分;
|
||||
<span style="color: red;">4.分组后需要点击确定按钮,否则会分组失败需要重新分组。</span>
|
||||
</span>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="height: 80%; overflow-y: auto;">
|
||||
<!-- 左侧:未分配的学生列表 -->
|
||||
<a-col :span="6" style="padding: 5px 20px;height: 70vh;">
|
||||
<a-list item-layout="horizontal"
|
||||
style="max-height: 100%; overflow-y: auto;padding-left: 15px;padding-right: 15px;">
|
||||
<a-list-item v-for="student in filteredUnallocatedStudents" :key="student.xh">
|
||||
<a-list-item-meta :title="`${student.xm}(${student.xh})`" />
|
||||
<template #actions>
|
||||
<a-button v-show="isEdit" type="primary" size="small" @click="assignStudent(student)">分配</a-button>
|
||||
</template>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-col>
|
||||
<!-- 右侧:已分配的小组卡片 -->
|
||||
<a-col :span="18" style="border-left: 1px solid rgb(240,240,240); padding: 10px;height: 65vh;">
|
||||
<a-row
|
||||
style="margin-bottom: 16px; position: sticky; top: 0; background-color: white; z-index: 10;padding:10px;">
|
||||
<a-col :span="4" style="display: flex; align-items: center;">
|
||||
<div>
|
||||
<span style="font-size: 17px;">小组人数:</span>
|
||||
<span style="font-size: 17px;" v-show="!!allocatedData.rs">{{ allocatedData.rs }}人</span>
|
||||
<span style="font-size: 17px;color:red;" v-show="!allocatedData.rs">未设置!</span>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="20">
|
||||
<a-button v-show="isEdit" :type="!allocatedData.rs ? 'danger' : 'primary'" @click="setGroupSize()"
|
||||
style="margin-left: 5px;">设置人数</a-button>
|
||||
<a-button v-show="isEdit" type="primary" @click="autoAssignGroups()"
|
||||
style="margin-left: 5px;">自动分组</a-button>
|
||||
<a-button v-show="isEdit" type="primary" @click="resetGroups()" style="margin-left: 5px;">重置分组</a-button>
|
||||
<a-button v-show="isEdit" type="primary" @click="quotationManager()"
|
||||
style="margin-left: 5px;">引用分组</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<p v-if="!hasAllocatedData">未分配数据</p>
|
||||
<a-row :gutter="[16, 16]" style="max-height: 100%; overflow-y: auto;">
|
||||
<a-col :span="8" v-for="group in sortedAllocatedGroups" :key="group.sort">
|
||||
<a-card>
|
||||
<template #title>
|
||||
<span style="flex-grow: 1;">
|
||||
<!-- 现有的小组信息 -->
|
||||
<span v-show="allocatedData.rs - group.students.length > 0">
|
||||
{{ group.xzmc }} (<span style="color: red;">还差{{ allocatedData.rs - group.students.length
|
||||
}}人</span>) - 排序:{{ group.sort }}号
|
||||
</span>
|
||||
<span v-show="allocatedData.rs - group.students.length == 0">{{ group.xzmc }}
|
||||
(<span style="color: green;">已满员</span>) - 排序:{{ group.sort }}号
|
||||
</span>
|
||||
<span v-show="allocatedData.rs - group.students.length < 0">
|
||||
{{ group.xzmc }} (<span style="color: red;">超员{{ Math.abs(allocatedData.rs -
|
||||
group.students.length
|
||||
) }}人</span>) -
|
||||
排序:{{ group.sort }}号
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<span>组长:</span>
|
||||
<span v-if="hasLeader(group)" style="color:green">{{ getLeaderName(group) }}</span>
|
||||
<a-button v-show="isEdit" v-if="hasLeader(group)" type="default" size="small"
|
||||
style="margin-left: 5px;" @click="removeLeader(group)">移除</a-button>
|
||||
<span v-if="!hasLeader(group)" style="color: red;">未设置组长</span>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="margin-top: 3px;">
|
||||
<a-col :span="12">组员:</a-col>
|
||||
</a-row>
|
||||
<a-row v-for="member in group.students.filter(member => member.sfzz !== 'Y')" :key="member.xh"
|
||||
style="margin-top: 3px;">
|
||||
<a-col :span="24">{{ member.xm }}
|
||||
<a-button v-show="isEdit" type="default" size="small" @click="removeFromGroup(member)">移除</a-button>
|
||||
<a-button v-show="isEdit" type="default" size="small" @click="promotionTeamLeader(member)"
|
||||
style="margin-left: 5px;">改为组长</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="margin-top: 10px;border-top:1px solid rgb(240, 240, 240);padding-top: 10px;">
|
||||
<a-col :span="24">
|
||||
<a-button v-show="isEdit" type="default" size="small" @click="editGroup(group)">编辑</a-button>
|
||||
<a-button v-show="isEdit" type="default" size="small" @click="dissolveGroup(group)"
|
||||
style="margin-left: 5px;">解散</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-modal>
|
||||
|
||||
<!-- 分配学生对话框 -->
|
||||
<a-modal v-model:visible="assignVisible" title="选择小组" @ok="handleAssign" @cancel="assignVisible = false">
|
||||
<a-row style="margin-top: 10px;">
|
||||
<a-col :push="1" :span="22">
|
||||
<a-steps :current="currentStep" size="small">
|
||||
<a-step title="选择分配方式" />
|
||||
<a-step title="填写详细信息" />
|
||||
</a-steps>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="padding: 20px;">
|
||||
<a-col :span="24">
|
||||
<span style="color: green;">当前学生:{{ selectedStudent.xm }}({{ selectedStudent.xh }})</span>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<!-- 第一步:选择分配方式 -->
|
||||
<div v-show="currentStep === 0">
|
||||
<a-row style="padding: 10px 25px;">
|
||||
<a-col :span="24">
|
||||
<a-radio-group v-model:value="form.assignType" @change="nextStep">
|
||||
<a-radio value="new">创建新小组</a-radio>
|
||||
<a-radio value="existing">分配至已有小组</a-radio>
|
||||
</a-radio-group>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
||||
<!-- 第二步:填写详细信息 -->
|
||||
<div v-show="currentStep !== 0">
|
||||
<a-form :model="form" layout="vertical">
|
||||
<template v-if="form.assignType === 'new'">
|
||||
<a-row :gutter="[16, 16]" style="padding-top: 10px;padding-left: 25px;padding-right: 25px;">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="小组名称">
|
||||
<a-input v-model:value="form.newGroupName" placeholder="请输入小组名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="小组排序">
|
||||
<a-input-number v-model:value="form.newGroupSort" placeholder="请输入排序值" :min="1" :precision="0"
|
||||
:step="1" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="padding: 0px 25px;">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="是否设置为组长">
|
||||
<a-switch v-model:checked="form.isLeader" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-row :gutter="[16, 16]" style="padding-top: 10px;padding-left: 25px;padding-right: 25px;">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="选择小组">
|
||||
<a-select v-model:value="form.existingGroupId" placeholder="请选择小组">
|
||||
<!-- :disabled="isGroupFull(group)" -->
|
||||
<a-select-option v-for="(group, index) in allocatedData.allocated" :key="group.id"
|
||||
:value="group.id">
|
||||
{{ group.xzmc }} (<span v-show="isGroupFull(group)" style="color: red;">已满员</span><span
|
||||
v-show="!isGroupFull(group)">有空位</span> )
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row style="padding: 0px 25px;">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="是否设置为组长">
|
||||
<a-switch v-model:checked="form.isLeader" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 编辑小组信息对话框 -->
|
||||
<a-modal v-model:visible="editModalVisible" title="编辑小组信息" @ok="saveEdit" @cancel="editModalVisible = false">
|
||||
<a-form :model="editingGroup" layout="vertical">
|
||||
<a-row :gutter="[16, 16]" style="padding:20px;">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="小组名称">
|
||||
<a-input v-model:value="editingGroup.xzmc" placeholder="请输入小组名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="小组排序">
|
||||
<a-input-number v-model:value="editingGroup.sort" placeholder="请输入排序值" :min="1" :precision="0"
|
||||
:step="1" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 设置小组人数对话框 -->
|
||||
<a-modal v-model:visible="setGroupSizeVisible" title="设置小组人数" @ok="confirmSetGroupSize"
|
||||
@cancel="setGroupSizeVisible = false">
|
||||
<a-form :model="form" layout="vertical">
|
||||
<a-row style="padding: 20px;">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="每组人数">
|
||||
<a-input-number v-model:value="form.groupSize" :min="1" :precision="0" :step="1" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 引用小组对话框 -->
|
||||
<a-modal v-model:visible="yyfzModalVisible" title="引用分组配置" @ok="yyfzOk" :okText="'引用'"
|
||||
@cancel="yyfzModalVisible = false">
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="[16, 16]" style="padding:20px;">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="课程作业">
|
||||
<a-select v-model:value="yyfzValue" placeholder="请选择课程作业">
|
||||
<a-select-option v-for="item in kczyOptions" :key="item.id" :value="item.id">
|
||||
<span>{{ item.title }}</span>
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="xzxx" setup>
|
||||
import { ref, computed, reactive, onMounted, toRaw } from 'vue';
|
||||
import { Modal, message } from 'ant-design-vue';
|
||||
import { getXKRY } from '/@/views/kc/xxhbbks/Xxhbbks.api';
|
||||
import { getxzxx, saveData } from '/@/views/zy/zyInfo/ZyInfo.api';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const yyfzModalVisible = ref(false)
|
||||
const { createMessage } = useMessage();
|
||||
const editingGroup = ref(null);
|
||||
const editModalVisible = ref(false);
|
||||
const open = ref<boolean>(false);
|
||||
const assignVisible = ref<boolean>(false);
|
||||
const currentStep = ref<number>(0); // 控制分步表单的当前步骤
|
||||
const students = ref([]);
|
||||
const allocatedData = ref({
|
||||
allocated: [] // 每个小组对象应包含 sort 字段
|
||||
});
|
||||
const selectedStudent = ref(null);
|
||||
const setGroupSizeVisible = ref(false);
|
||||
const zyinfoId = ref('')
|
||||
const hmz = ref(null)
|
||||
const kczyOptions = ref([])
|
||||
const yyfzValue = ref('')
|
||||
const form = reactive({
|
||||
id: '',
|
||||
assignType: '', // 分配类型:'new' 创建新小组 | 'existing' 分配至已有小组
|
||||
newGroupName: '', // 新建小组的名称
|
||||
newGroupSort: 1, // 新建小组的排序
|
||||
existingGroupId: null, // 已有小组的ID
|
||||
isLeader: false, // 是否为组长
|
||||
groupSize: 3
|
||||
});
|
||||
|
||||
const emit = defineEmits(['saveSuccess']);
|
||||
|
||||
const props = defineProps({
|
||||
studentsQP: { type: Object, default: () => ({}) }
|
||||
});
|
||||
|
||||
const isEdit = ref(false)
|
||||
|
||||
// 定义 sortedAllocatedGroups 计算属性
|
||||
const sortedAllocatedGroups = computed(() => {
|
||||
return allocatedData.value.allocated?.slice().sort((a, b) => a.sort - b.sort) || [];
|
||||
});
|
||||
|
||||
// 计算属性:未分配的学生列表
|
||||
const unallocatedStudents = computed(() => {
|
||||
const allocatedXhs = allocatedData.value.allocated?.flatMap(group => {
|
||||
return group.students.map(student => student.xh)
|
||||
}) || [];
|
||||
return students.value.filter(student => !allocatedXhs.includes(student.xh));
|
||||
});
|
||||
|
||||
// 计算属性:是否有已分配的数据
|
||||
const hasAllocatedData = computed(() => {
|
||||
return allocatedData.value.allocated && allocatedData.value.allocated.length > 0;
|
||||
});
|
||||
|
||||
// 计算属性:可用的小组列表(过滤掉满员的小组)
|
||||
const availableGroups = computed(() => {
|
||||
return allocatedData.value.allocated?.filter(group => !isGroupFull(group)) || [];
|
||||
});
|
||||
|
||||
// 判断小组是否已满员
|
||||
const isGroupFull = (group) => {
|
||||
return group.students.length >= allocatedData.value.rs;
|
||||
};
|
||||
|
||||
// 判断小组是否有组长
|
||||
const hasLeader = (group) => group.students.some(member => member.sfzz === 'Y');
|
||||
|
||||
// 获取组长的名字
|
||||
const getLeaderName = (group) => {
|
||||
const leader = group.students.find(member => member.sfzz === 'Y');
|
||||
return leader ? leader.xm : '';
|
||||
};
|
||||
|
||||
// 下一步逻辑
|
||||
const nextStep = () => {
|
||||
if (form.assignType) {
|
||||
currentStep.value = 1;
|
||||
}
|
||||
};
|
||||
|
||||
async function iniAllocatedData(zyInfo, selectStudents = true) {
|
||||
allocatedData.value.allocated = []
|
||||
allocatedData.value.unabsorbed = []
|
||||
|
||||
//获取全部选课的学生
|
||||
if (selectStudents) await loadStudents();
|
||||
|
||||
//获取已分配小组信息
|
||||
const data = await getxzxx({ id: zyInfo.id });
|
||||
allocatedData.value.allocated = data.result
|
||||
}
|
||||
|
||||
// 打开模态框并加载学生数据
|
||||
const showModal = async (zyInfo, kczyList, isEdit_) => {
|
||||
zyinfoId.value = zyInfo.id
|
||||
allocatedData.value.rs = zyInfo.xzrs
|
||||
open.value = true;
|
||||
//处理课程作业列表Options
|
||||
kczyOptions.value = []
|
||||
kczyList.forEach(kczy => {
|
||||
if (kczy.id != zyInfo.id && kczy.sfpzgxzxx == 'Y') {
|
||||
kczyOptions.value.push({
|
||||
title: kczy.title,
|
||||
id: kczy.id,
|
||||
rs: kczy.xzrs
|
||||
})
|
||||
}
|
||||
});
|
||||
//查询分组信息
|
||||
iniAllocatedData(zyInfo)
|
||||
isEdit.value = isEdit_
|
||||
};
|
||||
|
||||
// 加载学生数据
|
||||
const loadStudents = async () => {
|
||||
const res = await getXKRY(props.studentsQP.rwbh);
|
||||
students.value = res.result;
|
||||
};
|
||||
|
||||
// 处理分配逻辑
|
||||
const handleAssign = async () => {
|
||||
if (!form.assignType) {
|
||||
message.error('请先选择分配方式');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证表单完整性
|
||||
if (currentStep.value === 1 && validateForm()) {
|
||||
try {
|
||||
// 执行分配逻辑
|
||||
await performAssignment();
|
||||
message.success('分配成功');
|
||||
assignVisible.value = false;
|
||||
} catch (error) {
|
||||
message.error('分配失败,请稍后再试');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 表单验证逻辑
|
||||
const validateForm = () => {
|
||||
if (form.assignType === 'new') {
|
||||
if (!form.newGroupName || !form.newGroupSort) {
|
||||
message.error('请填写完整的新小组信息');
|
||||
return false;
|
||||
}
|
||||
} else if (form.assignType === 'existing') {
|
||||
if (!form.existingGroupId) {
|
||||
message.error('请选择要分配的小组');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 执行分配逻辑
|
||||
const performAssignment = () => {
|
||||
if (form.assignType === 'new') {
|
||||
if (!hmz.value) hmz.value = new Date().getTime()
|
||||
else hmz.value = hmz.value + 1
|
||||
const newGroup = {
|
||||
id: hmz.value,
|
||||
xzmc: form.newGroupName,
|
||||
sort: form.newGroupSort,
|
||||
students: [{ ...selectedStudent.value, sfzz: form.isLeader ? 'Y' : 'N' }]
|
||||
};
|
||||
allocatedData.value.allocated.push(newGroup);
|
||||
} else if (form.assignType === 'existing') {
|
||||
const targetGroup = allocatedData.value.allocated.find(group => group.id === form.existingGroupId);
|
||||
if (targetGroup) {
|
||||
if (form.isLeader) {
|
||||
targetGroup.students.forEach(s_ => {
|
||||
s_.sfzz = 'N'
|
||||
});
|
||||
}
|
||||
targetGroup.students.push({ ...selectedStudent.value, sfzz: form.isLeader ? 'Y' : 'N' });
|
||||
}
|
||||
}
|
||||
};
|
||||
function resetFormData() {
|
||||
form.id = ''
|
||||
form.assignType = ''
|
||||
form.newGroupName = ''
|
||||
form.newGroupSort = 1
|
||||
form.existingGroupId = null
|
||||
form.isLeader = false
|
||||
}
|
||||
// 分配学生
|
||||
const assignStudent = (student) => {
|
||||
if (!allocatedData.value.rs) {
|
||||
message.warning('未设置小组人数');
|
||||
return;
|
||||
}
|
||||
selectedStudent.value = student;
|
||||
assignVisible.value = true;
|
||||
currentStep.value = 0;
|
||||
resetFormData()
|
||||
};
|
||||
|
||||
// 设置组长
|
||||
const setLeader = (group) => {
|
||||
// 弹出一个简单对话框让用户选择成员作为组长
|
||||
Modal.confirm({
|
||||
title: '设置组长',
|
||||
content: '请选择一位成员作为组长',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
// TODO 将未分配人员展示出来 然后进行选择
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 移除成员
|
||||
const removeFromGroup = (member) => {
|
||||
Modal.confirm({
|
||||
title: '移除成员',
|
||||
content: `确定要将${member.xm}从小组中移除吗?`,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
// 将成员从小组中移除,并加入到未分配学生列表
|
||||
allocatedData.value.allocated.forEach(group => {
|
||||
const index = group.students.findIndex(student => student.xh === member.xh);
|
||||
if (index !== -1) {
|
||||
group.students.splice(index, 1);
|
||||
}
|
||||
});
|
||||
// 确保没有重复添加到未分配列表
|
||||
if (!students.value.some(student => student.xh === member.xh)) {
|
||||
students.value.push(member);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//提升组长
|
||||
function promotionTeamLeader(member) {
|
||||
// 将成员从小组中移除,并加入到未分配学生列表
|
||||
allocatedData.value.allocated.forEach(group => {
|
||||
const index = group.students.findIndex(student => student.xh === member.xh);
|
||||
if (index !== -1) {
|
||||
group.students.forEach(item => {
|
||||
if (item.xh == member.xh) item.sfzz = 'Y'
|
||||
else item.sfzz = 'N'
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 解散小组
|
||||
const dissolveGroup = (group) => {
|
||||
Modal.confirm({
|
||||
title: '解散小组',
|
||||
content: `确定要解散${group.xzmc}吗?`,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
// 在将小组成员加入到未分配学生列表前,先过滤掉已经在未分配列表中的学生
|
||||
const newMembers = group.students.filter(student =>
|
||||
!students.value.some(existingStudent => existingStudent.xh === student.xh)
|
||||
);
|
||||
// 添加新的未分配成员
|
||||
students.value.push(...newMembers);
|
||||
// 删除小组信息
|
||||
allocatedData.value.allocated = allocatedData.value.allocated.filter(g => g.sort !== group.sort);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 编辑小组的方法
|
||||
const editGroup = (group) => {
|
||||
// 将要编辑的小组信息复制到 editingGroup 中
|
||||
editingGroup.value = { ...group };
|
||||
editModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 保存编辑后的小组信息
|
||||
const saveEdit = () => {
|
||||
if (!editingGroup.value.xzmc) {
|
||||
message.error('请填写小组名称');
|
||||
return;
|
||||
}
|
||||
if (!editingGroup.value.sort) {
|
||||
message.error('请填写小组排序');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!editingGroup.value) return;
|
||||
|
||||
const targetGroupIndex = allocatedData.value.allocated.findIndex(g => g.id === editingGroup.value.id);
|
||||
if (targetGroupIndex !== -1) {
|
||||
allocatedData.value.allocated.splice(targetGroupIndex, 1, editingGroup.value);
|
||||
}
|
||||
message.success('编辑成功');
|
||||
editModalVisible.value = false;
|
||||
};
|
||||
|
||||
// 计算属性:筛选后的未分配的学生列表
|
||||
const searchQuery = ref('');
|
||||
const filteredUnallocatedStudents = computed(() => {
|
||||
if (!searchQuery.value) return unallocatedStudents.value;
|
||||
|
||||
const query = searchQuery.value.toLowerCase();
|
||||
return unallocatedStudents.value.filter(student =>
|
||||
student.xm.toLowerCase().includes(query) ||
|
||||
student.xh.toString().includes(query)
|
||||
);
|
||||
});
|
||||
|
||||
const setGroupSize = () => {
|
||||
setGroupSizeVisible.value = true;
|
||||
};
|
||||
|
||||
function shuffleArray(array) {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
// 生成一个从0到i的随机索引
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
// 交换元素array[i]和array[j]
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// 使用示例:
|
||||
const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
const performAutoAssignment = async () => {
|
||||
let unassigned = [...unallocatedStudents.value];
|
||||
let totalGroupsNeeded = Math.ceil(students.value.length / allocatedData.value.rs);
|
||||
|
||||
// 如果没有分组,则按规则一创建新分组
|
||||
if (!allocatedData.value.allocated || allocatedData.value.allocated.length === 0) {
|
||||
for (let i = 0; i < totalGroupsNeeded; i++) {
|
||||
const newGroupName = `小组${i + 1}`;
|
||||
const newGroupSort = i + 1;
|
||||
allocatedData.value.allocated.push({ id: Date.now() + i, xzmc: newGroupName, sort: newGroupSort, students: [] });
|
||||
}
|
||||
}
|
||||
|
||||
// 按照规则二处理已有分组
|
||||
if (allocatedData.value.allocated.length < totalGroupsNeeded) {
|
||||
for (let i = allocatedData.value.allocated.length; i < totalGroupsNeeded; i++) {
|
||||
const newGroupName = `小组${i + 1}`;
|
||||
const newGroupSort = allocatedData.value.allocated.reduce((max, g) => Math.max(max, g.sort), 0) + 1;
|
||||
allocatedData.value.allocated.push({ id: Date.now() + i, xzmc: newGroupName, sort: newGroupSort, students: [] });
|
||||
}
|
||||
}
|
||||
|
||||
unassigned = shuffleArray(unassigned)
|
||||
// 分配学生到小组中
|
||||
allocatedData.value.allocated.forEach(group => {
|
||||
while (group.students.length < allocatedData.value.rs && unassigned.length > 0) {
|
||||
const student = unassigned.shift();
|
||||
if (student) {
|
||||
group.students.push({ ...student, sfzz: group.students.length === 0 ? 'Y' : 'N' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
message.success('自动分配成功');
|
||||
};
|
||||
|
||||
const autoAssignGroups = async () => {
|
||||
if (!allocatedData.value.rs) {
|
||||
message.warning('未设置小组人数');
|
||||
return;
|
||||
}
|
||||
await performAutoAssignment();
|
||||
};
|
||||
|
||||
const resetGroups = () => {
|
||||
Modal.confirm({
|
||||
title: '重置分组',
|
||||
content: '是否重置分组信息?',
|
||||
okText: '重置',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
allocatedData.value.allocated = []
|
||||
allocatedData.value.unabsorbed = []
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const confirmSetGroupSize = () => {
|
||||
if (form.groupSize > 0) {
|
||||
allocatedData.value.rs = form.groupSize;
|
||||
setGroupSizeVisible.value = false;
|
||||
} else {
|
||||
message.error('请设置有效的人数');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const removeLeader = (group) => {
|
||||
removeFromGroup(toRaw(group.students.find(member => member.sfzz === 'Y')))
|
||||
}
|
||||
|
||||
// 关闭模态框
|
||||
const handleOk = () => {
|
||||
if(!isEdit.value){
|
||||
open.value = false
|
||||
return
|
||||
}
|
||||
allocatedData.value.allocated.forEach(allo => {
|
||||
allo.zyinfoId = zyinfoId.value
|
||||
allo.students?.forEach(stu => {
|
||||
stu.zyinfoId = zyinfoId.value
|
||||
});
|
||||
})
|
||||
saveData({ zyinfoId: zyinfoId.value, rs: allocatedData.value.rs, list: allocatedData.value.allocated }).then(res => {
|
||||
emit('saveSuccess', zyinfoId.value, allocatedData.value)
|
||||
createMessage.success('保存成功!')
|
||||
open.value = false
|
||||
}).catch(err => {
|
||||
createMessage.error('服务器异常,请稍后重试!');
|
||||
})
|
||||
};
|
||||
|
||||
//应用分组
|
||||
const quotationManager = () => {
|
||||
yyfzModalVisible.value = true
|
||||
}
|
||||
|
||||
//保存分组配置
|
||||
const yyfzOk = async () => {
|
||||
if (!!yyfzValue.value) {
|
||||
kczyOptions.value.forEach(kczy => {
|
||||
if (yyfzValue.value == kczy.id) {
|
||||
allocatedData.value.rs = kczy.rs
|
||||
}
|
||||
})
|
||||
await iniAllocatedData({ id: yyfzValue.value }, false)
|
||||
yyfzModalVisible.value = false
|
||||
} else {
|
||||
createMessage.warning('未选择课程作业!')
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时初始化数据
|
||||
onMounted(async () => {
|
||||
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
showModal
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
/* 确保模态框内的表单项有适当的间距 */
|
||||
.a-modal {
|
||||
.ant-form-item {
|
||||
margin-bottom: 16px;
|
||||
/* 增加表单项之间的垂直间距 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 可选:增加一些额外的样式以改善视觉效果 */
|
||||
.ant-form-vertical .ant-form-item-label {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.ant-card-head-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
|
@ -228,6 +228,7 @@
|
|||
}
|
||||
function handleBohui(record: Recordable){
|
||||
defHttp.post({url:'/zyInfoStudent/zyInfoStudent/editBohui',params:{id:record.id}}).then(res =>{
|
||||
createMessage.success('作业驳回成功!')
|
||||
handleSuccess()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -158,6 +158,8 @@
|
|||
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
|
||||
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
const stuZyIds = ref([])
|
||||
const xzxstjzy = ref(null)
|
||||
let zyInfo = ref<any>({});
|
||||
//表单验证
|
||||
const validatorRules = {
|
||||
|
@ -251,6 +253,8 @@ function handleKcnr(kcnr) {
|
|||
* 编辑
|
||||
*/
|
||||
function edit(record) {
|
||||
stuZyIds.value = record.stuZyIds
|
||||
xzxstjzy.value = record.xzxstjzy
|
||||
console.log(`🚀 ~ edit ~ record:`, record)
|
||||
stuId.value = record.stuId;
|
||||
nextTick(() => {
|
||||
|
@ -272,70 +276,96 @@ function handleKcnr(kcnr) {
|
|||
});
|
||||
}
|
||||
|
||||
function submitZy(model, ids, isUpdate) {
|
||||
let models = [model];
|
||||
|
||||
if (Array.isArray(ids) && ids.length > 0) {
|
||||
ids.forEach(id => {
|
||||
let newModel = { ...model, stuId: id.id };
|
||||
models.push(newModel);
|
||||
});
|
||||
}
|
||||
let msgr = true
|
||||
let msg = '操作成功'
|
||||
models.forEach(async m_ => {
|
||||
await zyscStu(m_, isUpdate)
|
||||
.then((res) => {
|
||||
console.log(`🚀 ~ .then ~ res:`, res)
|
||||
if (res.success) {
|
||||
//异步提交维普
|
||||
stuWpKsjc(model, isUpdate).then((res) => { })
|
||||
} else {
|
||||
msg = res.message
|
||||
createMessage.warning(res.message);
|
||||
}
|
||||
}).catch(err => {
|
||||
msgr = false
|
||||
msg = '提交失败'
|
||||
})
|
||||
})
|
||||
if (msgr) {
|
||||
createMessage.success("操作成功");
|
||||
emit('ok');
|
||||
confirmLoading.value = false;
|
||||
emit('closeLoading');
|
||||
} else {
|
||||
createMessage.warning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交数据
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
// var t = await validate();
|
||||
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
let model = formData;
|
||||
if (model.id) {
|
||||
isUpdate.value = true;
|
||||
}
|
||||
//循环数据
|
||||
for (let data in model) {
|
||||
//如果该数据是数组并且是字符串类型
|
||||
if (model[data] instanceof Array) {
|
||||
let valueType = getValueType(formRef.value.getProps, data);
|
||||
//如果是字符串类型的需要变成以逗号分割的字符串
|
||||
if (valueType === 'string') {
|
||||
model[data] = model[data].join(',');
|
||||
}
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
// var t = await validate();
|
||||
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
let model = formData;
|
||||
if (model.id) {
|
||||
isUpdate.value = true;
|
||||
}
|
||||
//循环数据
|
||||
for (let data in model) {
|
||||
//如果该数据是数组并且是字符串类型
|
||||
if (model[data] instanceof Array) {
|
||||
let valueType = getValueType(formRef.value.getProps, data);
|
||||
//如果是字符串类型的需要变成以逗号分割的字符串
|
||||
if (valueType === 'string') {
|
||||
model[data] = model[data].join(',');
|
||||
}
|
||||
}
|
||||
if(!model.filePath){
|
||||
emit('closeLoading');
|
||||
confirmLoading.value = false;
|
||||
createMessage.warning("请上传作业附件");
|
||||
return;
|
||||
}
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认提交',
|
||||
content: '是否确认提交数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
model.stuId = stuId.value;
|
||||
model.mainId = zyInfo.value.id;
|
||||
zyscStu(model, isUpdate.value)
|
||||
.then((res) => {
|
||||
console.log(`🚀 ~ .then ~ res:`, res)
|
||||
if (res.success) {
|
||||
createMessage.success("操作成功");
|
||||
emit('ok');
|
||||
//异步提交维普
|
||||
stuWpKsjc(model, isUpdate.value).then((res) => {})
|
||||
} else {
|
||||
createMessage.warning(res.message);
|
||||
}
|
||||
emit('closeLoading');
|
||||
})
|
||||
.finally(() => {
|
||||
confirmLoading.value = false;
|
||||
emit('closeLoading');
|
||||
});
|
||||
},
|
||||
onCancel: () => {
|
||||
confirmLoading.value = false;
|
||||
emit('closeLoading');
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!model.filePath) {
|
||||
emit('closeLoading');
|
||||
confirmLoading.value = false;
|
||||
createMessage.warning("请上传作业附件");
|
||||
return;
|
||||
}
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认提交',
|
||||
content: '是否确认提交数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
model.stuId = stuId.value;
|
||||
model.mainId = zyInfo.value.id;
|
||||
if(xzxstjzy.value == 'Y'){
|
||||
const zys = stuZyIds.value.filter(stu => stu.id != model.stuId)
|
||||
submitZy(model,zys,isUpdate.value)
|
||||
}else{
|
||||
submitZy(model,[],isUpdate.value)
|
||||
}
|
||||
},
|
||||
onCancel: () => {
|
||||
confirmLoading.value = false;
|
||||
emit('closeLoading');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function openPdf(record){
|
||||
if(record.stuPdfPath){
|
||||
|
|
|
@ -299,7 +299,7 @@ function handleVideo(three){
|
|||
}
|
||||
}
|
||||
|
||||
defHttp.post({url:'/zyInfoStudent/zyInfoStudent/editPiyue',params:model}).then(res =>{
|
||||
defHttp.post({url:'/zyInfoStudent/zyInfoStudent/editFabu',params:model}).then(res =>{
|
||||
emit('ok');
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -344,7 +344,7 @@ function handleVideo(three){
|
|||
}
|
||||
}
|
||||
|
||||
await defHttp.post({url:'/zyInfoStudent/zyInfoStudent/editPiyue',params:model}).then(res =>{
|
||||
await defHttp.post({url:'/zyInfoStudent/zyInfoStudent/editFabu',params:model}).then(res =>{
|
||||
emit('ok2');
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue