Commit 92de224c authored by wuhao's avatar wuhao 🎯

config +pages

parent d5318684
Pipeline #3304 failed with stages
in 2 minutes and 31 seconds
......@@ -8,7 +8,9 @@ export default {
"DEFAULT_404_IMG":"./assets/illustrations/illustration_404.svg"
},
test:{
"REACT_APP_URL":"http://118.25.178.150:7001"
"REACT_APP_URL":"/vstp",
"DEFAULT_HEAD_IMG":"./assets/images/avatars/avatar_21.jpg",
"DEFAULT_404_IMG":"./assets/illustrations/illustration_404.svg"
},
prod:{
"REACT_APP_URL":"http://tasks.nangaoyun.com"
......
......@@ -23,10 +23,10 @@ export default {
*/
test: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
"/api/": {
target: "https://proapi.azurewebsites.net",
"/vstp/": {
target: "http://192.168.40.117:8044/vstp",
changeOrigin: true,
pathRewrite: { "^": "" },
pathRewrite: { "^/vstp": "" },
},
},
pre: {
......
......@@ -109,6 +109,11 @@ export default [
path: "/work/dobustrain/:id",
component: "./dobustrain",
},
{
name: "课程详情",
path: "/work/domybustrain/:id",
component: "./domybustrain",
},
{
name: "成绩管理",
path: "/work/rebustrain/:id",
......@@ -129,6 +134,11 @@ export default [
path: "/work/checkhomework",
component: "./checkhomework",
},
{
name: "成绩单",
path: "/work/myrecord",
component: "./myrecord",
},
],
},
{
......
import PropTypes from "prop-types";
// @mui
import {
Box,
Card,
colors,
IconButton,
Stack,
Tooltip,
Typography,
} from "@mui/material";
import { styled } from "@mui/material/styles";
// utils
// components
import IconFont from "@/components/IconFont";
import Label from "@/components/label";
import difftime from "@/utils/difftime";
import AccessTimeFilledIcon from "@mui/icons-material/AccessTimeFilled";
import CheckIcon from "@mui/icons-material/Check";
import dayjs from "dayjs";
import { useState } from "react";
import { history } from "@umijs/max";
// ----------------------------------------------------------------------
const StyledProductImg = styled("img")({
top: 0,
width: "92%",
height: "92%",
marginTop: "4%",
objectFit: "cover",
position: "absolute",
});
ShopProductCard.propTypes = {
product: PropTypes.object,
};
export default function ShopProductCard({
product,
remove,
edit,
copy,
publish,
authorized,
tauthorized,
}) {
const {
trainName,
picUrl,
createTime,
typeName,
type,
deadline,
sectionNum,
experimentNum,
studentNum,
startTime,
totalSubmitExperimentNum,
totalExperimentNum,
} = product;
const [confirm, setconfirm] = useState(false);
const [shut, setshut] = useState(false);
const ifs = type === 1 || type === 3;
return (
<Card sx={{ borderRadius: 3 }} className="hovered" id="jikl">
<Box sx={{ pt: "66%", position: "relative" }} className="center">
{typeName && (
<Label
variant="filled"
color={
(type === 1 && "warning") ||
(type === 2 && "info") ||
(type === 3 && "default") ||
"error"
}
sx={{
zIndex: 9,
top: 20,
left: 20,
position: "absolute",
textTransform: "uppercase",
}}
>
{typeName}
</Label>
)}
<StyledProductImg
alt={trainName}
src={picUrl ?? DEFAULT_404_IMG}
sx={{ borderRadius: 2 }}
/>
</Box>
<Stack spacing={1} sx={{ p: 2 }}>
<Stack
direction={"row"}
justifyContent={"space-between"}
width={"100%"}
overflow={"hidden"}
alignItems={"center"}
>
<div className="center">
<Tooltip placement="bottom-start" title={trainName}>
<Typography
variant="subtitle2"
noWrap
sx={{
paddingLeft: 0,
}}
>
{trainName}
</Typography>
</Tooltip>
</div>
<Box width={60} textAlign={"right"} flexShrink={0}>
<Tooltip placement="bottom-start" title={createTime}>
<Typography
component="span"
variant="body2"
sx={{
color: "text.disabled",
}}
>
{difftime(dayjs(), dayjs(createTime))}
</Typography>
</Tooltip>
</Box>
</Stack>
<Stack
direction={"row"}
justifyContent={"space-between"}
width={"100%"}
overflow={"hidden"}
alignItems={"center"}
>
<Stack direction={"row"} alignItems={"center"}>
<AccessTimeFilledIcon
sx={{ color: colors.grey[800], fontSize: 20 }}
/>
<Typography
component="span"
variant="body2"
sx={{
paddingLeft: 1,
}}
>
日期: {startTime ?? "-"}{deadline}
</Typography>
</Stack>
</Stack>
<Stack
direction={"row"}
justifyContent={"space-between"}
alignItems={"center"}
padding={"0 2px"}
>
<Stack direction={"row"} spacing={2} alignItems={"center"}>
<Stack
direction={"row"}
alignItems={"center"}
sx={{ cursor: "pointer" }}
>
<IconFont
type="icon-beike"
style={{ fontSize: 16, opacity: 0.6 }}
></IconFont>
<Typography
component="span"
variant="body2"
sx={{
color: "text.disabled",
paddingLeft: 1.2,
fontSize: 12,
margin: 0,
}}
>
{sectionNum}课时/{experimentNum}实验
</Typography>
</Stack>
</Stack>
<Stack direction={"row"} spacing={0}>
<Tooltip placement="bottom-start" title={"发布"}>
<IconButton
onClick={() => {
history.push("/work/domybustrain/" + product.id);
}}
>
<IconFont
type="icon-fabu"
style={{ fontSize: 20, color: colors.blue[600] }}
></IconFont>
</IconButton>
</Tooltip>
<Tooltip
placement="bottom-start"
title={"成绩"}
>
<IconButton
disabled={shut === "1"}
onClick={() => {
}}
>
<CheckIcon
style={{
fontSize: 20,
color: shut === "1" ? colors.grey[500] : colors.green[500],
}}
></CheckIcon>
</IconButton>
</Tooltip>
</Stack>
</Stack>
</Stack>
</Card>
);
}
......@@ -61,6 +61,7 @@ export default function ShopProductCard({
sectionNum,
experimentNum,
studentNum,
startTime,
totalSubmitExperimentNum,
totalExperimentNum,
} = product;
......@@ -269,7 +270,7 @@ export default function ShopProductCard({
paddingLeft: 1,
}}
>
截止日期: {deadline}
日期: {startTime ?? "-"} {deadline}
</Typography>
</Stack>
</Stack>
......
......@@ -46,7 +46,7 @@ const navConfig = [
},
{
title: "我的成绩",
path: "/work/home",
path: "/work/myrecord",
icon: icon("ic_grades"),
info: (
<div
......
import AutoTable from "@/components/AutoTable";
import DraggableDialog from "@/components/DraggableDialog";
import InitForm from "@/components/InitForm";
import PremButton from "@/components/PremButton";
import TreeRender from "@/components/TreeRender/sxtree";
import { doFetch } from "@/utils/doFetch";
import editorIsNull from "@/utils/editorIsNull";
import { Box, Container, Grid, Link, Stack, Typography } from "@mui/material";
import { useParams } from "@umijs/max";
import { useRequest } from "ahooks";
import { Badge, message, Tabs } from "antd";
import { useEffect, useMemo, useRef, useState } from "react";
import { history } from "umi";
import "./index.less";
function Dolessons() {
const params = useParams();
const formRef = useRef(),
cksyactionRef = useRef(),
cjwtactionRef = useRef();
const [lessonDetail, setlessonDetail] = useState(null),
[courseContent, setCourseContent] = useState({}),
[drawer, setDrawer] = useState({
open: false,
}),
[active, setactive] = useState("1");
const { runAsync, loading } = useRequest(doFetch, {
manual: true,
onSuccess: (res, parames) => {
if (res?.code == "0000") {
handleClose();
message.success("操作成功");
if (active === "2") {
cksyactionRef?.current?.reload();
} else if (active === "3") {
cjwtactionRef?.current?.reload();
}
}
},
});
useEffect(() => {
doFetch({ url: "/studentTrain/detail", params: { id: params?.id } }).then(
(res) => {
if (res.code === "0000") {
setlessonDetail(res?.data?.data);
}
}
);
}, []);
const ifs = useMemo(() => {
let { type } = lessonDetail ?? {};
return !(type === 1 || type === 3);
}, [lessonDetail]);
const checkCourse = (val) => {
if (val.length) {
doFetch({
url: "/busTrainCatalogue/getCatalogueContent",
params: { id: val[0] },
}).then((res) => {
setCourseContent(res?.data?.data);
formRef.current.setFieldValue(
"trainContent",
res?.data?.data?.trainContent
);
});
}
};
const edit = (text, row, _, action) => {
return (
<PremButton
btn={{
size: "small",
disabled: ifs,
variant: "text",
onClick: () => {
setDrawer((v) => ({
open: true,
defaultFormValue: { ...row },
title: "编辑",
}));
},
}}
>
编辑
</PremButton>
);
};
const remove = (text, row, _, action) => {
return (
<PremButton
pop={{
disabled: ifs,
title: "是否删除该实验?",
okText: "确认",
cancelText: "取消",
onConfirm: async () => {
await runAsync({
url: "/busTrainExperiment/remove",
params: { id: row?.id },
});
},
}}
btn={{
disabled: ifs,
size: "small",
color: "error",
}}
>
删除
</PremButton>
);
};
const removeq = (text, row, _, action) => {
return (
<PremButton
pop={{
disabled: ifs,
title: "是否删除该实验?",
okText: "确认",
cancelText: "取消",
onConfirm: async () => {
await runAsync({
url: "/busTrainQuestion/delete",
params: { id: row?.id },
});
},
}}
btn={{
size: "small",
color: "error",
disabled: ifs,
}}
>
删除
</PremButton>
);
};
const questionColumns = useMemo(() => {
let col = [
{
title: "问题内容",
dataIndex: "question",
key: "question",
width: 400,
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
{
title: "参考答案",
dataIndex: "answer",
key: "answer",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
];
return col;
}, []);
const experimentColumns = useMemo(() => {
let col = [
{
title: "实验名称",
dataIndex: "experimentName",
key: "experimentName",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
render: (_, row) => {
return (
<Link
underline="hover"
href={row?.url}
target="_blank"
rel="noopener"
>
{row?.experimentName}
</Link>
);
},
search: false,
},
{
title: "考试时间(分钟)",
search: false,
dataIndex: "testTime",
key: "testTime",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
{
title: "权重(%)",
search: false,
dataIndex: "weight",
key: "weight",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
{
search: false,
title: "创建人",
dataIndex: "updateUserName",
key: "updateUserName",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
{
title: "创建时间",
dataIndex: "updateTime",
search: false,
key: "updateTime",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
{
title: "截止时间",
dataIndex: "deadline",
search: false,
key: "deadline",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
{
title: "实验完成率",
dataIndex: "finishPer",
search: false,
key: "finishPer",
formItemProps: { rules: [{ required: true, message: "此项为必填项" }] },
},
];
return col;
}, []);
const items = [
{
key: "1",
label: `课程目录`,
children: (
<Grid container spacing={2}>
<Grid item width={340}>
<Box boxShadow={"0 0 18px #f0f0f0"} borderRadius={2} padding={2}>
<TreeRender
onselected={checkCourse}
maxWidth={170}
url="/busTrainCatalogue/queryCatalogueTree"
saveurl="/busTrainCatalogue/saveOrUpdateCatalogue"
deleteurl="/busTrainCatalogue/deleteCatalogue"
submitKey="catalogue"
disabled={ifs}
params={{
trainId: params?.id,
}}
/>
</Box>
</Grid>
<Grid item flex={1}>
<Box boxShadow={"0 0 18px #f0f0f0"} borderRadius={2} padding={2}>
<InitForm
formRef={formRef}
fields={[
{
key: "trainContent",
dataIndex: "trainContent",
valueType: "Editor",
colProps: {
span: 24,
},
},
]}
onFinish={(val) => {
const data = { ...val };
if (editorIsNull(data?.trainContent)) {
return message.warning("备课内容不能为空!", 2);
}
doFetch({
url: "/busTrainCatalogue/saveCatalogueContent",
params: {
id: courseContent?.id,
trainContent: data?.trainContent,
},
}).then((res) => {
if (res.code === "0000") {
message.success("操作成功!");
}
});
}}
disabled={ifs}
/>
</Box>
</Grid>
</Grid>
),
},
{
key: "2",
label: (
<Badge count={lessonDetail?.experimentNum} size="small" offset={[6, 0]}>
查看实验
</Badge>
),
children: (
<Box boxShadow={"0 0 18px #f0f0f0"} borderRadius={2}>
<AutoTable
rerendered={false}
actionRef={cksyactionRef}
columns={[
...experimentColumns,
{
title: "操作",
valueType: "option",
width: 180,
render: (text, row, _, action) => [
edit(text, row, _, action),
remove(text, row, _, action),
],
},
]}
path="/busTrainExperiment/page"
extraparams={{
trainId: params?.id,
}}
/>
</Box>
),
},
{
key: "3",
label: "常见问题",
children: (
<Box boxShadow={"0 0 18px #f0f0f0"} borderRadius={2}>
<AutoTable
rerendered={false}
actionRef={cjwtactionRef}
columns={[
...questionColumns,
{
title: "操作",
valueType: "option",
width: 180,
render: (text, row, _, action) => [
edit(text, row, _, action),
removeq(text, row, _, action),
],
},
]}
path="/busTrainQuestion/page"
extraparams={{
trainId: params?.id,
}}
/>
</Box>
),
},
];
const addHandel = (val) => {
if (active === "1") {
// 预览
} else if (active === "2") {
// 添加实验
setDrawer({ open: true, title: "添加实验" });
} else {
// 添加问题
setDrawer({ open: true, title: "添加问题" });
}
};
const handleClose = () => {
setDrawer((s) => ({
...s,
open: false,
}));
};
return (
<Container maxWidth={false}>
<DraggableDialog
handleClose={handleClose}
dialogprops={drawer}
loading={loading}
maxWidth={drawer?.maxWidth ?? "sm"}
>
{active === "2" ? (
<InitForm
defaultFormValue={drawer?.defaultFormValue ?? null}
fields={[
{
title: "实验",
dataIndex: "id",
key: "id",
valueType: "select",
options: {
path: "/busTrainExperiment/selection",
params: { trainId: params?.id },
},
formItemProps: {
rules: [
{
required: true,
message: "此项为必填项",
},
],
},
},
{
title: "权重(%)",
dataIndex: "weight",
key: "weight",
valueType: "digit",
formItemProps: {
rules: [
{
required: true,
message: "此项为必填项",
},
],
},
},
{
title: "考试时间(分钟)",
dataIndex: "testTime",
key: "testTime",
valueType: "digit",
formItemProps: {
rules: [
{
required: true,
message: "此项为必填项",
},
],
},
},
{
title: "截止时间",
dataIndex: "deadline",
key: "deadline",
valueType: "date",
formItemProps: {
rules: [
{
required: true,
message: "此项为必填项",
},
],
},
},
]}
onFinish={(val, extra) => {
let postdata;
switch (drawer?.title) {
case "添加实验":
postdata = {
...val,
trainId: params?.id,
};
break;
case "编辑":
postdata = {
...val,
id: drawer?.defaultFormValue?.id,
trainId: params?.id,
};
default:
break;
}
runAsync({
url: "/busTrainExperiment/update",
params: postdata,
});
}}
onValuesChange={(curval, vals, formRef) => {
if (Object.keys(curval)[0] === "id") {
doFetch({
url: "/busTrainExperiment/detail",
params: { id: Object.values(curval)[0] },
}).then((res) => {
formRef?.current?.setFieldsValue({
weight: res?.data?.data?.weight,
});
});
}
}}
></InitForm>
) : (
<InitForm
defaultFormValue={drawer?.defaultFormValue ?? null}
fields={[
{
title: "问题内容",
dataIndex: "question",
key: "question",
valueType: "textarea",
},
{
title: "参考答案",
dataIndex: "answer",
key: "answer",
valueType: "textarea",
},
]}
onFinish={(val, extra) => {
let postdata;
switch (drawer?.title) {
case "添加问题":
postdata = {
...val,
trainId: params?.id,
};
break;
case "编辑":
postdata = {
...val,
id: drawer?.defaultFormValue?.id,
trainId: params?.id,
};
default:
break;
}
runAsync({
url: "/busTrainQuestion/saveOrUpdate",
params: postdata,
});
}}
></InitForm>
)}
</DraggableDialog>
<Box
display={"flex"}
justifyContent={"space-between"}
alignItems={"center"}
sx={{ mb: 2.5 }}
mt={0}
>
<Typography variant="h5">
{lessonDetail?.trainName ?? "暂无名称"}
</Typography>
<Stack spacing={2} direction="row">
<PremButton
btn={{
variant: "outlined",
onClick: (e) => {
e.stopPropagation();
history.back();
},
}}
>
返回
</PremButton>
<PremButton
btn={{
disabled:ifs,
variant: "contained",
onClick: addHandel,
}}
>
{active === "1" ? "预览" : active === "2" ? "添加实验" : "添加问题"}
</PremButton>
</Stack>
</Box>
<Box>
<Tabs
activeKey={active}
onChange={setactive}
items={items}
tabPosition="top"
animated={true}
/>
</Box>
</Container>
);
}
export default Dolessons;
.white {
.ant-pro-card {
background-color: #f6f6f6 !important;
}
.ant-table-tbody,td {
background-color: #f9f9f9 !important;
}
}
.ant-tree{
background-color: transparent !important;
}
\ No newline at end of file
......@@ -3,7 +3,7 @@ import ImportExcel from "@/components/ImportExcel";
import InitForm from "@/components/InitForm";
import PremButton from "@/components/PremButton";
import ShopProductLoadingCard from "@/components/ProductCard/loading";
import ShopProductCard from "@/components/ProductCard/sxcard";
import ShopProductCard from "@/components/ProductCard/stucard";
import { doFetch } from "@/utils/doFetch";
import PRODUCTS from "@/_mock/products";
import { Box, Container, Grid, Stack, Typography } from "@mui/material";
......@@ -47,7 +47,7 @@ function Lessons() {
const datalist = useRequest(
async () => {
let res = await doFetch({ url: "/busTrain/list", params });
let res = await doFetch({ url: "/studentTrain/queryTrainList", params });
return res?.data?.dataList;
},
{
......
import AutoTable from "@/components/AutoTable";
import { Box, Container, Stack, Typography } from "@mui/material";
import { useMemo, useRef } from "react";
import "./index.less";
function Record() {
const actionRef = useRef();
const columns = useMemo(() => {
let res = [
{ title: "课程名称", dataIndex: "courseName", key: "courseName" },
{ title: "实训名称", dataIndex: "trainName", key: "trainName" },
{ title: "实验名称", dataIndex: "experimentName", key: "experimentName" },
{
title: "分数",
dataIndex: "scoreWeight",
key: "scoreWeight",
hideInSearch: true,
},
{
title: "提交时间",
dataIndex: "finishTime",
key: "finishTimeRange",
valueType: "dateTimeRange",
},
{
title: "批阅时间",
dataIndex: "reviewTime",
key: "reviewTimeRange",
valueType: "dateTimeRange",
},
{
title: "批阅状态",
dataIndex: "reviewTypeName",
key: "reviewType",
valueType: "select",
options: [
{ label: "待批阅", value: "1" },
{ label: "已批阅", value: "2" },
],
},
];
return res;
}, []);
return (
<Container maxWidth={false}>
<Stack direction={"row"} mb={2}>
<Typography variant="h5">成绩单</Typography>
</Stack>
<Box boxShadow={"0 0 18px #f0f0f0"} borderRadius={2}>
<AutoTable
actionRef={actionRef}
scroll={{ x: 1366 }}
columns={[...columns]}
path={"/studentExperiment/queryPageByLoginStudent"}
></AutoTable>
</Box>
</Container>
);
}
export default Record;
.white {
.ant-pro-card {
background-color: #f6f6f6 !important;
}
.ant-table-tbody,td {
background-color: #f9f9f9 !important;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment