Skill.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. <template>
  2. <div>
  3. <el-card>
  4. <el-form :model="skillParams" ref="skillParams" class="clearfix topForm" style="float: left">
  5. <div class="leftForm-skill">
  6. <el-form-item
  7. class="pruductForm-skill"
  8. prop="skillId"
  9. label="技能选择"
  10. :rules="[{ required: true, message: '请选择技能', trigger: 'blur' }]"
  11. >
  12. <el-select v-model="skillParams.skillId" placeholder="请选择技能" @change="skillChange" style="width:160px">
  13. <el-option
  14. v-for="item in skillList"
  15. :key="item.skillId || item.skillId === 0 ? item.skillId : item.id"
  16. :label="item.skillName ? item.skillName : item.title"
  17. :value="item.skillId || item.skillId === 0 ? item.skillId : item.id"
  18. ></el-option>
  19. </el-select>
  20. </el-form-item>
  21. <el-form-item class="dateForm-skill" name="data" label="查询日期" style="display:flex">
  22. <el-date-picker
  23. style="width:140px"
  24. v-model="skillParams.startDate"
  25. type="date"
  26. placeholder="起"
  27. ></el-date-picker>
  28. <el-date-picker
  29. style="width:140px"
  30. v-model="skillParams.endDate"
  31. type="date"
  32. placeholder="止"
  33. ></el-date-picker>
  34. </el-form-item>
  35. </div>
  36. <el-form-item>
  37. <el-button type="primary" @click="submitForm('skillParams')">搜索</el-button>
  38. </el-form-item>
  39. </el-form>
  40. <el-button type="primary" @click="onExportExcel" style="float: right">导出</el-button>
  41. <el-table id="table" ref="table1" :data="skillData" border style="width: 100%" :height="tableHeight" >
  42. <el-table-column
  43. label="日期"
  44. fixed
  45. align="left"
  46. header-align="center"
  47. min-width="140px"
  48. >
  49. <template slot-scope="scope">
  50. <span>{{changeDate(scope.row.day)}}</span>
  51. </template>
  52. </el-table-column>
  53. <el-table-column label="流量与观看" header-align="center">
  54. <el-table-column
  55. label="UV"
  56. prop="uv"
  57. align="right"
  58. header-align="center"
  59. min-width="100px"
  60. ></el-table-column>
  61. <el-table-column
  62. label="VIP用户 | -UV1"
  63. align="right"
  64. header-align="center"
  65. :render-header="renderheader"
  66. prop="vipUv"
  67. min-width="120px"
  68. ></el-table-column>
  69. <el-table-column
  70. label="非VIP用户 | UV2=UV-UV1"
  71. align="right"
  72. header-align="center"
  73. :render-header="renderheader"
  74. prop="waitVipUv"
  75. min-width="140px"
  76. ></el-table-column>
  77. <el-table-column
  78. label="VIP用户占比 | =UV1/UV"
  79. align="right"
  80. header-align="center"
  81. :render-header="renderheader"
  82. prop="vipProportion"
  83. min-width="140px"
  84. ></el-table-column>
  85. <el-table-column
  86. label="VIP权限用户 | =V0"
  87. align="right"
  88. header-align="center"
  89. :render-header="renderheader"
  90. prop="vipCount"
  91. min-width="140px"
  92. v-if="skillParams.channel === 'XYYF' || skillParams.channel === 'XYYFMOBILE'"
  93. ></el-table-column>
  94. <el-table-column
  95. label="VIP用户活跃率 | =UV1/V0"
  96. align="right"
  97. header-align="center"
  98. :render-header="renderheader"
  99. min-width="140px"
  100. prop="aliveVipProportion"
  101. v-if="skillParams.channel === 'XYYF' || skillParams.channel === 'XYYFMOBILE'"
  102. >
  103. </el-table-column>
  104. <!-- <el-table-column
  105. label="VV"
  106. prop="vv"
  107. align="right"
  108. header-align="center"
  109. min-width="100px"
  110. ></el-table-column>-->
  111. <el-table-column
  112. label="VV"
  113. align="right"
  114. header-align="center"
  115. :render-header="renderheader"
  116. prop="vv"
  117. min-width="140px"
  118. ></el-table-column>
  119. <el-table-column
  120. label="忠实用户"
  121. align="right"
  122. header-align="center"
  123. :render-header="renderheader"
  124. prop="fealtyCount"
  125. min-width="140px"
  126. v-if="skillParams.channel === 'XYYF' || skillParams.channel === 'XYYFMOBILE'"
  127. ></el-table-column>
  128. <el-table-column
  129. label="忠实用户占比"
  130. align="right"
  131. header-align="center"
  132. :render-header="renderheader"
  133. prop="fealtyProportion"
  134. min-width="140px"
  135. v-if="skillParams.channel === 'XYYF' || skillParams.channel === 'XYYFMOBILE'"
  136. ></el-table-column>
  137. <el-table-column
  138. label="人均播放 | =VV/UV"
  139. align="right"
  140. header-align="center"
  141. :render-header="renderheader"
  142. prop="perCapitaPlay"
  143. min-width="140px"
  144. ></el-table-column>
  145. </el-table-column>
  146. <el-table-column label="拉新,付费与转换率" header-align="center">
  147. <el-table-column
  148. label="连续包月 | -Qm1"
  149. align="right"
  150. header-align="center"
  151. :render-header="renderheader"
  152. prop="consecutiveMonthly"
  153. min-width="100px"
  154. ></el-table-column>
  155. <el-table-column
  156. label="新增连续包月 | -Qm1-1"
  157. align="right"
  158. header-align="center"
  159. :render-header="renderheader"
  160. min-width="140px"
  161. >
  162. <template slot-scope="scope">
  163. <span>{{scope.row.appendConsecutiveMonthly || 0}}</span>
  164. </template>
  165. </el-table-column>
  166. <el-table-column
  167. label="续包月续费 | -Qm1-2"
  168. align="right"
  169. header-align="center"
  170. :render-header="renderheader"
  171. min-width="140px"
  172. >
  173. <template slot-scope="scope">
  174. <span>{{scope.row.continueConsecutiveMonthly || 0}}</span>
  175. </template>
  176. </el-table-column>
  177. <el-table-column
  178. label="月包 | -Qm2"
  179. align="right"
  180. header-align="center"
  181. :render-header="renderheader"
  182. prop="monthlyPayment"
  183. min-width="90px"
  184. ></el-table-column>
  185. <el-table-column
  186. label="年包 | -Qy"
  187. align="right"
  188. header-align="center"
  189. :render-header="renderheader"
  190. prop="yearlyPayment"
  191. ></el-table-column>
  192. <el-table-column
  193. label="付费订单数量| Q=Qm1+Qm2+Qy"
  194. align="right"
  195. header-align="center"
  196. :render-header="renderheader"
  197. prop="totalPayment"
  198. min-width="160px"
  199. ></el-table-column>
  200. <el-table-column
  201. label="r1 | =Qm1/Q"
  202. align="right"
  203. header-align="center"
  204. :render-header="renderheader"
  205. prop="consecutiveConversion"
  206. min-width="130px"
  207. ></el-table-column>// 月包占比
  208. <el-table-column
  209. label="r2 | =Qm2/Q"
  210. align="right"
  211. header-align="center"
  212. :render-header="renderheader"
  213. prop="monthlyConversion"
  214. min-width="130px"
  215. ></el-table-column>// 年包占比
  216. <el-table-column
  217. label="r3 | =Qy/Q"
  218. align="right"
  219. header-align="center"
  220. :render-header="renderheader"
  221. prop="yearlyConversion"
  222. min-width="130px"
  223. ></el-table-column>
  224. <el-table-column
  225. label="R | =(Qm1+Qm2+Qy)/UV2"
  226. align="right"
  227. header-align="center"
  228. :render-header="renderheader"
  229. prop="totalConversion"
  230. min-width="190px"
  231. ></el-table-column>
  232. <el-table-column
  233. label="R1 | =(Qm1-1+Qm2+Qy)/UV2"
  234. align="right"
  235. header-align="center"
  236. :render-header="renderheader"
  237. min-width="190px"
  238. >
  239. <template slot-scope="scope">
  240. <span>{{scope.row.appendTotalConversion || 0}}</span>
  241. </template>
  242. </el-table-column>
  243. </el-table-column>
  244. </el-table>
  245. <!-- <el-pagination
  246. v-if="orderList.totalElements"
  247. background
  248. layout="prev, pager, next"
  249. :total="orderList.totalElements"
  250. @current-change="changePage">
  251. </el-pagination>-->
  252. </el-card>
  253. </div>
  254. </template>
  255. <script>
  256. import { mapGetters } from "vuex";
  257. import formatDate from "../../utils/formatTime";
  258. import { getBaiduCourseList } from '../../api/skill'
  259. import downTable from '@/utils/downTable'
  260. export default {
  261. data() {
  262. return {
  263. tableHeight: 500,
  264. dateValue: "",
  265. skillParams: {
  266. skillId: "",
  267. startDate: "",
  268. endDate: "",
  269. channel: "",
  270. classId: ""
  271. },
  272. channelList: "",
  273. baiduCourseList: [],
  274. skillList:[
  275. { skillName : "小学语文",skillId : 0},
  276. { skillName : "小学数学",skillId : 3},
  277. { skillName : "小学一年级",skillId : 7},
  278. { skillName : "小学二年级",skillId : 8},
  279. { skillName : "小学三年级",skillId : 9},
  280. { skillName : "小学四年级",skillId : 10},
  281. { skillName : "易学拼音",skillId : 18},
  282. { skillName : "动画识字",skillId : 16},
  283. { skillName : "思维数学",skillId : 17},
  284. ]
  285. };
  286. },
  287. computed: {
  288. ...mapGetters({
  289. skillList: "skillList",
  290. orderList: "orderList",
  291. productList: "productList",
  292. skillData: "skillData"
  293. })
  294. },
  295. created() {
  296. this.$store.dispatch("clearList");
  297. // this.$store.dispatch("getOrderList", this.skillParams);
  298. this.skillParams.startDate = this.getYesterDay();
  299. this.skillParams.endDate = this.getYesterDay();
  300. this.tableHeight = document.documentElement.clientHeight * 0.75;
  301. },
  302. methods: {
  303. // 搜索
  304. submitForm(formName) {
  305. this.skillParams.startDate = this.skillParams.startDate
  306. ? formatDate(this.skillParams.startDate, 2)
  307. : "";
  308. this.skillParams.endDate = this.skillParams.endDate
  309. ? formatDate(this.skillParams.endDate, 2)
  310. : "";
  311. this.$refs[formName].validate(valid => {
  312. if (valid) {
  313. this.skillParams.channel = "BAIDU";
  314. this.$store.dispatch("getSkillData", this.skillParams);
  315. } else {
  316. console.log("error submit!!");
  317. return false;
  318. }
  319. });
  320. this.$refs.table1.doLayout();
  321. },
  322. // 渠道下课程分页
  323. changePage(e) {
  324. this.skillParams.pageNo = e;
  325. this.$store.dispatch("getSkillData", this.skillParams);
  326. },
  327. // 表头折行
  328. renderheader(h, { column, $index }) {
  329. return h("span", {}, [
  330. h("span", {}, column.label.split("|")[0]),
  331. h("br"),
  332. h("span", {}, column.label.split("|")[1])
  333. ]);
  334. },
  335. getYesterDay() {
  336. let yesterday = new Date().getTime() - 86400000;
  337. return formatDate(yesterday, 2);
  338. },
  339. skillChange(val) {
  340. this.skillParams.classId = ''
  341. console.log(val)
  342. // if (val === 0) {
  343. // getBaiduCourseList('CHINESE').then(res => {
  344. // this.baiduCourseList = [{
  345. // fullName: '全部',
  346. // id: 100
  347. // }, ...res.data]
  348. // })
  349. // } else if (val === 3) {
  350. // getBaiduCourseList('MATH').then(res => {
  351. // this.baiduCourseList = [{
  352. // fullName: '全部',
  353. // id: 101
  354. // }, ...res.data]
  355. // })
  356. // }
  357. },
  358. columnZero() {
  359. return "0";
  360. },
  361. columnZeroPercent(row, column, index) {
  362. if (row.totalPayment && column.property === "yearlyConversion") {
  363. return "100.00%";
  364. } else {
  365. return "0.00%";
  366. }
  367. // if(row.)
  368. },
  369. changeDate(date) {
  370. return formatDate(date, 4)
  371. },
  372. // 导出表格
  373. onExportExcel() {
  374. const name = "小度在家";
  375. const list = this.skillList.filter((item) => item.skillId === this.skillParams.skillId)[0] || ''
  376. const productName = list && list.skillName ? '-' + list.skillName : ''
  377. const date = this.skillParams.startDate + '至' + this.skillParams.endDate
  378. downTable('table', [
  379. {wch: 15}, // "characters"
  380. {wch: 6},
  381. {wch: 15},
  382. {wch: 20},
  383. {wch: 20},
  384. {wch: 6},
  385. {wch: 15},
  386. {wch: 15},
  387. {wch: 18},
  388. {wch: 18},
  389. {wch: 10},
  390. {wch: 15},
  391. {wch: 25},
  392. {wch: 10},
  393. {wch: 10},
  394. {wch: 10},
  395. {wch: 20},
  396. {wch: 25}
  397. ], name + productName + date)
  398. }
  399. }
  400. };
  401. </script>
  402. <style lang="less" scoped>
  403. .pruductForm-skill {
  404. margin-left: 10px;
  405. display: flex;
  406. }
  407. .topForm {
  408. display: flex;
  409. align-items: center;
  410. flex-direction: row;
  411. flex-shrink: 0;
  412. justify-content: space-between;
  413. }
  414. .leftForm-skill {
  415. display: flex;
  416. align-items: center;
  417. flex-direction: row;
  418. justify-content: space-between;
  419. }
  420. .dateForm-skill {
  421. margin-left: 18px;
  422. }
  423. </style>