MessageAnalyse.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. <style lang="scss">
  2. .content {
  3. // height: 80vh;
  4. }
  5. // 新
  6. .item {
  7. font-size: 14px;
  8. margin-bottom: 20px;
  9. .item-title {
  10. margin-bottom: 10px;
  11. color: #606266;
  12. .title-num {
  13. display: inline-block;
  14. // width:50px;
  15. font-weight: bold;
  16. }
  17. .title-header {
  18. // font-weight: 600;
  19. }
  20. .title-type {
  21. margin-left: 10px;
  22. }
  23. .title-download {
  24. color: #409eff;
  25. cursor: pointer;
  26. }
  27. }
  28. .item-content {
  29. // margin-left:60px;
  30. display: flex;
  31. .el-table {
  32. flex: 1.5;
  33. }
  34. div {
  35. flex: 1;
  36. }
  37. }
  38. }
  39. </style>
  40. <template>
  41. <section>
  42. <p><span>信息管理></span>问卷统计</p>
  43. <div class="content">
  44. <div class="download-all" style="display: inline-block; float: right">
  45. <el-button
  46. type="primary"
  47. icon="el-icon-download"
  48. size="mini"
  49. @click="downloadAll"
  50. >导出excel</el-button
  51. >
  52. </div>
  53. <div class="item" v-for="(item, index) in results" :key="index">
  54. <div class="item-title">
  55. <span class="title-num">第{{ index + 1 }}题:</span>
  56. <span class="title-header">{{ item.label }}</span>
  57. <span class="title-type">{{ item.type | getType }}</span>
  58. <span class="title-download" @click="downloadItem(item)"
  59. >导出Excel</span
  60. >
  61. </div>
  62. <div
  63. class="item-content"
  64. v-if="item.type == 'input' || item.type == 'textarea'"
  65. >
  66. 【答案】:<span v-for="(item1, index) in item.result" :key="index"
  67. >{{ item1 }}{{ index == item.result.length - 1 ? "" : "、" }}</span
  68. >
  69. </div>
  70. <div
  71. class="item-content"
  72. v-if="item.type == 'radio' || item.type == 'checkbox'"
  73. >
  74. <el-table :data="item.items" border>
  75. <el-table-column prop="label" label="选项"> </el-table-column>
  76. <el-table-column prop="times" label="次数"> </el-table-column>
  77. <el-table-column prop="sale" label="比例">
  78. <template slot-scope="scope">
  79. <el-progress :percentage="scope.row.sale"></el-progress>
  80. </template>
  81. </el-table-column>
  82. </el-table>
  83. <div
  84. :id="`chartPie${index}`"
  85. style="width: 500px; height: 150px"
  86. ></div>
  87. <div
  88. :id="`chartBar${index}`"
  89. style="width: 500px; height: 150px"
  90. ></div>
  91. </div>
  92. </div>
  93. </div>
  94. </section>
  95. </template>
  96. <script>
  97. import Page from "../../components/Page";
  98. import echarts from "echarts";
  99. export default {
  100. components: {
  101. Page,
  102. },
  103. data() {
  104. return {
  105. // checked: [],
  106. loading: false,
  107. results: [],
  108. };
  109. },
  110. filters: {
  111. getType(val) {
  112. if ((val == "input") | (val == "textarea")) {
  113. return "【填空题】";
  114. } else if (val == "radio") {
  115. return "【单选题】";
  116. } else if (val == "checkbox") {
  117. return "【多选题】";
  118. }
  119. },
  120. },
  121. methods: {
  122. downloadAll() {
  123. let message_id = this.$route.query.id;
  124. let type = this.$route.query.type;
  125. this.$api
  126. .downloadAnalyseAll({ message_id: message_id, type: type })
  127. .then((res) => {
  128. var elink = document.createElement("a");
  129. let blob = new Blob([res.data], {
  130. type: "application/vnd.ms-excel,charset=UTF-8",
  131. });
  132. let objUrl = URL.createObjectURL(blob);
  133. let file_name = decodeURIComponent(
  134. res.headers["content-disposition"].split("=")[1]
  135. );
  136. console.log(file_name);
  137. elink.download = file_name;
  138. elink.style.display = "none";
  139. elink.href = objUrl;
  140. document.body.appendChild(elink);
  141. elink.click();
  142. document.body.removeChild(elink);
  143. this.download_loading = false;
  144. });
  145. },
  146. downloadItem(item) {
  147. let message_id = this.$route.query.id;
  148. let type = this.$route.query.type;
  149. this.$api
  150. .downloadAnalyseItem({
  151. message_id: message_id,
  152. type: type,
  153. item: item.label,
  154. })
  155. .then((res) => {
  156. var elink = document.createElement("a");
  157. let blob = new Blob([res.data], {
  158. type: "application/vnd.ms-excel,charset=UTF-8",
  159. });
  160. let objUrl = URL.createObjectURL(blob);
  161. let file_name = decodeURIComponent(
  162. res.headers["content-disposition"].split("=")[1]
  163. );
  164. console.log(file_name);
  165. elink.download = file_name;
  166. elink.style.display = "none";
  167. elink.href = objUrl;
  168. document.body.appendChild(elink);
  169. elink.click();
  170. document.body.removeChild(elink);
  171. this.download_loading = false;
  172. });
  173. },
  174. getData() {
  175. let message_id = this.$route.query.id;
  176. let type = this.$route.query.type;
  177. this.$api
  178. .getMessageSurveyQuestionAnalyse({ id: message_id, type: type })
  179. .then((res) => {
  180. this.results = res.data.data;
  181. this.results.forEach((item, index) => {
  182. this.$nextTick(function () {
  183. this.getEcharts(item, index);
  184. });
  185. });
  186. });
  187. },
  188. getEcharts(item, index) {
  189. var myChart = this.$echarts.init(
  190. document.getElementById(`chartBar${index}`)
  191. );
  192. var myChart1 = this.$echarts.init(
  193. document.getElementById(`chartPie${index}`)
  194. );
  195. let dataPie = [];
  196. let dataBarX = [];
  197. let dataBarY = [];
  198. let colors = [
  199. "#9379ff",
  200. "#62A2FF",
  201. "#FFD053",
  202. "#FF9F41",
  203. "#FF542C",
  204. "#FE8463",
  205. "#9BCA63",
  206. "#FAD860",
  207. "#F3A43B",
  208. "#60C0DD",
  209. "#D7504B",
  210. "#C6E579",
  211. "#F4E001",
  212. "#F0805A",
  213. "#26C0C0",
  214. ];
  215. let pieColors = []
  216. item.items.forEach((item, index) => {
  217. dataPie.push({
  218. name: item.label,
  219. value: item.times,
  220. color:colors[index],
  221. itemStyle : {
  222. normal : {
  223. label : {
  224. show : true,
  225. color:colors[index]
  226. },
  227. labelLine : {
  228. show : true,
  229. color:colors[index]
  230. }
  231. },
  232. },
  233. });
  234. dataBarX.push(item.label);
  235. dataBarY.push({
  236. sale: item.sale,
  237. value: item.times,
  238. itemStyle: { color: colors[index] },
  239. });
  240. });
  241. dataPie = dataPie.filter(function(x){if(x.value==0){return false}return true})
  242. dataPie.forEach((item,index)=>{
  243. pieColors.push(item.color)
  244. })
  245. let option = {
  246. title: {
  247. subtext: "填报次数",
  248. },
  249. color: ["#5066FF"],
  250. tooltip: {
  251. trigger: "axis",
  252. axisPointer: {
  253. // 坐标轴指示器,坐标轴触发有效
  254. type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
  255. },
  256. },
  257. grid: {
  258. left: "2%",
  259. right: "4%",
  260. bottom: "3%",
  261. // top:'0px',
  262. containLabel: true,
  263. },
  264. xAxis: [
  265. {
  266. type: "category",
  267. data: dataBarX,
  268. axisTick: {
  269. alignWithLabel: true,
  270. },
  271. axisLine: {
  272. lineStyle: {
  273. color: "#D4D8EE",
  274. width: 2,
  275. type: "dotted",
  276. },
  277. },
  278. axisLabel: {
  279. // formatter:function(val) {
  280. // console.log(val,"")
  281. // return '中国科' //对每个标签处理后的结果(通过js字符串方法处理)
  282. // },
  283. // x轴字体颜色
  284. textStyle: {
  285. color: "#999999",
  286. // lineHeight: 20,
  287. fontSize: 12,
  288. },
  289. align: "center",
  290. // padding:[10,0 ,0,-40],
  291. },
  292. },
  293. ],
  294. yAxis: [
  295. {
  296. type: "value",
  297. boundaryGap: ["0%", "20%"],
  298. axisTick: {
  299. show: false,
  300. },
  301. minInterval: 1,
  302. axisLine: {
  303. show: false,
  304. },
  305. axisLabel: {
  306. show: true,
  307. textStyle: {
  308. color: "#666666", //更改坐标轴文字颜色
  309. fontSize: 14, //更改坐标轴文字大小
  310. },
  311. },
  312. splitLine: {
  313. show: true,
  314. lineStyle: {
  315. type: "dashed",
  316. },
  317. },
  318. // data:['0' , '100' , '200' , '300,400]
  319. },
  320. ],
  321. series: [
  322. {
  323. name: "次数",
  324. type: "bar",
  325. barWidth: "30px",
  326. data: dataBarY,
  327. itemStyle: {
  328. //柱形图圆角,鼠标移上去效果,如果只是一个数字则说明四个参数全部设置为那么多
  329. normal: {
  330. //柱形图圆角,初始化效果
  331. barBorderRadius: [10, 10, 10, 10],
  332. label: {
  333. show: true,
  334. position: "top",
  335. formatter: function (v) {
  336. return v.data.sale ? v.data.sale + "%" : "0%";
  337. },
  338. },
  339. },
  340. },
  341. },
  342. ],
  343. };
  344. let option1 = {
  345. // backgroundColor: '#dddddd',
  346. // title: {
  347. // text: 'Customized Pie',
  348. // left: 'center',
  349. // top: 20,
  350. // textStyle: {
  351. // color: '#ccc'
  352. // }
  353. // },
  354. color: pieColors,
  355. tooltip: {
  356. trigger: "item",
  357. formatter: "{a} <br/>{b} : {c} ({d}%)",
  358. },
  359. series: [
  360. {
  361. name: "访问来源",
  362. type: "pie",
  363. radius: "65%",
  364. // center: ['50%', '50%'],
  365. data: dataPie.sort(function (a, b) {
  366. return a.value - b.value;
  367. }),
  368. // roseType: 'radius',
  369. // label: {
  370. // color: "rgba(102, 102, 102,1)",
  371. // fontSize: 14,
  372. // },
  373. // labelLine: {
  374. // // show:false,
  375. // lineStyle: {
  376. // color: "rgba(000, 000, 000, 0.1)",
  377. // },
  378. // smooth: 0.2,
  379. // length: 20,
  380. // length2: 8,
  381. // },
  382. // itemStyle: {
  383. // // color: '#c23531',
  384. // // shadowBlur: 200,
  385. // // shadowColor: 'rgba(0, 0, 0, 0.5)'
  386. // normal:{
  387. // label:{
  388. // show: function(val){
  389. // console.log(val,222222222)
  390. // return false
  391. // },
  392. // },
  393. // labelLine: {
  394. // show: true
  395. // }
  396. // }
  397. // },
  398. data: dataPie.sort(function (a, b) {
  399. return a.value - b.value;
  400. }),
  401. animationType: "scale",
  402. animationEasing: "elasticOut",
  403. animationDelay: function (idx) {
  404. return Math.random() * 200;
  405. },
  406. },
  407. ],
  408. };
  409. myChart.setOption(option);
  410. myChart1.setOption(option1);
  411. },
  412. },
  413. mounted() {
  414. this.results.forEach((item, index) => {
  415. this.$nextTick(function () {
  416. this.getEcharts(item, index);
  417. });
  418. });
  419. },
  420. created() {
  421. this.getData();
  422. },
  423. };
  424. </script>