ReportFormsMonthPage.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <!-- 广告报表列表页 -->
  2. <template>
  3. <div v-loading="loading">
  4. <el-form :inline="true">
  5. <el-form-item label="周期">
  6. <el-date-picker
  7. v-model="pages.datas"
  8. type="daterange"
  9. format="YYYY-MM-DD"
  10. value-format="YYYY-MM-DD"
  11. range-separator="到"
  12. start-placeholder="开始时间"
  13. end-placeholder="结束时间"
  14. />
  15. </el-form-item>
  16. <el-form-item label="区域">
  17. <el-select filterable clearable v-model="pages.province" style="width: 200px">
  18. <el-option
  19. v-for="item in provinces"
  20. :key="item.value"
  21. :label="item.label"
  22. :value="item.value"
  23. />
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="广告主">
  27. <el-select
  28. multiple
  29. collapse-tags
  30. filterable
  31. clearable
  32. v-model="pages.advertiserIds"
  33. @change="() => changeAdvertiser()"
  34. style="width: 200px"
  35. >
  36. <el-option
  37. v-for="item in advertisers"
  38. :key="item.advertiserId"
  39. :label="item.enterpriseName"
  40. :value="item.advertiserId"
  41. />
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item label="创意">
  45. <el-select
  46. multiple
  47. collapse-tags
  48. filterable
  49. clearable
  50. v-model="pages.creativeIds"
  51. @change="() => changeMaterial()"
  52. style="width: 200px"
  53. >
  54. <el-option
  55. v-for="item in originalitys"
  56. :key="item.creativeId"
  57. :label="item.creativeName"
  58. :value="item.creativeId"
  59. />
  60. </el-select>
  61. </el-form-item>
  62. <el-form-item label="素材">
  63. <el-select
  64. multiple
  65. collapse-tags
  66. filterable
  67. clearable
  68. v-model="pages.stuffIds"
  69. style="width: 200px"
  70. >
  71. <el-option
  72. v-for="item in SourceMaterials"
  73. :key="item.stuffId"
  74. :label="item.stuffName"
  75. :value="item.stuffId"
  76. />
  77. </el-select>
  78. </el-form-item>
  79. <el-form-item>
  80. <el-button type="primary" @click="() => onSubmit()">搜索</el-button>
  81. <el-button type="primary" @click="() => onSubmit(true)">导出</el-button>
  82. </el-form-item>
  83. </el-form>
  84. <el-table :data="tableData" stripe style="width: 100%">
  85. <el-table-column prop="sdate" label="日期" />
  86. <el-table-column prop="exposureCount" label="曝光数" />
  87. <el-table-column prop="clickCount" label="点击数" />
  88. <el-table-column prop="clickCount" label="点击率">
  89. <template #default="scope"> {{ scope.row.lv }}% </template>
  90. </el-table-column>
  91. <el-table-column prop="uvCount" label="用户数" />
  92. </el-table>
  93. <br />
  94. <el-pagination
  95. background
  96. layout="prev, pager, next"
  97. :total="pages.total"
  98. @current-change="page"
  99. />
  100. </div>
  101. </template>
  102. <script setup lang="ts">
  103. import type { OriginalityItem } from '@/types/AdListPage'
  104. import type { Advertiser } from '@/types/Advertiser'
  105. import type { Pages } from '@/types/Tool'
  106. import type { SourceMaterialList } from '@/types/SourceMaterial'
  107. import type { IReportItem } from '@/types/Report'
  108. import {
  109. getAdvertiserList,
  110. getOriginalityList,
  111. getMaterialList,
  112. getAdvertiserMonthReport,
  113. getProvinceCity,
  114. } from '@/api/index'
  115. import { formatDate } from '@/tool/index'
  116. import { reactive, ref } from 'vue'
  117. const date_ = formatDate(new Date().getTime() - 86400000)
  118. const pages = reactive<Pages>({
  119. pageNum: 1,
  120. pageSize: 10,
  121. advertiserIds: [],
  122. creativeIds: [],
  123. stuffIds: [],
  124. province: '',
  125. datas: [
  126. date_.fmtYear + '-' + date_.fmtMonth + '-' + date_.fmtDay,
  127. date_.fmtYear + '-' + date_.fmtMonth + '-' + date_.fmtDay,
  128. ],
  129. total: 0,
  130. type: 'month',
  131. })
  132. const advertisers = ref<Advertiser[]>([])
  133. const originalitys = ref<OriginalityItem[]>([])
  134. const SourceMaterials = ref<SourceMaterialList>([])
  135. const provinces = ref<{ label: string; value: string }[]>([])
  136. const tableData = ref<IReportItem[]>([])
  137. const loading = ref(false)
  138. const changeAdvertiser = () => {
  139. if (!pages.advertiserIds || !pages.advertiserIds.length) {
  140. originalitys.value = []
  141. return
  142. }
  143. getOriginalityList({
  144. pageNum: 1,
  145. pageSize: 999999,
  146. keyword: '',
  147. advertiserIds: pages.advertiserIds,
  148. }).then(({ data }) => {
  149. // 创意列表
  150. originalitys.value = data.records || []
  151. })
  152. }
  153. const changeMaterial = () => {
  154. if (!pages.creativeIds || !pages.creativeIds.length) {
  155. SourceMaterials.value = []
  156. return
  157. }
  158. getMaterialList({
  159. pageNum: 1,
  160. pageSize: 999999,
  161. creativeIds: pages.creativeIds,
  162. }).then(({ data }) => {
  163. // 素材列表
  164. SourceMaterials.value = data.records || []
  165. })
  166. }
  167. const getList = () => {
  168. getAdvertiserList({
  169. pageNum: 1,
  170. pageSize: 999999,
  171. }).then(({ data }) => {
  172. // 广告主列表
  173. advertisers.value = data.records || []
  174. })
  175. getProvinceCity().then(({ data }) => {
  176. provinces.value = data.area.map((item: { name: string }) => {
  177. return {
  178. label: item.name,
  179. value: item.name,
  180. }
  181. })
  182. })
  183. }
  184. const onSubmit = (isExport = false) => {
  185. const p = {
  186. advertiserIds: pages.advertiserIds,
  187. creativeIds: pages.creativeIds,
  188. stuffIds: pages.stuffIds,
  189. startDate: pages.datas ? pages.datas[0] : '',
  190. endDate: pages.datas ? pages.datas[1] : '',
  191. provinces: pages.province ? [pages.province] : [],
  192. pageNum: pages.pageNum,
  193. pageSize: isExport ? 999999 : pages.pageSize,
  194. }
  195. const Func = getAdvertiserMonthReport
  196. loading.value = true
  197. Func(p).then(({ data }) => {
  198. const list = (data.records || []).map((v: IReportItem) => {
  199. return {
  200. ...v,
  201. lv: (v.clickCount / v.exposureCount).toFixed(2) - 0,
  202. }
  203. })
  204. if (!isExport) {
  205. loading.value = false
  206. tableData.value = list
  207. pages.total = data.total
  208. return
  209. }
  210. if (!data.records || data.records.length == 0) {
  211. loading.value = false
  212. return
  213. }
  214. // 生成数据
  215. let strcsv = 'data:text/csv;charset=utf-8,\uFEFF日期,曝光数,点击数,点击率,用户数\r\n'
  216. list.map((v: IReportItem) => {
  217. strcsv += `${v.sdate},${v.exposureCount},${v.clickCount},${v.lv}%,${v.uvCount},\r\n`
  218. })
  219. // 导出
  220. let link: HTMLAnchorElement | undefined = document.createElement('a')
  221. link.id = 'download-csv'
  222. link.setAttribute('href', encodeURI(strcsv))
  223. link.setAttribute('download', '广告' + '.csv')
  224. link.click()
  225. link = undefined
  226. loading.value = false
  227. })
  228. }
  229. const page = (val: number) => {
  230. pages.pageNum = val
  231. onSubmit()
  232. }
  233. getList()
  234. onSubmit()
  235. </script>
  236. <style></style>