page-res.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <template>
  2. <!-- 对应页面: 受访页 -->
  3. <view class="fix-top-window">
  4. <view class="uni-header">
  5. <uni-stat-breadcrumb class="uni-stat-breadcrumb-on-phone" />
  6. <view class="uni-group">
  7. <view class="uni-sub-title hide-on-phone">受访页数据分析</view>
  8. </view>
  9. </view>
  10. <view class="uni-container">
  11. <view class="uni-stat--x flex p-1015">
  12. <view class="uni-stat--app-select">
  13. <uni-data-select collection="opendb-app-list" field="appid as value, name as text" orderby="text asc" :defItem="1" label="应用选择" v-model="query.appid" :clear="false" />
  14. <uni-data-select collection="opendb-app-versions" :where="versionQuery" class="ml-m" field="_id as value, version as text, uni_platform as label, create_date as date" format="{label} - {text}" orderby="date desc" label="版本选择" v-model="query.version_id" />
  15. </view>
  16. </view>
  17. <view class="uni-stat--x flex">
  18. <uni-stat-tabs label="日期选择" :current="currentDateTab" mode="date" @change="changeTimeRange" />
  19. <uni-datetime-picker type="datetimerange" :end="new Date().getTime()" v-model="query.start_time"
  20. returnType="timestamp" :clearIcon="false" class="uni-stat-datetime-picker"
  21. :class="{'uni-stat__actived': currentDateTab < 0 && !!query.start_time.length}"
  22. @change="useDatetimePicker" />
  23. </view>
  24. <view class="uni-stat--x">
  25. <uni-stat-tabs label="平台选择" type="boldLine" mode="platform" v-model="query.platform_id" @change="changePlatform" />
  26. <uni-data-select ref="version-select" v-if="query.platform_id && query.platform_id.indexOf('==') === -1" collection="uni-stat-app-channels" :where="channelQuery" class="p-channel" field="_id as value, channel_name as text" orderby="text asc" label="渠道/场景值选择" v-model="query.channel_id" />
  27. </view>
  28. <uni-stat-panel :items="panelData" />
  29. <view class="uni-stat--x p-m">
  30. <uni-table :loading="loading" border stripe :emptyText="errorMessage || $t('common.empty')">
  31. <uni-tr>
  32. <block v-for="(mapper, index) in fieldsMap" :key="index">
  33. <uni-th v-if="mapper.title" :key="index" align="center">
  34. <!-- #ifdef MP -->
  35. {{mapper.title}}
  36. <!-- #endif -->
  37. <!-- #ifndef MP -->
  38. <uni-tooltip>
  39. {{mapper.title}}
  40. <uni-icons v-if="index === 0 && mapper.tooltip" type="help" color="#666" />
  41. <template v-if="index === 0 && mapper.tooltip" v-slot:content>
  42. <view class="uni-stat-tooltip-s">
  43. {{mapper.tooltip}}
  44. </view>
  45. </template>
  46. </uni-tooltip>
  47. <!-- #endif -->
  48. </uni-th>
  49. </block>
  50. </uni-tr>
  51. <uni-tr v-for="(item ,i) in tableData" :key="i">
  52. <block v-for="(mapper, index) in fieldsMap" :key="index">
  53. <uni-td v-if="index === 1" :key="mapper.field" class="uni-stat-edit--x">
  54. {{item[mapper.field] !== undefined ? item[mapper.field] : '-'}}
  55. <uni-icons type="compose" color="#2979ff" size="25" class="uni-stat-edit--btn"
  56. @click="inputDialogToggle(item.path, item.title)" />
  57. </uni-td>
  58. <uni-td v-else :key="mapper.field" :align="index === 0 ? 'left' : 'center'">
  59. {{item[mapper.field] !== undefined ? item[mapper.field] : '-'}}
  60. </uni-td>
  61. </block>
  62. </uni-tr>
  63. </uni-table>
  64. <view class="uni-pagination-box">
  65. <uni-pagination show-icon show-page-size :page-size="options.pageSize"
  66. :current="options.pageCurrent" :total="options.total" @change="changePageCurrent"
  67. @pageSizeChange="changePageSize" />
  68. </view>
  69. </view>
  70. </view>
  71. <uni-popup ref="inputDialog" type="dialog" :maskClick="true">
  72. <uni-popup-dialog ref="inputClose" mode="input" title="请编辑名称" v-model="updateValue" placeholder="请输入内容"
  73. @confirm="editName"></uni-popup-dialog>
  74. </uni-popup>
  75. <!-- #ifndef H5 -->
  76. <fix-window />
  77. <!-- #endif -->
  78. </view>
  79. </template>
  80. <script>
  81. import {
  82. mapfields,
  83. stringifyQuery,
  84. stringifyField,
  85. stringifyGroupField,
  86. getTimeOfSomeDayAgo,
  87. division,
  88. format,
  89. debounce
  90. } from '@/js_sdk/uni-stat/util.js'
  91. import fieldsMap from './fieldsMap.js'
  92. export default {
  93. data() {
  94. return {
  95. fieldsMap,
  96. query: {
  97. dimension: "day",
  98. appid: '',
  99. platform_id: '',
  100. uni_platform: '',
  101. version_id: '',
  102. channel_id: '',
  103. start_time: [],
  104. },
  105. options: {
  106. pageSize: 20,
  107. pageCurrent: 1, // 当前页
  108. total: 0, // 数据总量
  109. },
  110. loading: false,
  111. currentDateTab: 1,
  112. tableData: [],
  113. panelData: fieldsMap.filter(f => f.hasOwnProperty('value')),
  114. queryId: '',
  115. updateValue: '',
  116. channelData: [],
  117. errorMessage: ''
  118. }
  119. },
  120. computed: {
  121. channelQuery() {
  122. const platform_id = this.query.platform_id
  123. return stringifyQuery({
  124. platform_id
  125. })
  126. },
  127. versionQuery() {
  128. const {
  129. appid,
  130. uni_platform
  131. } = this.query
  132. const query = stringifyQuery({
  133. appid,
  134. uni_platform
  135. })
  136. return query
  137. }
  138. },
  139. created() {
  140. this.debounceGet = debounce(() => this.getAllData())
  141. this.getChannelData()
  142. },
  143. watch: {
  144. query: {
  145. deep: true,
  146. handler(val) {
  147. this.options.pageCurrent = 1 // 重置分页
  148. this.debounceGet()
  149. }
  150. }
  151. },
  152. methods: {
  153. useDatetimePicker() {
  154. this.currentDateTab = -1
  155. },
  156. changeAppid(id) {
  157. this.getChannelData(id, false)
  158. },
  159. changePlatform(id, index, name, item) {
  160. this.getChannelData(null, id)
  161. this.query.version_id = 0
  162. this.query.uni_platform = item.code
  163. },
  164. changeTimeRange(id, index) {
  165. this.currentDateTab = index
  166. const start = getTimeOfSomeDayAgo(id),
  167. end = getTimeOfSomeDayAgo(0) - 1
  168. this.query.start_time = [start, end]
  169. },
  170. changePageCurrent(e) {
  171. this.options.pageCurrent = e.current
  172. this.getTableData(this.query)
  173. },
  174. changePageSize(pageSize) {
  175. this.options.pageSize = pageSize
  176. this.options.pageCurrent = 1 // 重置分页
  177. this.getTableData()
  178. },
  179. getAllData() {
  180. this.getPanelData()
  181. this.getTableData()
  182. },
  183. getTableData(query) {
  184. if (!this.query.appid){
  185. this.errorMessage = "请先选择应用";
  186. return;
  187. }
  188. this.errorMessage = "";
  189. query = stringifyQuery(this.query, null, ['uni_platform'])
  190. const {
  191. pageCurrent
  192. } = this.options
  193. this.loading = true
  194. const db = uniCloud.database()
  195. const filterAppid = stringifyQuery({
  196. appid: this.query.appid
  197. })
  198. const mainTableTemp = db.collection('uni-stat-pages')
  199. .where(filterAppid)
  200. .field('_id, title, path')
  201. .getTemp()
  202. const subTableTemp = db.collection('uni-stat-page-result')
  203. .where(query)
  204. .getTemp()
  205. db.collection(subTableTemp, mainTableTemp)
  206. .field(
  207. `${stringifyField(fieldsMap)}, stat_date, page_id`
  208. )
  209. .groupBy("page_id")
  210. .groupField(stringifyGroupField(fieldsMap))
  211. .orderBy('visit_times', 'desc')
  212. .skip((pageCurrent - 1) * this.options.pageSize)
  213. .limit(this.options.pageSize)
  214. .get({
  215. getCount: true
  216. })
  217. .then(res => {
  218. const {
  219. count,
  220. data
  221. } = res.result
  222. this.options.total = count
  223. this.tableData = []
  224. for (const item of data) {
  225. const lines = item.page_id
  226. if (Array.isArray(lines)) {
  227. delete(item.page_id)
  228. const line = lines[0]
  229. if (line && Object.keys(line).length) {
  230. for (const key in line) {
  231. if (key !== '_id') {
  232. item[key] = line[key]
  233. }
  234. }
  235. }
  236. }
  237. mapfields(fieldsMap, item, item)
  238. this.tableData.push(item)
  239. }
  240. }).catch((err) => {
  241. console.error(err)
  242. // err.message 错误信息
  243. // err.code 错误码
  244. }).finally(() => {
  245. this.loading = false
  246. })
  247. },
  248. getPanelData(query = stringifyQuery(this.query, null, ['uni_platform'])) {
  249. if (!this.query.appid){
  250. this.errorMessage = "请先选择应用";
  251. return;
  252. }
  253. this.errorMessage = "";
  254. const db = uniCloud.database()
  255. const subTable = db.collection('uni-stat-page-result')
  256. .where(query)
  257. .field(stringifyField(fieldsMap))
  258. .groupBy('appid')
  259. .groupField(stringifyGroupField(fieldsMap))
  260. .orderBy('start_time', 'desc ')
  261. .get()
  262. .then(res => {
  263. const items = res.result.data[0]
  264. this.panelData = []
  265. this.panelData = mapfields(fieldsMap, items)
  266. })
  267. },
  268. inputDialogToggle(url, title) {
  269. this.queryId = url
  270. this.updateValue = title
  271. this.$refs.inputDialog.open()
  272. },
  273. editName(value) {
  274. // 使用 clientDB 提交数据
  275. const db = uniCloud.database()
  276. db.collection('uni-stat-pages')
  277. .where({
  278. path: this.queryId
  279. })
  280. .update({
  281. title: value
  282. })
  283. .then((res) => {
  284. if (res.result.updated) {
  285. uni.showToast({
  286. title: '修改成功'
  287. })
  288. this.getTableData()
  289. } else {
  290. uni.showToast({
  291. title: '修改失败',
  292. icon: "none"
  293. })
  294. }
  295. }).catch((err) => {
  296. uni.showModal({
  297. content: err.message || '请求服务失败',
  298. showCancel: false
  299. })
  300. }).finally(() => {
  301. uni.hideLoading()
  302. })
  303. },
  304. getChannelData(appid, platform_id) {
  305. this.query.channel_id = ''
  306. const db = uniCloud.database()
  307. const condition = {}
  308. //对应应用
  309. appid = appid ? appid : this.query.appid
  310. if (appid) {
  311. condition.appid = appid
  312. }
  313. //对应平台
  314. platform_id = platform_id ? platform_id : this.query.platform_id
  315. if (platform_id) {
  316. condition.platform_id = platform_id
  317. }
  318. let platformTemp = db.collection('uni-stat-app-platforms')
  319. .field('_id, name')
  320. .getTemp()
  321. let channelTemp = db.collection('uni-stat-app-channels')
  322. .where(condition)
  323. .field('_id, channel_name, create_time, platform_id')
  324. .getTemp()
  325. db.collection(channelTemp, platformTemp)
  326. .orderBy('platform_id', 'asc')
  327. .get()
  328. .then(res => {
  329. let data = res.result.data
  330. let channels = []
  331. if (data.length > 0) {
  332. let channelName
  333. for (let i in data) {
  334. channelName = data[i].channel_name ? data[i].channel_name : '默认'
  335. if (data[i].platform_id.length > 0) {
  336. channelName = data[i].platform_id[0].name + '-' + channelName
  337. }
  338. channels.push({
  339. value: data[i]._id,
  340. text: channelName
  341. })
  342. }
  343. }
  344. this.channelData = channels
  345. })
  346. .catch((err) => {
  347. console.error(err)
  348. // err.message 错误信息
  349. // err.code 错误码
  350. }).finally(() => {})
  351. }
  352. }
  353. }
  354. </script>
  355. <style>
  356. .uni-stat-edit--x {
  357. display: flex;
  358. justify-content: space-between;
  359. }
  360. .uni-stat-edit--btn {
  361. cursor: pointer;
  362. }
  363. </style>