TaskMng.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <script setup lang="ts">
  2. import { ref, onMounted, getCurrentInstance } from "vue";
  3. import { getTaskList, deleteTask, publishTask as pubTask, finishTask } from "../../api/techer/taskMng";
  4. import { Search } from "@element-plus/icons-vue";
  5. import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
  6. import router from '../../router/index'
  7. import { useRoute } from "vue-router";
  8. const loading = ref(false);
  9. const taskType = ref(null);
  10. const keyword:any = ref(null);
  11. const taskId = ref("");
  12. const size = ref(8);
  13. const page = ref(1);
  14. const total = ref(1);
  15. const taskData = ref([]);
  16. const searchByType = (type:any) => {
  17. taskType.value = type;
  18. search();
  19. }
  20. const searchByPage = (e) => {
  21. page.value = e;
  22. search();
  23. }
  24. const search = () => {
  25. console.log(keyword.value, taskType.value);
  26. loading.value = true;
  27. console.log(page.value, size.value);
  28. getTaskList({
  29. pageNum: page.value,
  30. pageSize:size.value,
  31. state:taskType.value,
  32. keyword:keyword.value
  33. }).then((e:any) => {
  34. loading.value = false;
  35. if(e.data.code==0){
  36. let data=e.data.data;
  37. total.value = data.total;
  38. console.log(data);
  39. taskData.value = data.list;
  40. console.log(data);
  41. }
  42. })
  43. }
  44. const addTaskInfo = () => {
  45. router.push({
  46. path: "/TaskEditor",
  47. });
  48. }
  49. /**编辑任务 */
  50. const editTask = (id: any) => {
  51. console.log(id);
  52. if(taskId.value&&taskId.value==keyword.value){
  53. router.push({
  54. path: "/TaskEditor/"+id,
  55. query: {
  56. linkId:taskId.value
  57. }
  58. });
  59. }else{
  60. router.push({
  61. path: "/TaskEditor/"+id
  62. });
  63. }
  64. }
  65. const delTask = (id: any) => {
  66. deleteTask(id).then((e: any) => {
  67. if (e.status == 0) {
  68. ElMessage({
  69. message: '任务成功删除',
  70. type: 'success',
  71. });
  72. }
  73. else {
  74. ElMessage({
  75. message: '任务删除失败:' + e.data.msg ||"系统异常",
  76. type: 'error',
  77. });
  78. }
  79. });
  80. }
  81. const finishTaskById = (id: any) => {
  82. finishTask(id).then((e: any) => {
  83. if (e.data.code == 0) {
  84. ElMessage({
  85. message: '任务成功结束',
  86. type: 'success',
  87. });
  88. }
  89. else {
  90. ElMessage({
  91. message: '任务结束失败:' + e.data.msg || "系统异常",
  92. type: 'error',
  93. });
  94. }
  95. });
  96. }
  97. /**发布任务 */
  98. const publishTask = (id:any) => {
  99. pubTask(id).then((e: any) => {
  100. if (e.data.code == 0) {
  101. ElMessage({
  102. message: '任务成功发布',
  103. type: 'success',
  104. });
  105. search();
  106. } else {
  107. ElMessage({
  108. message: '任务发布失败:' + e.data.msg || "系统异常",
  109. type: 'error',
  110. });
  111. }
  112. });
  113. }
  114. /**批改作业 */
  115. const markingWorks = (id:any) => {
  116. router.push({
  117. path: "/TaskStudentScore/" + id+"/2",
  118. });
  119. }
  120. /*
  121. 查看成绩
  122. */
  123. const showStudResult = (id:any) => {
  124. router.push({
  125. path: "/TaskStatis/"+id,
  126. });
  127. }
  128. onMounted(() => {
  129. const route = useRoute();
  130. console.log(route.params.taskId );
  131. if (route.params.taskId != null && route.params.taskId.toString().length > 0) {
  132. taskId.value = route.params.taskId + "";
  133. console.log(taskId.value);
  134. keyword.value=route.params.taskId + "";
  135. }
  136. search();
  137. });
  138. </script>
  139. <template>
  140. <div class="task-panel">
  141. <div class="task-search">
  142. <el-button :type="taskType==null? 'primary':'default'" @click="searchByType(null)">全部</el-button>
  143. <el-button :type="taskType==1? 'primary':'default'" @click="searchByType(1)">未发布</el-button>
  144. <el-button :type="taskType==2? 'primary':'default'" @click="searchByType(2)">进行中</el-button>
  145. <el-button :type="taskType==3? 'primary':'default'" @click="searchByType(3)">已完成</el-button>
  146. <div class="task-search-panel">
  147. <span style="color: #757575; font-size:0.8rem; margin-right:1rem;" v-if="total>0">共{{total}}个实例任务</span>
  148. <el-input v-model="keyword" placeholder="输入搜索内容" :suffix-icon="Search" @change="search"/>
  149. </div>
  150. </div>
  151. <div class="task-main" v-loading="loading">
  152. <div class="task-add task-item" @click="addTaskInfo">
  153. <el-icon :size="60"><Plus /></el-icon>
  154. <p>新建实训任务</p>
  155. </div>
  156. <div v-for="item in taskData" class="task-item task-item-base">
  157. <div class="task-name">
  158. <span style="justify-self:start;margin-right:auto;">{{item.name}}</span>
  159. <el-button link type="primary" v-if="item.state==1" @click="editTask(item.id)">编辑</el-button>
  160. <el-popconfirm v-if="item.state==1" title="确定删除该条目" @confirm="delTask(item.id)">
  161. <template #reference>
  162. <el-button link type="danger" size="small">删除</el-button>
  163. </template>
  164. </el-popconfirm>
  165. <el-popconfirm v-if="item.state==2&&item.studentNum>0&&item.submitStudentNum/item.studentNum>0.99" title="确定要结束本次任务?" @confirm="finishTaskById(item.id)">
  166. <template #reference>
  167. <el-button link type="primary" size="small">结束任务</el-button>
  168. </template>
  169. </el-popconfirm>
  170. </div>
  171. <div class="task-desc">
  172. <div class="desc-text">
  173. <div class="desc-course desc-item"><div class="desc-icon"></div>{{item.courseName}}</div>
  174. <div class="desc-class desc-item"><div class="desc-icon"></div>{{item.schoolClassName}}</div>
  175. <div class="desc-stud desc-item"><div class="desc-icon"></div>{{item.studentNum||0}}人已分配任务</div>
  176. </div>
  177. <div class="desc-status" :class="{nopub:item.state==1,inproc:item.state==2,iscomplete:item.state==3}"></div>
  178. </div>
  179. <div class="task-opt">
  180. <div v-if="item.state<3">已完成</div>
  181. <div v-if="item.state==3">任务已结束</div>
  182. <div class="task-comp-list" v-if="item.state<3">
  183. <div class="task-com-item" v-for="stud in item.compDetail||[]">
  184. {{stud.name.length>2? stud.name.substring(stud.name.length-2,stud.name.length):stud.name}}
  185. </div>
  186. <div class="task-com-item plus">{{item.submitStudentNum>0?''+item.submitStudentNum:'0' }}</div>
  187. </div>
  188. <div class="task-opt-button">
  189. <!--<el-button type="primary" v-if="item.state==1" @click="publishTask()">发布</el-button>-->
  190. <el-popconfirm v-if="item.state==1" title="发布前确定任务没有问题" @confirm="publishTask(item.id)">
  191. <template #reference>
  192. <el-button type="primary" size="small">发布</el-button>
  193. </template>
  194. </el-popconfirm>
  195. <el-button type="primary" size="small" v-if="item.state==2" @click="showStudResult(item.id)">查看进度</el-button>
  196. <el-button type="primary" size="small" v-if="item.state==2" @click="markingWorks(item.id)">批改作业({{item.waitGradeNum}})</el-button>
  197. <el-button type="default" size="small" v-if="item.state==3" @click="showStudResult(item.id)">查看成绩</el-button>
  198. </div>
  199. </div>
  200. <el-progress v-show="item.state>1&&item.submitStudentNum>0" :percentage="item.studentNum>0? parseInt((item.submitStudentNum/item.studentNum)*100):0" style="height:100%;" :show-text="false"/>
  201. </div>
  202. </div>
  203. <div class="task-page">
  204. <el-pagination layout="prev, pager, next" :page-size="size" :current-page="page" :total="total" @current-change="searchByPage"/>
  205. </div>
  206. </div>
  207. </template>
  208. <style scoped>
  209. :deep(.el-pager li) {
  210. background-color: transparent;
  211. border: 1px solid #DEDDDD;
  212. margin: 0 5px;
  213. }
  214. :deep(.number.is-active) {
  215. color: #fff;
  216. background-color: var(--el-color-primary);
  217. }
  218. :deep(.btn-prev) {
  219. border: 1px solid #DEDDDD;
  220. }
  221. :deep(.btn-next) {
  222. border: 1px solid #DEDDDD;
  223. }
  224. .task-panel {
  225. margin: 1rem;
  226. margin-bottom: 1rem;
  227. height: calc(100% - 2rem);
  228. width: calc(100% - 2rem);
  229. background: #fff;
  230. display:grid;
  231. grid-template-rows:3rem 1fr 4rem;
  232. padding:3rem 8rem 1rem 8rem;
  233. box-sizing:border-box;
  234. }
  235. .task-search {
  236. display: flex;
  237. align-items: center;
  238. box-sizing: border-box;
  239. padding: 0 1rem;
  240. }
  241. .task-search-panel {
  242. justify-self: right;
  243. margin-left: auto;
  244. display: flex;
  245. white-space: nowrap;
  246. align-items: center;
  247. }
  248. .task-page {
  249. display: flex;
  250. align-items: center;
  251. justify-content: end;
  252. }
  253. .task-main {
  254. display: grid;
  255. grid-template-columns: 1fr 1fr 1fr;
  256. /* grid-template-rows:1fr 1fr 1fr;*/
  257. overflow-x: hidden;
  258. grid-gap: 3rem;
  259. grid-column-gap: 6rem;
  260. overflow: auto;
  261. padding: 1rem;
  262. justify-content: center;
  263. align-items: start;
  264. color: rgb(117, 117, 117);
  265. }
  266. .task-item {
  267. height: 16rem;
  268. width: 100%;
  269. background-color: #fff;
  270. box-shadow: 0px 0px 3px rgba(0,0,0,0.2);
  271. justify-self: center;
  272. }
  273. .task-add {
  274. color: #fff;
  275. display: flex;
  276. flex-direction: column;
  277. align-items: center;
  278. justify-content: center;
  279. background-color: var(--el-color-primary);
  280. }
  281. .task-add p {
  282. font-size: 20px;
  283. }
  284. .task-item-base {
  285. display:grid;
  286. grid-template-rows:3rem 1fr 4rem 6px;
  287. }
  288. .task-name {
  289. color: var(--el-color-primary);
  290. font-size: 1.2rem;
  291. margin: 1rem 2rem 0 2rem;
  292. box-sizing: border-box;
  293. display:flex;
  294. align-items:center;
  295. justify-content:end;
  296. }
  297. .task-desc {
  298. margin: 0.5rem 2rem 0 2rem;
  299. display:grid;
  300. grid-template-columns:18rem 1fr;
  301. }
  302. .desc-text {
  303. display: flex;
  304. flex-flow: column;
  305. white-space:nowrap;
  306. justify-content: space-around;
  307. }
  308. .task-opt {
  309. display: flex;
  310. margin: 0rem 2rem 0 2rem;
  311. align-items:center;
  312. }
  313. .task-comp-list {
  314. display:flex;
  315. }
  316. .task-com-item {
  317. margin-left: -10px;
  318. background-color: #FF9F73;
  319. height:2rem;
  320. width:2rem;
  321. color:#fff;
  322. border-radius:1rem;
  323. display:flex;
  324. align-items:center;
  325. justify-content:center;
  326. font-size:8px;
  327. /* box-shadow:rgba(0,0,0,0.3) 0px 0px 3px;*/
  328. border:1px solid #fff;
  329. box-sizing:border-box;
  330. }
  331. .task-com-item:first-child {
  332. margin-left:1rem;
  333. }
  334. .task-com-item.plus {
  335. background-color: var(--el-color-primary);
  336. border:none;
  337. }
  338. .task-opt-button {
  339. margin-left:auto;
  340. justify-self:end;
  341. }
  342. .desc-item {
  343. display:flex;
  344. align-items:center;
  345. }
  346. .desc-icon {
  347. background-image: url(@/assets/techer/task-icon-course.png);
  348. height:1.2rem;
  349. width:1.2rem;
  350. background-size:1.2rem;
  351. background-position:center;
  352. margin-right:0.5rem;
  353. }
  354. .desc-course .desc-icon {
  355. background-image: url(@/assets/techer/task-icon-course.png);
  356. }
  357. .desc-class .desc-icon {
  358. background-image: url(@/assets/techer/task-icon-class.png);
  359. }
  360. .desc-stud .desc-icon {
  361. background-image: url(@/assets/techer/task-icon-student.png);
  362. }
  363. .desc-status {
  364. background-size: 8rem 8rem;
  365. height: 8rem;
  366. width: 8rem;
  367. background-position: center;
  368. background-repeat: no-repeat;
  369. }
  370. .desc-status.nopub {
  371. background-image: url(@/assets/techer/task-mark-nopub.png);
  372. }
  373. .desc-status.iscomplete {
  374. background-image: url(@/assets/techer/task-mark-comp.png);
  375. }
  376. .desc-status.inproc {
  377. background-image: url(@/assets/techer/task-mark-inprocess.png);
  378. }
  379. </style>