diff --git a/admin/config/config.ts b/admin/config/config.ts index 8bd160c..918ed96 100644 --- a/admin/config/config.ts +++ b/admin/config/config.ts @@ -85,7 +85,7 @@ export default defineConfig({ name: '主题设置', icon: 'smile', path: '/course/subject', - component: './course/subject', + component: './course/subject/index_new', }, { name: '新建主题', @@ -102,7 +102,7 @@ export default defineConfig({ hideInMenu: true, }, { - name: '编辑主题', + name: '新建主题', icon: 'smile', path: '/course/subject/step/create', component: './course/subject/step', diff --git a/admin/src/pages/course/subject/index.tsx b/admin/src/pages/course/subject/index.tsx index f5848e2..deae115 100644 --- a/admin/src/pages/course/subject/index.tsx +++ b/admin/src/pages/course/subject/index.tsx @@ -414,68 +414,68 @@ const TableList: React.FC = () => { { - setCurrentRow(undefined); // 设置当前行 - handleDetailModalVisible(false); - }} - footer={null} - centered - > - {currentRow?.subject_id && ( - <> - { - console.log('step2 主题信息') - return Promise.resolve({ - success: true, - data: { id: '这是一段文本', object: '', date: '2020-07-30 08:00', duration: '', grade: 100, through: '>60', learn: '>20 min', times: 2 }, - }); - }}*/ - extra={false} - > - - {currentRow?.subject_name} - -
- - + title={'主题信息'} + width="50%" + visible={detailModalVisible} + onCancel={() => { + setCurrentRow(undefined); // 设置当前行 + handleDetailModalVisible(false); + }} + footer={null} + centered + > + {currentRow?.subject_id && ( + <> + { + console.log('step2 主题信息') + return Promise.resolve({ + success: true, + data: { id: '这是一段文本', object: '', date: '2020-07-30 08:00', duration: '', grade: 100, through: '>60', learn: '>20 min', times: 2 }, + }); + }}*/ + extra={false} + > + + {currentRow?.subject_name} + +
+ + - - headerTitle={false} - actionRef={actionChapterRef} - rowKey="chapter_id" - options={false} - search={false} - toolBarRender={false} - request={async (value) => { - const { data } = await queryListChapterBySubject({ - subject_id: currentRow?.subject_id, - page_number: value?.current || 1, - page_size: value?.pageSize, - }); - return { - current: data?.page_number, - data: data?.list, - pageSize: data?.page_size, - success: true, - total: data?.total_row || 0, - }; - }} - // dataSource={list} - columns={chapterColumns} - rowSelection={false} - /> - + + headerTitle={false} + actionRef={actionChapterRef} + rowKey="chapter_id" + options={false} + search={false} + toolBarRender={false} + request={async (value) => { + const { data } = await queryListChapterBySubject({ + subject_id: currentRow?.subject_id, + page_number: value?.current || 1, + page_size: value?.pageSize, + }); + return { + current: data?.page_number, + data: data?.list, + pageSize: data?.page_size, + success: true, + total: data?.total_row || 0, + }; + }} + // dataSource={list} + columns={chapterColumns} + rowSelection={false} + /> + )} - + { const success = await handleUpdate(value, currentRow); diff --git a/admin/src/pages/course/subject/index_new.tsx b/admin/src/pages/course/subject/index_new.tsx new file mode 100644 index 0000000..5e43576 --- /dev/null +++ b/admin/src/pages/course/subject/index_new.tsx @@ -0,0 +1,379 @@ +import { PlusOutlined } from '@ant-design/icons'; +import { Button, message, Card, List,Image, Modal,DatePicker,Input,Typography} from 'antd'; +import React, { useState, useRef,useEffect } from 'react'; +import { history,useRequest } from 'umi'; +import { PageContainer, FooterToolbar } from '@ant-design/pro-layout'; +import type { ProColumns, ActionType } from '@ant-design/pro-table'; +import ProTable from '@ant-design/pro-table'; +import { ModalForm, ProFormText, ProFormTextArea } from '@ant-design/pro-form'; +import type { ProDescriptionsItemProps } from '@ant-design/pro-descriptions'; +import ProDescriptions from '@ant-design/pro-descriptions'; +import type { FormValueType } from './components/UpdateForm'; +import UpdateForm from './components/UpdateForm'; +import { copySubject, addSubject, updateSubject, removeSubject, querySubjectList, queryListChapterBySubject } from './service'; +import type { TableListItem, TableListPagination } from './data'; +import { queryCourseListByTag } from '../option/service'; +const { confirm } = Modal; +const { RangePicker } = DatePicker; +const { Search } = Input; +const { Paragraph } = Typography; +import pic from './image/tip.svg'; +import styles from './style.less'; +// import useEffect = require("react"); +import moment from 'moment'; +const dateFormat='YYYY-MM-DD'; +const TableList: React.FC = () => { + /** 新建窗口的弹窗 */ + const [createModalVisible, handleModalVisible] = useState(false); + const [updateModalVisible, handleUpdateModalVisible] = useState(false); + const [detailModalVisible, handleDetailModalVisible] = useState(false); + const [courseList,setCourseList]=useState([]); + const [date,setDate]=useState(''); + const [beginTime,setBeginTime]=useState(''); + const [endTime,setEndTime]=useState(''); + const [subjectName,setSubjectName]=useState(''); + const [pageNumber,setPageNumber]=useState([]); + const [total,setTotal]=useState(0); + const actionRef = useRef(); + const actionChapterRef = useRef(); + + const [currentRow, setCurrentRow] = useState(); + const [selectedRowsState, setSelectedRows] = useState([]); + const chapterColumns: ProColumns[] = [ + { + title: '序号', + key: 'index', + valueType: 'indexBorder', + width: 48, + }, + { + title: '章节名称', + dataIndex: 'chapter_name', + valueType: 'text', + hideInTable: false, + hideInDescriptions: false, + hideInForm: false, + hideInSearch: true, + }, + { + title: '简单介绍', + dataIndex: 'chapter_describe', + valueType: 'textarea', + sorter: false, + hideInTable: false, + hideInForm: false, + hideInSearch: true, + renderText: (val: string) => (
), + }, + { + title: '包含课程', + valueType: 'select', + dataIndex: 'course_names', + sorter: false, + hideInTable: false, + hideInForm: false, + hideInSearch: true, + fieldProps: { + mode: "multiple" + }, + renderText: (val: string) => `${val}`, + request: async (params) => { + const { tags } = params; + const { data: Items } = await queryCourseListByTag({ tag_ids: tags?.toString() }); + console.log('queryCourseListByTag...') + const courses = [] + for (let i = 0; i < Items?.length; i++) { + courses.push({ label: Items[i]?.course_name, value: Items[i]?.course_id }) + } + console.log(courses, 'courses:::'); + return courses; + }, + + }, + { + title: '学时', + dataIndex: 'course_minutes', + valueType: 'text', + sorter: false, + hideInTable: false, + hideInForm: true, + hideInSearch: true, + renderText: (val: string) => `${val}学时`, + }, + ]; + const { data, run, loading } = useRequest(() => { + return querySubjectList({ + begin_time:beginTime, + end_time:endTime, + page_number:pageNumber, + page_size:9999, + subject_name:subjectName, + }); + },{ + onSuccess:(result)=>{ + console.log('result9999',result); + setCourseList(result.list); + setTotal(result.total_row) + + } + }); + const showConfirm=async (record)=>{ + confirm({ + title: '确认删除主题吗?', + centered:true, + onOk() { + handleRemove([{ key: record?.subject_id }]); // 调用批量删除函数(如果接口不支持批量需要在service中处理) + setSelectedRows([]); + actionRef.current?.reloadAndRest?.(); + }, + onCancel() { + }, + }); + }; + + const handleRemove = async (selectedRows: TableListItem[]) => { + const hide = message.loading('正在删除'); + if (!selectedRows) return true; + + try { + const { code, msg } = await removeSubject({ + key: selectedRows.map((row) => row.key), + }); + hide(); + if (code === 2000) { + message.success('删除成功,即将刷新'); + run() + } else { + message.warning(msg); + } + return true; + } catch (error) { + hide(); + message.error('删除失败,请重试'); + return false; + } + }; + + useEffect(()=>{ + run() + },[beginTime,endTime,subjectName]) + + return ( + +
+
+ 培训主题: + { + setSubjectName(e.target.value); + }} + + /> + 创建时间: + { + setDate([moment(dateStrings[0],'YYYY-MM-DD'),moment(dateStrings[1],'YYYY-MM-DD')]) + setBeginTime(dateStrings[0]) + setEndTime(dateStrings[1]); + + }}/> + +
+
+ + 已筛选{total}个 + { + setBeginTime(''); + setEndTime(''); + setSubjectName(''); + setDate('') + }} + >清空 +
+
+ { + if (item && item.subject_id) { + return ( + + {item?.subject_name}} + hoverable + className={styles.card} + actions={[]} + + > + } + title={false} + description={ + <> + + + {/*{item.subject_describe}*/} +
+ + + +
+ { + item.b_use===0? +
待发布
: +
+ 章节数:{item.total_chapter_number} 个
+ 课程数:{item.total_course_number} 个
+ 考核学时:{item.total_course_minutes} 分钟 +
+ } +
+
+ +
+ { + item.isExistRelation?'': + [,
] + + } + +
+ { + item.isExistRelation?'': + [ ,
] + + } + +
+ + } + /> + + + ); + } + }} + /> +
+
+ { + setCurrentRow(undefined); // 设置当前行 + handleDetailModalVisible(false); + }} + footer={null} + centered + > + {currentRow?.subject_id && ( + <> + { + console.log('step2 主题信息') + return Promise.resolve({ + success: true, + data: { id: '这是一段文本', object: '', date: '2020-07-30 08:00', duration: '', grade: 100, through: '>60', learn: '>20 min', times: 2 }, + }); + }}*/ + extra={false} + > + + {currentRow?.subject_name} + +
+ + + + + headerTitle={false} + actionRef={actionChapterRef} + rowKey="chapter_id" + options={false} + search={false} + toolBarRender={false} + request={async (value) => { + const { data } = await queryListChapterBySubject({ + subject_id: currentRow?.subject_id, + page_number: value?.current || 1, + page_size: value?.pageSize, + }); + return { + current: data?.page_number, + data: data?.list, + pageSize: data?.page_size, + success: true, + total: data?.total_row || 0, + }; + }} + // dataSource={list} + columns={chapterColumns} + rowSelection={false} + /> + + )} + + + ); +}; + +export default TableList; diff --git a/admin/src/pages/course/subject/step/index.tsx b/admin/src/pages/course/subject/step/index.tsx index 73c8c62..42bf8dd 100644 --- a/admin/src/pages/course/subject/step/index.tsx +++ b/admin/src/pages/course/subject/step/index.tsx @@ -614,7 +614,7 @@ export default () => { // console.log('values:新建', values); const success = await handleAddChapter({ ...values, - subject_id: params?.id || 0, + subject_id:subjectId, }); if (success) { handleCreateModalVisible(false); @@ -657,7 +657,7 @@ export default () => { // console.log('currentRow', currentRow) const success = await handleUpdateChapter({ ...values, - subject_id: params?.id || 0, + subject_id: subjectId, chapter_id: currentRow.chapter_id }); if (success) { diff --git a/admin/src/pages/course/subject/style.less b/admin/src/pages/course/subject/style.less new file mode 100644 index 0000000..fa7cc48 --- /dev/null +++ b/admin/src/pages/course/subject/style.less @@ -0,0 +1,118 @@ +@import '~antd/es/style/themes/default.less'; +@import './utils/utils.less'; + +.cardList { + .card { + :global { + .ant-card-meta-title { + margin-bottom: 12px; + & > a { + display: inline-block; + max-width: 100%; + color: @heading-color; + } + } + .ant-card-body:hover { + .ant-card-meta-title > a { + color: @primary-color; + } + } + } + } + .item { + height: 64px; + } + + :global { + .ant-list .ant-list-item-content-single { + max-width: 100%; + } + .ant-card-meta-description{ + height:100%; + } + .ant-card-grid{ + box-shadow:none; + height:100%; + } + } +} +:global { + .ant-card-meta-detail{ + height: 200px; + } +} +.extraImg { + width: 155px; + margin-top: -20px; + text-align: center; + img { + width: 100%; + } +} + +.newButton { + width: 100%; + height: 201px; + color: @text-color-secondary; + background-color: @component-background; + border-color: @border-color-base; +} + +.cardAvatar { + width: 270px; + height: 150px; + border-radius: 10px; +} + +.cardDescription { + .textOverflowMulti(); +} + +.pageHeaderContent { + position: relative; +} + +.contentLink { + margin-top: 16px; + a { + margin-right: 32px; + img { + width: 24px; + } + } + img { + margin-right: 8px; + vertical-align: middle; + } +} + +@media screen and (max-width: @screen-lg) { + .contentLink { + a { + margin-right: 16px; + } + } +} +@media screen and (max-width: @screen-md) { + .extraImg { + display: none; + } +} + +@media screen and (max-width: @screen-sm) { + .pageHeaderContent { + padding-bottom: 30px; + } + .contentLink { + position: absolute; + bottom: -4px; + left: 0; + width: 1000px; + a { + margin-right: 16px; + } + img { + margin-right: 4px; + } + } +} diff --git a/admin/src/pages/course/subject/utils/utils.less b/admin/src/pages/course/subject/utils/utils.less new file mode 100644 index 0000000..de1aa64 --- /dev/null +++ b/admin/src/pages/course/subject/utils/utils.less @@ -0,0 +1,50 @@ +.textOverflow() { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + word-break: break-all; +} + +.textOverflowMulti(@line: 3, @bg: #fff) { + position: relative; + max-height: @line * 1.5em; + margin-right: -1em; + padding-right: 1em; + overflow: hidden; + line-height: 1.5em; + text-align: justify; + &::before { + position: absolute; + right: 14px; + bottom: 0; + padding: 0 1px; + background: @bg; + content: '...'; + } + &::after { + position: absolute; + right: 14px; + width: 1em; + height: 1em; + margin-top: 0.2em; + background: white; + content: ''; + } +} + +// mixins for clearfix +// ------------------------ +.clearfix() { + zoom: 1; + &::before, + &::after { + display: table; + content: ' '; + } + &::after { + clear: both; + height: 0; + font-size: 0; + visibility: hidden; + } +} diff --git a/web/src/pages/course/list/index.tsx b/web/src/pages/course/list/index.tsx index 6760aa0..1e3f2ec 100644 --- a/web/src/pages/course/list/index.tsx +++ b/web/src/pages/course/list/index.tsx @@ -180,7 +180,7 @@ const CardList = () => {
第{item?.sort_no}讲
{item?.course_name}
-
{item?.course_hours*60}分钟
+
{item?.course_minutes}分钟
percent === 100 ? '100%' : `${percent}%`}