index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. <template>
  2. <div class="program">
  3. <el-card class="box-card">
  4. <el-form
  5. :model="form"
  6. size="small"
  7. :inline="true"
  8. label-width="120px"
  9. class="demo-form-inline"
  10. >
  11. <el-form-item>
  12. <template v-for="item in pListData" :key="item.platform">
  13. <el-button
  14. :class="
  15. 'colorBtn ' +
  16. btnGroup[item.platform].class +
  17. (form.platform == item.platform
  18. ? ' ' + btnGroup[item.platform].class + 'act'
  19. : '')
  20. "
  21. @click="() => tabChange(item)"
  22. >
  23. <span
  24. class="icon iconfont"
  25. v-html="btnGroup[item.platform].text"
  26. />
  27. {{ item.platform }}
  28. </el-button>
  29. </template>
  30. </el-form-item>
  31. <el-form-item label="日期">
  32. <el-date-picker
  33. v-model="form.dt"
  34. type="daterange"
  35. start-placeholder="开始时间"
  36. end-placeholder="结束时间"
  37. :disabled-date="time => disabledDate(time)"
  38. placeholder="日期"
  39. >
  40. </el-date-picker>
  41. </el-form-item>
  42. <el-form-item label="关键词">
  43. <el-input v-model="form.match" placeholder="检索关键词" clearable />
  44. </el-form-item>
  45. <el-form-item style="float: right">
  46. <el-button type="primary" @click="onSubmit" :loading="load">
  47. 查询
  48. </el-button>
  49. <el-button type="primary" @click="onExport">导出</el-button>
  50. </el-form-item>
  51. </el-form>
  52. </el-card>
  53. <br />
  54. <el-card class="box-card">
  55. <el-tabs v-model="activeTab" class="demo-tabs">
  56. <el-tab-pane label="传播数据" name="agg">
  57. <el-table
  58. :header-cell-style="{
  59. backgroundColor: '#f4f5f7',
  60. color: '#606266',
  61. }"
  62. ref="table1"
  63. align="center"
  64. :data="tableData"
  65. empty-text="暂无数据"
  66. style="width: 100%"
  67. @sort-change="sort_change"
  68. >
  69. <template v-for="(item, i) in agg" :key="i">
  70. <el-table-column
  71. align="center"
  72. :width="item.width"
  73. show-overflow-tooltip
  74. :prop="item.key"
  75. :label="item.label"
  76. :sortable="item.sortable"
  77. :sort-orders="
  78. item.sortable ? ['ascending', 'descending', null] : []
  79. "
  80. >
  81. <template #default="scope">
  82. {{
  83. item.type == 'number'
  84. ? formatter(scope.row[item.key])
  85. : scope.row[item.key]
  86. }}
  87. </template>
  88. </el-table-column>
  89. </template>
  90. </el-table>
  91. </el-tab-pane>
  92. <el-tab-pane label="稿件数据" name="list">
  93. <el-table
  94. :header-cell-style="{
  95. backgroundColor: '#f4f5f7',
  96. color: '#606266',
  97. }"
  98. ref="table2"
  99. align="center"
  100. empty-text="暂无数据"
  101. :data="tableList"
  102. style="width: 100%"
  103. @sort-change="sort_change"
  104. >
  105. <template v-for="(item, i) in list" :key="i">
  106. <el-table-column
  107. align="center"
  108. :width="item.width"
  109. show-overflow-tooltip
  110. :prop="item.key"
  111. :label="item.label"
  112. :sortable="item.sortable"
  113. :sort-orders="
  114. item.sortable ? ['ascending', 'descending', null] : []
  115. "
  116. >
  117. <template #default="scope">
  118. {{
  119. item.type == 'number'
  120. ? formatter(scope.row[item.key])
  121. : scope.row[item.key]
  122. }}
  123. </template>
  124. </el-table-column>
  125. </template>
  126. </el-table>
  127. <br />
  128. <el-pagination
  129. @current-change="cChange"
  130. background
  131. :page-size="pagesize || 10"
  132. layout="prev, pager, next"
  133. :total="total"
  134. />
  135. <br />
  136. </el-tab-pane>
  137. </el-tabs>
  138. </el-card>
  139. </div>
  140. </template>
  141. <script>
  142. // @ is an alias to /src
  143. const ElLoading = require('element-plus/lib/el-loading/index');
  144. import 'element-plus/lib/theme-chalk/el-loading.css';
  145. import { platformList, platformlistData, platform } from '@/api/index';
  146. import { formatter } from '@/utils/tool';
  147. import config from '@/config/index';
  148. let tableDataListOri = [];
  149. let sort = null;
  150. let sortLib = null;
  151. export default {
  152. name: 'RealData',
  153. data() {
  154. return {
  155. btnGroup: {
  156. 微信: {
  157. color: '#1cc393',
  158. class: 'weixin',
  159. text: '&#xe603;',
  160. },
  161. 微博: {
  162. color: '#ffb712',
  163. class: 'weibo',
  164. text: '&#xe67a;',
  165. },
  166. 快手: {
  167. color: '#ffb712',
  168. class: 'kuaishou',
  169. text: '&#xe8dc;',
  170. },
  171. 抖音: {
  172. color: '#170b1a',
  173. class: 'douyin',
  174. text: '&#xe8db;',
  175. },
  176. 头条: {
  177. color: '#de0517',
  178. class: 'toutiao',
  179. text: '&#xe607;',
  180. },
  181. B站: {
  182. color: '#ffb712',
  183. class: 'bzhan',
  184. text: '&#xe61e;',
  185. },
  186. 视频号: {
  187. color: '#ffb712',
  188. class: 'weixinshipinhao',
  189. text: '&#xe60a;',
  190. },
  191. },
  192. page: 0,
  193. pagesize: 20,
  194. total: 0,
  195. load: false,
  196. activeTab: 'agg',
  197. form: {
  198. platform: '',
  199. dt: [],
  200. match: '',
  201. },
  202. formRael: { platform: '', dt: [] },
  203. tableData: [],
  204. pListData: [],
  205. };
  206. },
  207. mounted() {
  208. platformList().then(res => {
  209. const first = res[0] || { platform: '', dt: '' };
  210. this.form = {
  211. dt: [first.dt, first.dt],
  212. platform: first.platform,
  213. };
  214. this.formRael = {
  215. dt: [first.dt, first.dt],
  216. platform: first.platform || '',
  217. };
  218. this.pListData = res || [];
  219. this.onSubmit();
  220. });
  221. },
  222. computed: {
  223. agg() {
  224. if (!this.formRael.platform) return [];
  225. return config.tableCol.agg[this.formRael.platform];
  226. },
  227. list() {
  228. if (!this.formRael.platform) return [];
  229. return config.tableCol.list[this.formRael.platform];
  230. },
  231. tableList() {
  232. const out = [];
  233. for (
  234. let i = (this.page - 1) * this.pagesize;
  235. i < this.page * this.pagesize;
  236. i++
  237. ) {
  238. const v = tableDataListOri[i];
  239. v && out.push(v);
  240. }
  241. return out;
  242. },
  243. },
  244. methods: {
  245. formatter,
  246. tabChange(item) {
  247. let p = {
  248. platform: item.platform,
  249. dt: this.form.dt,
  250. match: this.form.match,
  251. };
  252. if (new Date(item.dt) - new Date(p.dt) < 0) p.dt = item.dt;
  253. this.form = p;
  254. this.$refs.table1.clearSort();
  255. this.$refs.table2.clearSort();
  256. sortLib = null;
  257. sort = null;
  258. this.onSubmit();
  259. },
  260. cChange(num) {
  261. this.page = num;
  262. },
  263. onExport() {
  264. if (!this.formRael.dt || this.formRael.dt.length != 2) return;
  265. const startd = this.dateFormat(this.formRael.dt[0] || 0);
  266. const starte = this.dateFormat(this.formRael.dt[1] || 0);
  267. let url =
  268. config.base.url2 +
  269. '/new-media/export?start=' +
  270. [startd.year, startd.month, startd.day].join('-') +
  271. '&end=' +
  272. [starte.year, starte.month, starte.day].join('-');
  273. if (this.formRael.sort) url += '&sort=' + this.formRael.sort;
  274. if (this.formRael.match) url += '&match=' + this.formRael.match;
  275. window.open(url);
  276. },
  277. disabledDate(time) {
  278. return time.getTime() > Date.now() - 86400000;
  279. },
  280. sort_change(type) {
  281. sort = type.prop;
  282. sortLib = type.order;
  283. this.onSubmit();
  284. },
  285. onSubmit() {
  286. const data = this.formatListData();
  287. this.page = 0;
  288. this.tableData = [];
  289. this.total = 0;
  290. this.load = true;
  291. const l = ElLoading.default.service();
  292. Promise.all([platform(data), platformlistData(data)])
  293. .then(list => {
  294. this.formRael = data;
  295. this.formRael.dt = [this.formRael.start, this.formRael.end];
  296. this.tableData = (list[0] || []).map((v, i) => {
  297. v.index = i + 1;
  298. return v;
  299. });
  300. tableDataListOri = (list[1] || []).map((v, i) => {
  301. v.index = i + 1;
  302. return v;
  303. });
  304. this.total = tableDataListOri.length;
  305. this.page = this.page + 1;
  306. this.load = false;
  307. l.close();
  308. })
  309. .catch(() => {
  310. this.load = false;
  311. l.close();
  312. });
  313. },
  314. dateFormat(date) {
  315. let D = new Date(date);
  316. let m = D.getMonth() + 1;
  317. let d = D.getDate();
  318. let h = D.getHours();
  319. let M = D.getMinutes();
  320. let s = D.getSeconds();
  321. m > 9 ? m : (m = '0' + m);
  322. d > 9 ? d : (d = '0' + d);
  323. h > 9 ? h : (h = '0' + h);
  324. M > 9 ? M : (M = '0' + M);
  325. s > 9 ? s : (s = '0' + s);
  326. return {
  327. year: D.getFullYear(),
  328. month: m,
  329. day: d,
  330. hour: h,
  331. minutes: M,
  332. seconds: s,
  333. };
  334. },
  335. formatListData() {
  336. const startd = this.form.dt[0] ? this.dateFormat(this.form.dt[0]) : false;
  337. const starte = this.form.dt[1] ? this.dateFormat(this.form.dt[1]) : false;
  338. const loginname = JSON.parse(
  339. window.parent.localStorage.userinfo || '{}'
  340. ).loginname;
  341. const p = {
  342. platform: this.form.platform || this.pListData[0],
  343. start: startd
  344. ? [startd.year, startd.month, startd.day].join('-')
  345. : undefined,
  346. end: starte
  347. ? [starte.year, starte.month, starte.day].join('-')
  348. : undefined,
  349. match: this.form.match,
  350. userId: loginname,
  351. };
  352. sort && (p.sort = sort);
  353. const sortLibType = {
  354. descending: 1,
  355. ascending: 0,
  356. };
  357. sortLib && (p.order = sortLibType[sortLib]);
  358. return p;
  359. },
  360. },
  361. components: {},
  362. };
  363. </script>
  364. <style>
  365. .colorBtn {
  366. background-color: #fff;
  367. color: #000;
  368. padding: 0 18px;
  369. width: 8em;
  370. height: 38px;
  371. line-height: 38px;
  372. font-size: 14px;
  373. }
  374. .weibo .icon {
  375. color: #ffb712;
  376. }
  377. .weiboact,
  378. .weibo:hover,
  379. .weibo:focus,
  380. .weiboact .icon,
  381. .weibo:hover .icon {
  382. background-color: #ffb712;
  383. border-color: #ffb712;
  384. color: #fff;
  385. }
  386. .toutiao .icon {
  387. color: #f04142;
  388. }
  389. .toutiaoact,
  390. .toutiao:hover,
  391. .toutiao:focus,
  392. .toutiaoact .icon,
  393. .toutiao:hover .icon {
  394. background-color: #f04142;
  395. border-color: #f04142;
  396. color: #fff;
  397. }
  398. .weixin .icon {
  399. color: #1cc393;
  400. }
  401. .weixinact,
  402. .weixin:hover,
  403. .weixin:focus,
  404. .weixinact .icon,
  405. .weixin:hover .icon {
  406. background-color: #1cc393;
  407. border-color: #1cc393;
  408. color: #fff;
  409. }
  410. .kuaishou .icon {
  411. color: #eb3661;
  412. }
  413. .kuaishouact,
  414. .kuaishou:hover,
  415. .kuaishou:focus,
  416. .kuaishou:focus,
  417. .kuaishouact .icon,
  418. .kuaishou:hover .icon {
  419. background-color: #eb3661;
  420. border-color: #eb3661;
  421. color: #fff;
  422. }
  423. .douyin .icon {
  424. color: #170b1a;
  425. }
  426. .douyinact,
  427. .douyin:hover,
  428. .douyin:focus,
  429. .douyinact .icon,
  430. .douyin:hover .icon {
  431. background-color: #170b1a;
  432. border-color: #170b1a;
  433. color: #fff;
  434. }
  435. .bzhan .icon {
  436. color: #fb7299;
  437. }
  438. .bzhanact,
  439. .bzhan:hover,
  440. .bzhan:focus,
  441. .bzhanact .icon,
  442. .bzhan:hover .icon {
  443. background-color: #fb7299;
  444. border-color: #fb7299;
  445. color: #fff;
  446. }
  447. .weixinshipinhao .icon {
  448. color: #fa9d3b;
  449. }
  450. .weixinshipinhaoact,
  451. .weixinshipinhao:hover,
  452. .weixinshipinhao:focus,
  453. .weixinshipinhaoact .icon,
  454. .weixinshipinhao:hover .icon {
  455. background-color: #fa9d3b;
  456. border-color: #fa9d3b;
  457. color: #fff;
  458. }
  459. </style>