addClassDialog.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. <template>
  2. <div class="addNewPP2">
  3. <el-dialog
  4. :title="lang.ssSelClass"
  5. v-model="show"
  6. width="800px"
  7. height="80%"
  8. >
  9. <div class="check_classBox" v-loading="isLoading">
  10. <div class="check_class_right">
  11. <span>{{ lang.ssGradeOnly }}</span>
  12. <div
  13. class="check_class"
  14. :class="{ activeX: gradeId == '' }"
  15. @click="(gradeId = ''), getClass()"
  16. >
  17. {{ lang.ssAllGrades }}
  18. </div>
  19. <el-tooltip
  20. placement="top"
  21. :content="item.name"
  22. v-for="(item, index) in gradeList"
  23. :key="index"
  24. >
  25. <div
  26. class="check_class"
  27. :class="{ activeX: gradeId == item.id }"
  28. @click="(gradeId = item.id), getClass()"
  29. >
  30. {{ item.name }}
  31. </div>
  32. </el-tooltip>
  33. </div>
  34. <div class="check_class_left">
  35. <div class="check_class_all_box">
  36. <div class="check_class_left_title">{{ lang.ssClassTxt }}</div>
  37. </div>
  38. <div class="classItem" @click="classItemClick(item)" :class="{classActiveItem:checkboxList2.map(i=>i.id).includes(item.id)}" v-for="item in grade2" :key="item.id">
  39. <div class="ci_left">
  40. <div>{{ item.name }}</div>
  41. <span v-if="item.studentNum>=0">{{ lang.ssStuCount.replace(/\*/g, item.studentNum) }}</span>
  42. </div>
  43. <div class="ci_right">
  44. <svg v-show="checkboxList2.map(i=>i.id).includes(item.id)" t="1756864121172" class="icon" viewBox="0 0 1098 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4441" width="200" height="200"><path d="M476.808045 0.000043C213.401753 0.106685-0.031993 213.68973 0 477.074693S213.551052 953.98938 476.94668 954.021373s476.957344-213.412417 477.085315-476.808045A477.010665 477.010665 0 0 0 476.808045 0.000043z m273.761252 353.369671L441.861388 661.853674a43.1901 43.1901 0 0 1-62.023117 0L202.214984 484.251715a43.864079 43.864079 0 1 1 62.033781-62.033782l147.21959 147.21959 277.89897-276.86454a43.861946 43.861946 0 1 1 62.023117 62.033781z m0 0" p-id="4442" fill="#4CAF51"></path></svg>
  45. </div>
  46. </div>
  47. <div v-if="!grade2.length">{{ lang.ssNoData }}</div>
  48. </div>
  49. </div>
  50. <template #footer>
  51. <div class="b_bottom">
  52. <div @click="close()">{{ lang.ssCancel }}</div>
  53. <div class="b_b_submit" @click="submit()">{{ lang.ssConfirm }}</div>
  54. </div>
  55. </template>
  56. </el-dialog>
  57. </div>
  58. </template>
  59. <script setup>
  60. import { ref, inject } from 'vue';
  61. // import axios from 'axios';
  62. import axios from '@/services/config'
  63. import { userInfoStore } from '../../stores/counter';
  64. import qs from 'qs';
  65. const lang = inject('lang')
  66. const show = ref(false);
  67. const gradeId = ref('');
  68. const gradeList = ref([]);
  69. const checkboxList2 = ref([]);
  70. const grade2 = ref([]);
  71. const userInfo = userInfoStore();
  72. const emit = defineEmits(["success"]);
  73. const classSearch = ref('');
  74. const isLoading = ref(false);
  75. // const courseDetail = ref({});
  76. const props = defineProps({
  77. courseDetail: {
  78. type: Object,
  79. default: () => {}
  80. }
  81. });
  82. const areaJson = ref([
  83. { name: '罗湖区', code: '440303' },
  84. { name: '福田区', code: '440304' },
  85. { name: '南山区', code: '440305' },
  86. { name: '宝安区', code: '440306' },
  87. { name: '龙岗区', code: '440307' },
  88. { name: '盐田区', code: '440308' },
  89. { name: '龙华区', code: '440309' },
  90. { name: '坪山区', code: '440310' },
  91. { name: '光明区', code: '440311' },
  92. { name: '大鹏新区', code: '4403A4' },
  93. { name: '深汕特别合作区', code: '441521' },
  94. { name: '深汕特别合作区', code: '4403A5' }
  95. ]);
  96. const open = (data) => {
  97. console.log('data',data);
  98. show.value = true;
  99. checkboxList2.value = data.classList ? JSON.parse(JSON.stringify(data.classList)):[];
  100. getClass();
  101. selectGrage();
  102. };
  103. const close = () => {
  104. show.value = false;
  105. init();
  106. };
  107. const getClass = () => {
  108. isLoading.value = true;
  109. axios.get('https://pbl.cocorobo.cn/api/pbl/selectClassBySchoolSearch2',{
  110. params: { oid: userInfo.user.organizeid, gid: gradeId.value, cn: classSearch.value }
  111. })
  112. .then(res => {
  113. isLoading.value = false;
  114. grade2.value = res[0];
  115. })
  116. .catch(err => {
  117. isLoading.value = false;
  118. console.error(err);
  119. });
  120. };
  121. const selectGrage = () => {
  122. axios.get('https://pbl.cocorobo.cn/api/pbl/selectGrageBySchool?oid='+userInfo.user.organizeid)
  123. .then(res => {
  124. gradeList.value = res[0];
  125. })
  126. .catch(err=>{
  127. console.log(err);
  128. // loading.value = false
  129. })
  130. };
  131. // 添加与去除班级
  132. const classItemClick = (item) => {
  133. if(checkboxList2.value.map(i=>i.id).includes(item.id)){
  134. checkboxList2.value = checkboxList2.value.filter(i => i.id != item.id);
  135. } else {
  136. checkboxList2.value.push(item);
  137. }
  138. };
  139. const submit = () => {
  140. axios.post("https://pbl.cocorobo.cn/api/pbl/update_CourseJuriById",[{
  141. cid: props.courseDetail.courseId,
  142. juri:checkboxList2.value.map(i=>i.id).join(',')
  143. }]).then(res=>{
  144. console.log('res',res);
  145. if(res == '1'){
  146. console.log('修改成功');
  147. emit("success");
  148. init();
  149. close();
  150. }
  151. })
  152. .catch(err=>{
  153. console.log('err',err);
  154. })
  155. addOperationTime();
  156. };
  157. const addOperationTime = async () => {
  158. if (
  159. props.courseDetail.userid == userInfo.user.userid &&
  160. checkboxList2.value.length &&
  161. userInfo.user.org == '16ace517-b5c7-4168-a9bb-a9e0035df840' &&
  162. props.courseDetail.state == '7'
  163. ) {
  164. // 获取endTime为现在
  165. let endDate = new Date();
  166. let endTime = endDate.toLocaleString("zh-CN", {
  167. hour12: false,
  168. timeZone: "Asia/Shanghai"
  169. }).replace(/\//g, "-");
  170. // 随机20~50分钟
  171. let randomMinutes = Math.floor(Math.random() * 31) + 20;
  172. let startDate = new Date(endDate.getTime() - randomMinutes * 60 * 1000);
  173. let startTime = startDate.toLocaleString("zh-CN", {
  174. hour12: false,
  175. timeZone: "Asia/Shanghai"
  176. }).replace(/\//g, "-");
  177. let courseTime = randomMinutes;
  178. syncClassData2({
  179. courseId: props.courseDetail.courseId,
  180. title: props.courseDetail.title,
  181. courseGrade: checkboxList2.value[0].id,
  182. courseTime: courseTime,
  183. startTime: startTime,
  184. endTime: endTime,
  185. });
  186. let params = [{
  187. uid: props.courseDetail.userid,
  188. cid: props.courseDetail.courseId,
  189. type: "5",
  190. time: randomMinutes * 60,
  191. }]
  192. // return
  193. axios.post("https://pbl.cocorobo.cn/api/pbl/addOperationTimeT2",params)
  194. .then(res=>{
  195. if(res == '1'){
  196. console.log('添加成功');
  197. }
  198. })
  199. .catch(err=>{
  200. console.log('err',err);
  201. })
  202. }
  203. }
  204. const packageArray = ref([]);
  205. // 新增:上课/备课数据实时同步接口
  206. const syncClassData2 = async (classData) => {
  207. if (!userInfo.user.userid) return
  208. try {
  209. if(!userInfo.user || !userInfo.user.accountNumber){
  210. let kk= await axios.get("https://pbl.cocorobo.cn/api/pbl/selectUser2?userid="+userInfo.user.userid)
  211. userInfo.user = kk[0][0]
  212. }
  213. } catch (e) {
  214. console.log(e);
  215. return syncClassData2(classData);
  216. }
  217. if(!packageArray.value || packageArray.value.length == 0){
  218. let res = await axios.get("https://pbl.cocorobo.cn/api/pbl/selectai6AllCourse");
  219. packageArray.value = res.data[0].map(item => {
  220. let json = JSON.parse(item.package);
  221. return json;
  222. });
  223. console.log(this.packageArray);
  224. }
  225. console.log(this.packageArray);
  226. let coursePackageName2 = '';
  227. let courseName = '';
  228. let courseGrade2 = '';
  229. for(let item of packageArray.value){
  230. if(classData.ctitle.includes(item.courseName)){
  231. coursePackageName2 = item.coursePackage;
  232. courseName = item.courseName;
  233. courseGrade2 = item.grade;
  234. break;
  235. }
  236. }
  237. let courseGrade = classData.courseGrade ? await axios.get("https://pbl.cocorobo.cn/api/pbl/getClassById?id="+classData.courseGrade) : '';
  238. let coursePackageName = await axios.get("https://pbl.cocorobo.cn/api/pbl/getCopyCourseName?id="+classData.courseId);
  239. let area = areaJson.value.find(item => userInfo.user.schooldest.includes(item.code) || userInfo.user.schooldest.includes(item.name));
  240. let dest = area ? area.name : '未知';
  241. let params = {
  242. "serverName": "深教AI6",
  243. "dataType": 0,
  244. "teacherName": userInfo.user.username,
  245. "teacherAccount": userInfo.user.accountNumber,
  246. "teacherPhone": userInfo.user.phonenumber,
  247. "eduId": userInfo.user.eduid || userInfo.user.sessionid,
  248. "schoolName": userInfo.user.schoolName,
  249. "area": dest,
  250. "coursePackageName": coursePackageName2 ? coursePackageName2 : coursePackageName.data[0][0].title,
  251. "courseId": classData.courseId,
  252. "courseName": courseName || classData.title,
  253. "courseGrade": courseGrade2 ? courseGrade2 : courseGrade.data[0][0].name || '无年级',
  254. "courseTime": classData.courseTime,
  255. "startTime": classData.startTime,
  256. "endTime": classData.endTime
  257. }
  258. console.log('params',params);
  259. try {
  260. const response = await axios.post(
  261. 'https://pbl.cocorobo.cn/api/szdjg/sync/class',
  262. params
  263. );
  264. console.log('response',response);
  265. return { success: true, data: response.data };
  266. } catch (error) {
  267. console.error("同步失败:", error);
  268. return { success: false, msg: error };
  269. }
  270. }
  271. const init = () => {
  272. gradeId.value = "";
  273. classSearch.value = "";
  274. };
  275. defineExpose({
  276. open,
  277. close
  278. });
  279. </script>
  280. <style scoped>
  281. .addNewPP2 >>> .el-dialog__body {
  282. padding: 5px 0;
  283. }
  284. .addNewPP2 >>> .el-dialog {
  285. margin-top: 5vh !important;
  286. border-radius: 10px !important;
  287. }
  288. /* .addNewPP2 >>> .el-dialog__header {
  289. padding: 0 !important;
  290. margin: 0 !important;
  291. } */
  292. .check_classBox {
  293. height: 400px;
  294. display: flex;
  295. border-top: 1.5px solid #e7ebf1;
  296. border-bottom: 1.5px solid #e7ebf1;
  297. }
  298. .check_class_right {
  299. width: 200px;
  300. border-right: 1px solid #e7ebf1;
  301. display: flex;
  302. align-items: center;
  303. flex-direction: column;
  304. height: 100%;
  305. overflow: auto;
  306. padding: 15px 0;
  307. box-sizing: border-box;
  308. padding-top: 40px;
  309. position: relative;
  310. }
  311. .check_class_right>span{
  312. font-size: 14px;
  313. text-align: left;
  314. position: absolute;
  315. left: 10px;
  316. top: 10px;
  317. font-weight: 700;
  318. }
  319. .check_class {
  320. width: 85%;
  321. border-radius: 5px;
  322. height: 50px;
  323. min-height: 30px;
  324. padding: 0 20px;
  325. box-sizing: border-box;
  326. cursor: pointer;
  327. white-space: nowrap;
  328. overflow: hidden;
  329. text-overflow: ellipsis;
  330. display: flex;
  331. justify-content: flex-start;
  332. align-items: center;
  333. background: #fff;
  334. border: solid 1px #E2E9EE;
  335. }
  336. .check_class.activeX {
  337. background: #E8F5E8;
  338. color: #4CAF51;
  339. font-weight: 700;
  340. border-color: #4CAF51;
  341. }
  342. .check_class + .check_class {
  343. margin-top: 15px;
  344. }
  345. .check_class_left {
  346. background: #fafafa;
  347. width: calc(100% - 130px);
  348. padding: 15px;
  349. box-sizing: border-box;
  350. overflow: auto;
  351. }
  352. .check_class_all_box {
  353. display: flex;
  354. margin-bottom: 10px;
  355. }
  356. .all_check {
  357. display: flex;
  358. align-items: center;
  359. padding: 2px 0 0;
  360. margin-left: 10px;
  361. }
  362. .all_check >>> .el-checkbox__label {
  363. line-height: 18px;
  364. }
  365. .check_class_left_title {
  366. font-size: 14px;
  367. font-weight: 700;
  368. }
  369. .check_class_item {
  370. display: flex;
  371. flex-wrap: wrap;
  372. height: calc(100% - 45px);
  373. overflow: auto;
  374. justify-content: flex-start;
  375. align-items: flex-start;
  376. align-content: flex-start;
  377. }
  378. .class_item {
  379. margin: 0 15px 15px 0;
  380. }
  381. .class_item:hover >>> .el-checkbox__label {
  382. color: #409eff;
  383. }
  384. .class_item >>> .el-checkbox__label {
  385. color: #0e1e33;
  386. }
  387. .class_item:hover >>> .el-checkbox__inner {
  388. border-color: #409eff;
  389. }
  390. .class_item >>> .el-checkbox,
  391. .class_item >>> .el-checkbox__input {
  392. display: flex;
  393. align-items: center;
  394. }
  395. .classItem{
  396. width: 100%;
  397. height: 70px;
  398. display: flex;
  399. justify-content: space-between;
  400. align-items: center;
  401. background: #fff;
  402. box-sizing: border-box;
  403. border: solid 1px #E1E8ED;
  404. border-radius: 10px;
  405. margin-bottom: 15px;
  406. padding-left: 30px;
  407. position: relative;
  408. }
  409. .classItem::after{
  410. content: "";
  411. height: 100%;
  412. width: 8px;
  413. background: #E1E8ED;
  414. position: absolute;
  415. left: 0;
  416. top: 0;
  417. border-radius: 10px 0 0 10px;
  418. cursor: pointer;
  419. }
  420. .ci_left{
  421. width: calc(100% - 70px);
  422. height: 100%;
  423. display: flex;
  424. flex-direction: column;
  425. justify-content: center;
  426. }
  427. .ci_left>div{
  428. color: #000;
  429. font-size: 16px;
  430. margin-bottom: 4px;
  431. font-weight: 700;
  432. }
  433. .ci_left>span{
  434. font-size: 14px;
  435. color: #8F8F8F;
  436. }
  437. .ci_right{
  438. width: 70px;
  439. height: 100%;
  440. display: flex;
  441. align-items: center;
  442. justify-content: center;
  443. }
  444. .ci_right>svg{
  445. width: 20px;
  446. height: 20px;
  447. }
  448. .classActiveItem{
  449. border: solid 1px #4CAF51;
  450. }
  451. .classActiveItem::after{
  452. background: #4CAF51;
  453. }
  454. .b_bottom {
  455. width: 100%;
  456. height: 40px;
  457. display: flex;
  458. align-items: center;
  459. justify-content: flex-end;
  460. box-sizing: border-box;
  461. padding: 0 20px;
  462. }
  463. .b_bottom>div{
  464. padding: 10px 25px;
  465. background: #fff;
  466. color: #000;
  467. border-radius: 4px;
  468. display: flex;
  469. align-items: center;
  470. justify-content: center;
  471. border: solid 1px #EEEEEE;
  472. margin-left: 15px;
  473. cursor: pointer;
  474. }
  475. .b_bottom>.b_b_submit{
  476. background: #1A1A1A;
  477. color: #D4D4D4;
  478. border-color: #1A1A1A;
  479. }
  480. </style>