myAnli.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. <template>
  2. <div class="center_content">
  3. <!-- <div
  4. style="
  5. display: flex;
  6. flex-direction: row;
  7. flex-wrap: nowrap;
  8. justify-content: space-between;
  9. align-items: center;
  10. "
  11. >
  12. <div></div>
  13. <el-button
  14. type="primary"
  15. style="background: rgb(112, 135, 228); width: 100px; margin-right: 3%"
  16. @click="goTo('/addRace')"
  17. >案例设计</el-button
  18. >
  19. </div> -->
  20. <div class="myAnliBox" v-if="anliBox.length > 0">
  21. <div class="anLi" v-for="(an, anIndex) in anliBox" :key="anIndex">
  22. <div class="anliTop">
  23. <div class="anliTopLeft">
  24. <div>比赛名称:广东省PBL案例征集</div>
  25. <div>案例组别:{{ an.typename ? an.typename : "暂无分类" }}</div>
  26. </div>
  27. <div class="anliTopRight">创建人:{{ an.name }}</div>
  28. </div>
  29. <div class="anliMiddle">
  30. <div class="anliBox">
  31. <div class="anliImg">
  32. <img
  33. :src="
  34. JSON.parse(an.info).cover && JSON.parse(an.info).cover.length
  35. ? JSON.parse(an.info).cover[0].url
  36. : noBanner
  37. "
  38. alt=""
  39. />
  40. </div>
  41. <div class="anliNav">
  42. <div>项目名称:{{ JSON.parse(an.info).title }}</div>
  43. <div>单位:{{ an.schoolName }}</div>
  44. <div class="xmjj" v-if="JSON.parse(an.info).courseText">
  45. {{ JSON.parse(an.info).courseText }}
  46. </div>
  47. <div class="personAndAutor">
  48. <div>总人数:</div>
  49. <div class="people">
  50. <div class="man">
  51. <img src="../../../../assets/people.png" alt />
  52. </div>
  53. <div class="person">
  54. {{
  55. an.info
  56. ? JSON.parse(an.info).autor.length +
  57. JSON.parse(an.info).tableData.length
  58. : 0
  59. }}人
  60. </div>
  61. </div>
  62. <div class="autorBox" v-if="JSON.parse(an.info).autor.length">
  63. <div>联系人:</div>
  64. <div
  65. class="Autor"
  66. v-for="(a, aIndex) in JSON.parse(an.info).autor"
  67. :key="aIndex"
  68. >
  69. {{ a.sn }}
  70. </div>
  71. </div>
  72. <div
  73. class="autorBox"
  74. v-if="JSON.parse(an.info).tableData.length"
  75. >
  76. <div>协作者:</div>
  77. <div
  78. class="Autor"
  79. v-for="(a, aIndex) in JSON.parse(an.info).tableData"
  80. :key="aIndex"
  81. >
  82. {{ a.sn }}
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. <div class="anliBottom">
  90. <div style="margin-top: 5px;" :class="{ isSubmit : an.state == 1 } " >
  91. 当前状态:{{ an.state == 0 ? "未提交" : "已提交" }}
  92. </div>
  93. <div class="bottomRight">
  94. <div class="rightButton" @click="updateState(an.id)">提交</div>
  95. <div class="rightButton" @click="exportAnli(an)">导出</div>
  96. <!-- <div class="rightButton" @click="goTo('/anliDetail?aid=' + an.id)">
  97. 开始教学
  98. </div> -->
  99. <div class="rightButton" @click="goTo('/addRace?aid=' + an.id)">
  100. 编辑
  101. </div>
  102. <div class="rightButton" @click="deleteAnli(an.id)">删除</div>
  103. <div
  104. class="rightButton"
  105. style="background: #225ac7"
  106. @click="lookDetail(an.id)"
  107. >
  108. 查看详情
  109. </div>
  110. </div>
  111. </div>
  112. </div>
  113. </div>
  114. <div class="noAnliBox" v-else>
  115. <img src="../../../../assets/icon/race/isNoMessage.png" alt="" />
  116. </div>
  117. </div>
  118. </template>
  119. <script>
  120. export default {
  121. props: ["userid", "oid"],
  122. data() {
  123. return {
  124. anliBox: [],
  125. noBanner: require("../../../../assets/noBanner.jpg"),
  126. };
  127. },
  128. methods: {
  129. goTo(path) {
  130. this.$router.push(path);
  131. },
  132. selectAnLi() {
  133. let params = {
  134. uid: this.userid,
  135. };
  136. this.ajax
  137. .get(this.$store.state.api + "selectRaceList", params)
  138. .then((res) => {
  139. this.anliBox = res.data[0];
  140. })
  141. .catch((err) => {
  142. console.error(err);
  143. });
  144. },
  145. updateState(id) {
  146. this.$confirm("确定提交此案例吗?", "提示", {
  147. confirmButtonText: "确定",
  148. cancelButtonText: "取消",
  149. type: "warning",
  150. })
  151. .then(() => {
  152. let params = {
  153. id: id,
  154. };
  155. this.ajax
  156. .get(this.$store.state.api + "updateRaceState", params)
  157. .then((res) => {
  158. this.$message({
  159. message: "提交成功",
  160. type: "success",
  161. });
  162. this.selectAnLi();
  163. })
  164. .catch((err) => {
  165. console.error(err);
  166. });
  167. })
  168. .catch(() => {});
  169. },
  170. deleteAnli(id) {
  171. this.$confirm("确定删除此案例吗?", "提示", {
  172. confirmButtonText: "确定",
  173. cancelButtonText: "取消",
  174. type: "warning",
  175. })
  176. .then(() => {
  177. let params = {
  178. id: id,
  179. };
  180. this.ajax
  181. .get(this.$store.state.api + "deleteAnli", params)
  182. .then((res) => {
  183. this.$message({
  184. message: "删除成功",
  185. type: "success",
  186. });
  187. this.selectAnLi();
  188. })
  189. .catch((err) => {
  190. console.error(err);
  191. });
  192. })
  193. .catch(() => {});
  194. },
  195. exportAnli(res) {
  196. console.log(res);
  197. let _html = "";
  198. var _title = "<h1>项目基础信息</h1>";
  199. let info = JSON.parse(res.info);
  200. _title += `
  201. <iframe style="display: none;" name="downloadFile"></iframe>
  202. <h2>项目名称:${info.title}</h2>
  203. `;
  204. _title += `<h3>比赛类别:${res.typename}</h3>`;
  205. _title += `<h4>单位:${res.schoolName}</h4>`;
  206. _title += `<div>项目简介:${info.courseText}</div>`;
  207. _title += `<h4>文件:`;
  208. var _div = document.createElement("div");
  209. for (var i = 0; i < info.data.length; i++) {
  210. var _div2 = document.createElement("div");
  211. _div2.innerHTML = ` <a href="JavaScript:void(0)" onclick="downloadFile2('${info.data[i].url}')">${info.data[i].name}</a>`;
  212. _div.appendChild(_div2);
  213. }
  214. _title += `<div>${_div.innerHTML}</div>`;
  215. let overview = JSON.parse(res.overview);
  216. var _overview = "<h1>项目概况</h1>";
  217. var oArray = [
  218. { j: "driQuestion", name: "驱动性问题" },
  219. { j: "tarDesign", name: "学习目标" },
  220. { j: "actiDesign", name: "评价设计" },
  221. // { j: "evaDesign", name: "评价设计" },
  222. // { j: "other", name: "其他补充" },
  223. ];
  224. for (var k = 0; k < oArray.length; k++) {
  225. _overview += `<h2>${oArray[k].name}</h2>`;
  226. // <a :href="`${完整的下载地址}`" onclick="downloadFile2>{{文件名称}}</a>
  227. // <iframe style="display: none;" name="downloadFile"></iframe>
  228. _overview += `<div>${overview[oArray[k].j].brief}</div>`;
  229. var _div = document.createElement("div");
  230. for (var i = 0; i < overview[oArray[k].j].data.length; i++) {
  231. var _div2 = document.createElement("div");
  232. _div2.innerHTML = ` <a href="JavaScript:void(0)" onclick="downloadFile2('${
  233. overview[oArray[k].j].data[i].url
  234. }')">${overview[oArray[k].j].data[i].name}</a>`;
  235. _div.appendChild(_div2);
  236. }
  237. _overview += `<div>${_div.innerHTML}</div>`;
  238. }
  239. let process = JSON.parse(res.process).stageBox;
  240. var _process = "<h1>项目安排</h1>";
  241. for (var pz = 0; pz < process.length; pz++) {
  242. _process += `<h2>阶段${pz + 1}:${process[pz].staTitle}</h2>`;
  243. _process += `<h2>总课时:${process[pz].allTime}</h2>`;
  244. let _act = process[pz].actBox;
  245. for (var z = 0; z < _act.length; z++) {
  246. _process += `<h2>活动${z + 1}</h2>`;
  247. _process += `<h3>活动名称:${_act[z].actName} 课时:${_act[z].actTime}</h3>`;
  248. let pAarray = [
  249. { j: "driQuestion", name: "活动目标" },
  250. { j: "tarDesign", name: "活动内容" },
  251. { j: "actiDesign", name: "预期成果" },
  252. { j: "evaDesign", name: "活动评价" },
  253. ];
  254. for (var i = 0; i < pAarray.length; i++) {
  255. _process += `<h3>${pAarray[i].name}</h3>`;
  256. _process += `<div>描述</div>`;
  257. _process += `<div>${_act[z][pAarray[i].j].brief}</div>`;
  258. _process += `<div>资料补充</div>`;
  259. var _div = document.createElement("div");
  260. for (var c = 0; c < _act[z][pAarray[i].j].data.length; c++) {
  261. var _div2 = document.createElement("div");
  262. _div2.innerHTML = ` <a href="JavaScript:void(0)" onclick="downloadFile2('${
  263. _act[z][pAarray[i].j].data[c].url
  264. }')">${_act[z][pAarray[i].j].data[c].name}</a>`;
  265. _div.appendChild(_div2);
  266. }
  267. _process += `<div>${_div.innerHTML}</div>`;
  268. }
  269. }
  270. }
  271. let _proact = "<h1>项目活动过程</h1>";
  272. for (var pz = 0; pz < process.length; pz++) {
  273. _proact += `<h2>阶段${pz + 1}</h2>`;
  274. _proact += `<h2>描述</h2>`;
  275. _proact += `<div>${process[pz].brief}</div>`;
  276. _proact += `<h4>附件:`;
  277. var _div = document.createElement("div");
  278. for (var i = 0; i < process[pz].data.length; i++) {
  279. var _div2 = document.createElement("div");
  280. _div2.innerHTML = ` <a href="JavaScript:void(0)" onclick="downloadFile2('${process[pz].data[i].url}')">${process[pz].data[i].name}</a>`;
  281. _div.appendChild(_div2);
  282. }
  283. _proact += `<div>${_div.innerHTML}</div>`;
  284. }
  285. let proexc = JSON.parse(res.proexc);
  286. let _proexc = "<h1>项目成果交流与评价</h1>";
  287. _proexc += `<div>描述</div>`;
  288. _proexc += `<div>${proexc.brief}</div>`;
  289. _proexc += `<div>附件</div>`;
  290. var _div = document.createElement("div");
  291. for (var i = 0; i < proexc.data.length; i++) {
  292. var _div2 = document.createElement("div");
  293. _div2.innerHTML = ` <a href="JavaScript:void(0)" onclick="downloadFile2('${proexc.data[i].url}')">${proexc.data[i].name}</a>`;
  294. _div.appendChild(_div2);
  295. }
  296. _proexc += `<div>${_div.innerHTML}</div>`;
  297. let results = JSON.parse(res.results);
  298. let _results = "<h1>项目成效与反思</h1>";
  299. _results += `<div>描述</div>`;
  300. _results += `<div>${results.brief}</div>`;
  301. _results += `<div>附件</div>`;
  302. var _div = document.createElement("div");
  303. for (var i = 0; i < results.data.length; i++) {
  304. var _div2 = document.createElement("div");
  305. _div2.innerHTML = ` <a href="JavaScript:void(0)" onclick="downloadFile2('${results.data[i].url}')">${results.data[i].name}</a>`;
  306. _div.appendChild(_div2);
  307. }
  308. _results += `<div>${_div.innerHTML}</div>`;
  309. // _results += `<h3>项目成效</h3>`;
  310. // _results += `<div>${results.proEffText}</div>`;
  311. // _results += `<h3>项目反思</h3>`;
  312. // _results += `<div>${results.proRefText}</div>`;
  313. _html = _title + _overview + _process + _proact + _proexc + _results;
  314. console.log("_overview", overview);
  315. console.log("_process", process);
  316. console.log("_results", results);
  317. this.generate(_html, { title: info.title, username: res.name });
  318. },
  319. async generate(a, data) {
  320. // 将html文件中需要用到的数据挂载到store上
  321. this.$store.commit("update", ["report", a]);
  322. console.log(this.$store.state.report);
  323. const content =
  324. '<!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="UTF-8">\n <meta http-equiv="X-UA-Compatible" content="IE=edge">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>报告</title>\n </head> \n <body>' +
  325. this.$store.state.report +
  326. '</body>\n \x3Cscript>\n function downloadFile2(url) {\n let _url = "";\n _url = url;\n const x = new XMLHttpRequest();\n x.open("GET", _url, true);\n x.responseType = "blob";\n x.onload = function (e) {\n let content = x.response;\n let elink = document.createElement("a");\n elink.download = decodeURI(\n _url.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1]\n );\n elink.style.display = "none";\n let blob = new Blob([content]);\n elink.href = URL.createObjectURL(blob);\n document.body.appendChild(elink);\n elink.click();\n document.body.removeChild(elink);\n };\n x.send();\n }\n \x3C/script>\n </html>';
  327. // debugger
  328. // 生成报告
  329. const link = document.createElement("a");
  330. let dname = data.title + "-" + data.username + ".html";
  331. // link.download = "报告.html"; // 文件名
  332. link.download = dname; // 文件名
  333. link.style.display = "none";
  334. // 创建文件流
  335. // 创建bolb实例时,内容一定要放在[]中
  336. const blob = new Blob([content], {
  337. type: "text/plain;charset='utf-8'",
  338. });
  339. link.href = window.URL.createObjectURL(blob);
  340. document.body.appendChild(link);
  341. link.click();
  342. document.body.removeChild(link);
  343. },
  344. lookDetail(aid) {
  345. window.open(
  346. window.location.origin +
  347. window.location.pathname +
  348. "/#/anliDetail?aid=" +
  349. aid
  350. );
  351. },
  352. },
  353. created() {
  354. this.selectAnLi();
  355. },
  356. };
  357. </script>
  358. <style scoped>
  359. @media screen and (max-width: 1280px) {
  360. .xmjj {
  361. width: 70% !important;
  362. }
  363. .noAnliBox {
  364. width: 300px !important;
  365. }
  366. }
  367. .myAnliBox {
  368. /* height: 500px; */
  369. overflow: auto;
  370. overflow-x: hidden;
  371. height: 100%;
  372. /* box-shadow: inset 0px 14px 7px -14px #b9b9b9; */
  373. }
  374. .center_content {
  375. width: 100%;
  376. height: 100%;
  377. }
  378. .anLi {
  379. background: #fff;
  380. width: 95%;
  381. margin: 20px auto 30px;
  382. border-radius: 10px;
  383. height: 210px;
  384. }
  385. .anliTop {
  386. display: flex;
  387. flex-direction: row;
  388. flex-wrap: nowrap;
  389. align-items: center;
  390. justify-content: space-between;
  391. }
  392. .anliTopLeft {
  393. display: flex;
  394. flex-direction: row;
  395. flex-wrap: nowrap;
  396. align-items: center;
  397. color: #afafaf;
  398. padding: 20px 0 10px 30px;
  399. }
  400. .anliTopLeft > div:nth-child(2) {
  401. padding-left: 20px;
  402. }
  403. .anliTopRight {
  404. padding: 20px 30px 10px 0;
  405. }
  406. .anliMiddle {
  407. padding: 0 0 5px 30px;
  408. }
  409. .anliImg {
  410. width: 200px;
  411. height: 115px;
  412. min-width: 200px;
  413. }
  414. .anliImg > img {
  415. width: 100%;
  416. height: 100%;
  417. object-fit: contain;
  418. }
  419. .people {
  420. display: flex;
  421. }
  422. .person {
  423. margin-left: 10px;
  424. line-height: 18px;
  425. }
  426. .man {
  427. width: 16px;
  428. height: 16px;
  429. }
  430. .man > img {
  431. width: 100%;
  432. height: 100%;
  433. }
  434. .anliBox {
  435. display: flex;
  436. flex-direction: row;
  437. flex-wrap: nowrap;
  438. align-items: flex-start;
  439. }
  440. .anliNav {
  441. padding-left: 30px;
  442. width: 100%;
  443. }
  444. .anliNav > div:nth-child(1) {
  445. font-size: 20px;
  446. /* font-weight: bold; */
  447. }
  448. .anliNav > div:nth-child(2) {
  449. /* font-weight: bold; */
  450. margin: 10px 0 10px 0;
  451. }
  452. .xmjj {
  453. color: #aba8a8;
  454. margin-bottom: 10px;
  455. white-space: nowrap;
  456. overflow: hidden;
  457. text-overflow: ellipsis;
  458. width: 80%;
  459. }
  460. .anliBottom {
  461. display: flex;
  462. flex-direction: row;
  463. flex-wrap: nowrap;
  464. align-items: center;
  465. justify-content: space-between;
  466. margin: -10px 10px 0 30px;
  467. }
  468. .isSubmit {
  469. color: red;
  470. }
  471. .bottomRight {
  472. display: flex;
  473. flex-direction: row;
  474. flex-wrap: nowrap;
  475. align-items: center;
  476. }
  477. .rightButton {
  478. background: #499eef;
  479. color: #fff;
  480. /* width: 60px; */
  481. height: 30px;
  482. text-align: center;
  483. line-height: 30px;
  484. font-size: 14px;
  485. border-radius: 5px;
  486. cursor: pointer;
  487. margin-right: 20px;
  488. padding: 0 15px;
  489. }
  490. .noAnliBox {
  491. width: 500px;
  492. margin: 20px auto;
  493. }
  494. .noAnliBox > img {
  495. width: 100%;
  496. height: 100%;
  497. }
  498. .personAndAutor {
  499. display: flex;
  500. flex-direction: row;
  501. flex-wrap: nowrap;
  502. align-items: center;
  503. }
  504. .autorBox {
  505. display: flex;
  506. flex-direction: row;
  507. flex-wrap: nowrap;
  508. align-items: center;
  509. margin-left: 10px;
  510. }
  511. .Autor {
  512. margin: 0 5px;
  513. }
  514. </style>