trainPlan.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. <template>
  2. <div>
  3. <el-alert
  4. title="训练规划"
  5. :closable="false"
  6. class="alert marginBtm22"
  7. type="info"
  8. >
  9. <template slot="title">
  10. <div class="alerTitle">
  11. <p>
  12. 师资安排
  13. <span style="color: red; font-weight: bold"
  14. >该乐团声部课剩余 2 课时、合奏课 4 课时未进行教学规划</span
  15. >
  16. </p>
  17. <el-button type="text" @click="addPlan">+新增训练规划</el-button>
  18. </div>
  19. </template>
  20. </el-alert>
  21. <save-form
  22. :inline="true"
  23. class="searchForm"
  24. save-key="teamTrainPlan"
  25. ref="searchForm"
  26. @submit="search"
  27. @reset="onReSet"
  28. :model.sync="searchForm"
  29. >
  30. <el-form-item prop="year" label="年份">
  31. <el-date-picker
  32. style="width: 180px !important"
  33. v-model="searchForm.year"
  34. type="year"
  35. value-format="yyyy"
  36. placeholder="选择年"
  37. :clearable="false"
  38. @change="changeYear"
  39. >
  40. </el-date-picker>
  41. </el-form-item>
  42. <el-form-item prop="term" label="学期">
  43. <el-select
  44. :disabled="!searchForm.year"
  45. class="multiple"
  46. filterable
  47. style="width: 180px !important"
  48. v-model.trim="searchForm.term"
  49. placeholder="请选择学期"
  50. @change="changeTerm"
  51. >
  52. <el-option value="0" label="上学期"></el-option>
  53. <el-option value="1" label="下学期"></el-option>
  54. </el-select>
  55. </el-form-item>
  56. <el-form-item prop="classGroupId" label="班级">
  57. <el-select
  58. :disabled="!searchForm.term || !searchForm.year"
  59. v-model.trim="searchForm.classGroupId"
  60. filterable
  61. placeholder="请选择班级"
  62. >
  63. <el-option
  64. v-for="(item, index) in classList"
  65. :key="index"
  66. :value="item.id"
  67. :label="item.name"
  68. ></el-option>
  69. </el-select>
  70. </el-form-item>
  71. <el-form-item
  72. label="课程类型"
  73. prop="courseType"
  74. :rules="[
  75. { required: true, message: '请选择课程类型', trigger: 'blur' },
  76. ]"
  77. >
  78. <el-select
  79. :disabled="
  80. !searchForm.term || !searchForm.year || !searchForm.classGroupId
  81. "
  82. style="width: 180px !important"
  83. class="multiple"
  84. v-model.trim="searchForm.courseScheduleType"
  85. filterable
  86. placeholder="课程类型"
  87. >
  88. <el-option
  89. v-for="(item, index) in courseTypeList"
  90. :key="index"
  91. :label="item.label"
  92. :value="item.value"
  93. ></el-option>
  94. </el-select>
  95. </el-form-item>
  96. </save-form>
  97. <div class="timerWrap">
  98. <div class="timerList">
  99. <el-timeline>
  100. <!-- timestamp="2018/4/12" :timestamp="item.timestamp" -->
  101. <!-- {timer:time,index:`第${index+1}次训练`,courseType:filterCourseType[val],timestamp:timestamp} -->
  102. <el-timeline-item
  103. v-for="item in planList"
  104. :key="item.timestamp"
  105. placement="top"
  106. :hide-timestamp="true"
  107. >
  108. {{ item.index }}
  109. <div class="timeline">
  110. <h4 class="time">{{ item.timer }}</h4>
  111. <p class="cuorseType">{{ item.courseType }}</p>
  112. <p class="concat"> <Tooltip :content="item.plan.value || '暂无规划'" /></p>
  113. <el-button
  114. class="button"
  115. :disabled="!item.plan.value || !item.timer"
  116. type="text"
  117. @click="resetPlan(item)"
  118. >修改</el-button
  119. >
  120. <el-button
  121. class="button"
  122. :disabled="Boolean(item.timer)"
  123. type="text"
  124. @click="detelePlan(item)"
  125. >删除</el-button
  126. >
  127. </div>
  128. </el-timeline-item>
  129. </el-timeline>
  130. </div>
  131. </div>
  132. <el-dialog
  133. :title="planTitle"
  134. :visible.sync="planVisible"
  135. width="1100px"
  136. v-if="planVisible"
  137. >
  138. <addplan
  139. ref="addPlan"
  140. :form="searchForm"
  141. :planList="planList"
  142. :currentIndex="currentIndex"
  143. :maxPlansNum="maxPlansNum"
  144. :courseTypeList="courseTypeList"
  145. :classList="classList"
  146. :isAdd="isAdd"
  147. :activeItem="activeItem"
  148. @close="close"
  149. />
  150. <span slot="footer" class="dialog-footer">
  151. <el-button @click="planVisible = false">取 消</el-button>
  152. <el-button type="primary" @click="submitPlan">确 定</el-button>
  153. </span>
  154. </el-dialog>
  155. </div>
  156. </template>
  157. <script>
  158. import { getMusicGroupAllClass } from "@/api/buildTeam";
  159. import { getCourseType, getPlanCourseNum, getMusicGroupTrainPlan } from "./api";
  160. import { filterCourseType } from "@/constant/index";
  161. import addplan from "./modals/addPlan";
  162. import Tooltip from '@/components/Tooltip/index'
  163. export default {
  164. components: { addplan ,Tooltip},
  165. data() {
  166. return {
  167. searchForm: {
  168. year: "",
  169. classGroupId: "",
  170. term: "",
  171. courseScheduleType: "",
  172. musicGroupId: "",
  173. },
  174. classList: [],
  175. courseTypeList: [],
  176. planList: [],
  177. planTitle: "",
  178. planVisible: false,
  179. currentIndex: 0,
  180. addIndex:0,
  181. resetIndex:0,
  182. maxPlansNum: 0,
  183. isAdd: false,
  184. activeItem:null
  185. };
  186. },
  187. created() {
  188. let date = new Date();
  189. this.searchForm.year = String(date.getFullYear());
  190. // console.log('year',date.getFullYear())
  191. let month = date.getMonth() + 1;
  192. if (month > 3 && month < 8) {
  193. this.searchForm.term = "0";
  194. } else {
  195. this.searchForm.term = "1";
  196. }
  197. },
  198. mounted() {
  199. this.teamid = this.$route.query.id;
  200. this.getMusicClass();
  201. },
  202. methods: {
  203. search() {},
  204. onReSet() {},
  205. getMusicClass() {
  206. getMusicGroupAllClass({ musicGroupId: this.teamid }).then((res) => {
  207. if (res.code == 200) {
  208. this.classList = res.data;
  209. if (this.classList.length < 1) {
  210. this.$message.error("当前乐团暂无班级");
  211. return;
  212. }
  213. this.searchForm.classGroupId = this.classList[0].id;
  214. }
  215. });
  216. },
  217. async getCourseList(obj) {
  218. try {
  219. this.searchForm.courseScheduleType = "";
  220. const res = await getCourseType(obj);
  221. if (!res.data || res.data.length <= 0) {
  222. this.$message.error("当前学期暂无课程类型");
  223. } else {
  224. this.courseTypeList = [];
  225. res.data.forEach((course) => {
  226. if (filterCourseType[course]) {
  227. this.courseTypeList.push({
  228. label: filterCourseType[course],
  229. value: course,
  230. });
  231. }
  232. });
  233. this.searchForm.courseScheduleType = this.courseTypeList[0].value;
  234. }
  235. } catch (e) {
  236. console.log(e);
  237. }
  238. },
  239. changeYear(val) {
  240. if (val) {
  241. if (this.searchForm.classGroupId && this.searchForm.term) {
  242. let obj = {
  243. classGroupId: this.searchForm.classGroupId,
  244. musicGroupId: this.teamid,
  245. term: this.searchForm.term,
  246. year: val,
  247. };
  248. this.getCourseList(obj);
  249. }
  250. } else {
  251. this.searchForm.courseScheduleType = "";
  252. }
  253. },
  254. changeTerm(val) {
  255. if (val) {
  256. if (this.searchForm.classGroupId && this.searchForm.year) {
  257. let obj = {
  258. classGroupId: this.searchForm.classGroupId,
  259. musicGroupId: this.teamid,
  260. term: val,
  261. year: this.searchForm.year,
  262. };
  263. this.getCourseList(obj);
  264. }
  265. } else {
  266. this.searchForm.courseScheduleType = "";
  267. }
  268. },
  269. addPlan() {
  270. if (this.maxPlansNum > 0) {
  271. this.planTitle = "新增训练规划";
  272. this.isAdd = true;
  273. this.activeItem = null;
  274. this.planVisible = true;
  275. this.currentIndex = this.addIndex;
  276. } else {
  277. this.$message.error("已添加所有课时规划");
  278. }
  279. },
  280. submitPlan() {
  281. this.$refs.addPlan.submit();
  282. },
  283. close() {
  284. this.planVisible = false;
  285. let obj = {
  286. classGroupId: this.searchForm.classGroupId,
  287. musicGroupId: this.teamid,
  288. term: this.searchForm.term,
  289. year: this.searchForm.year,
  290. courseScheduleType: this.searchForm.courseScheduleType,
  291. };
  292. console.log(obj);
  293. this.getList(obj);
  294. },
  295. async getList(obj) {
  296. try {
  297. const res2 = await getMusicGroupTrainPlan(obj);
  298. let dayjs = this.$helpers.dayjs;
  299. let timestamp;
  300. // 判断 是规划多 还是课多
  301. let classDates = res2.data.classDates;
  302. let musicGroupTrainPlans = res2.data.musicGroupTrainPlans;
  303. if (classDates.length < 1) {
  304. this.$message.error("当前学期该班级暂无此类型课程");
  305. return;
  306. }
  307. if (classDates.length >= musicGroupTrainPlans.length) {
  308. this.planList = res2.data.classDates.map((time, index) => {
  309. let dayStr = time.substring(0, 19);
  310. timestamp = dayjs(dayStr).valueOf();
  311. return {
  312. num:index + 1,
  313. timer: time,
  314. index: `第${index + 1}次训练`,
  315. courseType: filterCourseType[this.searchForm.courseScheduleType],
  316. timestamp: timestamp,
  317. plan: null,
  318. };
  319. });
  320. this.addIndex = musicGroupTrainPlans.length + 1;
  321. this.maxPlansNum = classDates.length - musicGroupTrainPlans.length;
  322. this.planList.forEach((item, index) => {
  323. item.plan = {
  324. id: res2.data.musicGroupTrainPlans[index]?.id,
  325. value: res2.data.musicGroupTrainPlans[index]?.plan,
  326. };
  327. });
  328. } else {
  329. // 规划多 课少
  330. this.planList = res2.data.musicGroupTrainPlans.map((item, index) => {
  331. return {
  332. num:index + 1,
  333. timer: null,
  334. index: `第${index + 1}次训练`,
  335. courseType: filterCourseType[this.searchForm.courseScheduleType],
  336. timestamp: null,
  337. plan: { id: item.id, value: item.plan },
  338. };
  339. });
  340. this.planList.forEach((item, index) => {
  341. let time = res2.data?.classDates[index];
  342. let timestamp;
  343. if (time) {
  344. let dayStr = time.substring(0, 19);
  345. timestamp = dayjs(dayStr).valueOf();
  346. }
  347. item.timer = res2.data?.classDates[index];
  348. item.timestamp = timestamp;
  349. });
  350. }
  351. } catch (e) {
  352. console.log(e);
  353. }
  354. },
  355. // 删除尚未接完
  356. detelePlan(item) {
  357. this.$confirm("确定删除该规划?", "提示", {
  358. confirmButtonText: "确定",
  359. cancelButtonText: "取消",
  360. type: "warning",
  361. })
  362. .then(() => {
  363. orderDelete({ orderId: row.id }).then((res) => {
  364. if (res.code === 200) {
  365. this.$message.success("删除成功");
  366. this.getList();
  367. // this.routeOrderStatus = false;
  368. }
  369. });
  370. })
  371. .catch();
  372. },
  373. // 修改
  374. resetPlan(item){
  375. this.planTitle = "修改训练规划";
  376. this.isAdd = false;
  377. this.activeItem = item;
  378. this.currentIndex = item.num;
  379. this.planVisible = true;
  380. }
  381. },
  382. watch: {
  383. "searchForm.classGroupId"(val) {
  384. if (val) {
  385. if (this.searchForm.year && this.searchForm.term) {
  386. let obj = {
  387. classGroupId: val,
  388. musicGroupId: this.teamid,
  389. term: this.searchForm.term,
  390. year: this.searchForm.year,
  391. };
  392. this.getCourseList(obj);
  393. }
  394. } else {
  395. this.searchForm.courseScheduleType = "";
  396. }
  397. },
  398. "searchForm.courseScheduleType": {
  399. immediate: true,
  400. async handler(val) {
  401. if (
  402. val &&
  403. this.teamid &&
  404. this.searchForm.term &&
  405. this.searchForm.year &&
  406. this.searchForm.classGroupId
  407. ) {
  408. // 请求列表接口
  409. let obj = {
  410. classGroupId: this.searchForm.classGroupId,
  411. musicGroupId: this.teamid,
  412. term: this.searchForm.term,
  413. year: this.searchForm.year,
  414. courseScheduleType: val,
  415. };
  416. this.getList(obj);
  417. }
  418. },
  419. },
  420. },
  421. };
  422. </script>
  423. <style lang="scss" scoped>
  424. .marginBtm22 {
  425. margin-bottom: 22px;
  426. }
  427. .timerWrap {
  428. position: relative;
  429. // .topDot {
  430. // width: 30px;
  431. // height: 30px;
  432. // background-color: red;
  433. // position: absolute;
  434. // top: 0;
  435. // left: 50%;
  436. // margin-left: -15px;
  437. // }
  438. // .bottomDot {
  439. // position: absolute;
  440. // width: 30px;
  441. // height: 30px;
  442. // background-color: blue;
  443. // bottom: 0;
  444. // left: 50%;
  445. // margin-left: -15px;
  446. // }
  447. .timerList {
  448. padding: 30px 16px;
  449. overflow: auto;
  450. height: 300px;
  451. .timeline {
  452. display: flex;
  453. flex-direction: row;
  454. align-items: center;
  455. width: 100%;
  456. .time {
  457. width: 200px;
  458. }
  459. .cuorseType {
  460. width: 120px;
  461. text-align: center;
  462. }
  463. .concat {
  464. flex: 1;
  465. overflow: hidden;
  466. text-overflow: ellipsis;
  467. white-space: nowrap;
  468. }
  469. .button {
  470. width: 40px;
  471. }
  472. }
  473. }
  474. }
  475. /deep/.alerTitle {
  476. width: 100%;
  477. display: flex;
  478. flex-direction: row;
  479. justify-content: space-between;
  480. .el-button {
  481. padding: 0 20px !important;
  482. }
  483. }
  484. /deep/.el-alert__content {
  485. flex: 1;
  486. }
  487. .searchForm {
  488. padding: 0 16px;
  489. }
  490. </style>