util.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /**
  2. * 以下为 uni-stat 的工具方法
  3. */
  4. // 将查询条件拼接为字符串
  5. function stringifyQuery(query, dimension = false, delArrs = []) {
  6. const queryArr = []
  7. const keys = Object.keys(query)
  8. const time = query.start_time
  9. keys.forEach(key => {
  10. if (key === 'time_range' || delArrs.indexOf(key) !== -1) return
  11. let val = query[key]
  12. if (val) {
  13. if (typeof val === 'string' && val.indexOf(key) > -1) {
  14. queryArr.push(val)
  15. } else {
  16. if (typeof val === 'string') {
  17. val = `"${val}"`
  18. }
  19. if (Array.isArray(val)) {
  20. if (val.length === 2 && key.indexOf('time') > -1) {
  21. queryArr.push(`${key} >= ${val[0]} && ${key} <= ${val[1]}`)
  22. } else {
  23. val = val.map(item => `${key} == "${item}"`).join(' || ')
  24. val && queryArr.push(`(${val})`)
  25. }
  26. } else if (dimension && key === 'dimension') {
  27. if (maxDeltaDay(time)) {
  28. queryArr.push(`dimension == "hour"`)
  29. } else {
  30. if (val && val !== `"hour"`) {
  31. queryArr.push(`${key} == ${val}`)
  32. } else {
  33. queryArr.push(`dimension == "day"`)
  34. }
  35. }
  36. } else {
  37. queryArr.push(`${key} == ${val}`)
  38. }
  39. }
  40. }
  41. })
  42. const queryStr = queryArr.join(' && ')
  43. return queryStr || {}
  44. }
  45. // 根据页面字段配置 fieldsMap 数据计算、格式化字段
  46. function mapfields(map, data = {}, goal, prefix = '', prop = 'value') {
  47. const goals = [],
  48. argsGoal = goal
  49. map = JSON.parse(JSON.stringify(map))
  50. const origin = JSON.parse(JSON.stringify(data))
  51. for (const mapper of map) {
  52. let {
  53. field,
  54. computed,
  55. formatter,
  56. disable,
  57. fix
  58. } = mapper
  59. if (!disable) {
  60. goal = argsGoal || mapper
  61. const hasValue = goal.hasOwnProperty(prop)
  62. const preField = prefix + field
  63. if (data) {
  64. const value = data[preField]
  65. if (computed) {
  66. const computedFields = computed.split('/')
  67. let [dividend, divisor] = computedFields
  68. dividend = Number(origin[prefix + dividend])
  69. divisor = Number(origin[prefix + divisor])
  70. const val = format(division(dividend, divisor), formatter, fix)
  71. if (hasValue && field === goal.field) {
  72. goal[prop] = val
  73. } else {
  74. goal[field] = val
  75. }
  76. } else {
  77. if (value) {
  78. const val = format(value, formatter, fix)
  79. if (hasValue) {
  80. if (goal.field === field) {
  81. goal[prop] = val
  82. }
  83. } else {
  84. goal[field] = val
  85. }
  86. }
  87. }
  88. }
  89. if (hasValue) {
  90. goals.push(goal)
  91. }
  92. }
  93. }
  94. return goals
  95. }
  96. // 将查询条件对象拼接为字符串,给 client db 的 field 属性消费
  97. function stringifyField(mapping, goal, prop) {
  98. if (goal) {
  99. mapping = mapping.filter(f => f.field === goal)
  100. }
  101. if (prop) {
  102. mapping = mapping.filter(f => f.field && f.hasOwnProperty(prop))
  103. }
  104. const fieldString = mapping.map(f => {
  105. let fields = []
  106. if (f.computed) {
  107. fields = f.computed.split('/')
  108. } else {
  109. fields.push(f.field)
  110. }
  111. fields = fields.map(field => {
  112. if (f.stat === -1) {
  113. return field
  114. } else {
  115. return `${field} as ${ 'temp_' + field}`
  116. }
  117. })
  118. return fields.join()
  119. })
  120. return fieldString.join()
  121. }
  122. // 将查询条件对象拼接为字符串,给 client db 的 groupField 属性消费
  123. function stringifyGroupField(mapping, goal, prop) {
  124. if (goal) {
  125. mapping = mapping.filter(f => f.field === goal)
  126. }
  127. if (prop) {
  128. mapping = mapping.filter(f => f.field && f.hasOwnProperty(prop))
  129. }
  130. const groupField = mapping.map(f => {
  131. const stat = f.stat
  132. let fields = []
  133. if (f.computed) {
  134. fields = f.computed.split('/')
  135. } else {
  136. fields.push(f.field)
  137. }
  138. fields = fields.map(field => {
  139. if (stat !== -1) {
  140. return `${stat ? stat : 'sum' }(${'temp_' + field}) as ${field}`
  141. }
  142. })
  143. return fields.filter(Boolean).join()
  144. })
  145. .filter(Boolean)
  146. .join()
  147. return groupField
  148. }
  149. // 除法函数
  150. function division(dividend, divisor) {
  151. if (divisor) {
  152. return dividend / divisor
  153. } else {
  154. return 0
  155. }
  156. }
  157. // 对数字进行格式化,格式 type 配置在页面 fieldMap.js 中
  158. function format(num, type = ',', fix) {
  159. // if (!type) return num
  160. if (typeof num !== 'number') return num
  161. if (type === '%') {
  162. // 注意浮点数精度
  163. num = (num * 100)
  164. if (String(num).indexOf('.') > -1) {
  165. num = num.toFixed(2)
  166. }
  167. num = num ? num + type : num
  168. return num
  169. } else if (type === '%%') {
  170. num = Number(num)
  171. return num.toFixed(2) + '%'
  172. } else if (type === '-') {
  173. return formatDate(num, 'day')
  174. } else if (type === ':') {
  175. num = Math.ceil(num)
  176. let h, m, s
  177. h = m = s = 0
  178. const wunH = 60 * 60,
  179. wunM = 60 // 单位秒, wun 通 one
  180. if (num >= wunH) {
  181. h = Math.floor(num / wunH)
  182. const remainder = num % wunH
  183. if (remainder >= wunM) {
  184. m = Math.floor(remainder / wunM)
  185. s = remainder % wunM
  186. } else {
  187. s = remainder
  188. }
  189. } else if (wunH >= num && num >= wunM) {
  190. m = Math.floor(num / wunM)
  191. s = num % wunM
  192. } else {
  193. s = num
  194. }
  195. const hms = [h, m, s].map(i => i < 10 ? '0' + i : i)
  196. return hms.join(type)
  197. } else if (type === ',') {
  198. return num.toLocaleString()
  199. } else {
  200. if (String(num).indexOf('.') > -1) {
  201. if (Math.abs(num) > 1) {
  202. num = num.toFixed(fix || 0)
  203. } else {
  204. num = num.toFixed(fix || 2)
  205. }
  206. }
  207. return num
  208. }
  209. }
  210. // 格式化日期,返回其所在的范围
  211. function formatDate(date, type) {
  212. let d = new Date(date)
  213. if (type === 'hour') {
  214. let h = d.getHours()
  215. h = h < 10 ? '0' + h : h
  216. return `${h}:00 ~ ${h}:59`
  217. } else if (type === 'week') {
  218. const first = d.getDate() - d.getDay() + 1; // First day is the day of the month - the day of the week
  219. const last = first + 6; // last day is the first day + 6
  220. let firstday = new Date(d.setDate(first));
  221. firstday = parseDateTime(firstday)
  222. let lastday = new Date(d.setDate(last));
  223. lastday = parseDateTime(lastday)
  224. return `${firstday} ~ ${lastday}`
  225. } else if (type === 'month') {
  226. let firstday = new Date(d.getFullYear(), d.getMonth(), 1);
  227. firstday = parseDateTime(firstday)
  228. let lastday = new Date(d.getFullYear(), d.getMonth() + 1, 0);
  229. lastday = parseDateTime(lastday)
  230. return `${firstday} ~ ${lastday}`
  231. } else {
  232. return parseDateTime(d)
  233. }
  234. }
  235. // 格式化日期,返回其 yyyy-mm-dd 格式
  236. function parseDateTime(datetime, type, splitor = '-') {
  237. let d = datetime
  238. if (typeof d !== 'object') {
  239. d = new Date(d)
  240. }
  241. const year = d.getFullYear()
  242. const month = d.getMonth() + 1
  243. const day = d.getDate()
  244. const hour = d.getHours()
  245. const minute = d.getMinutes()
  246. const second = d.getSeconds()
  247. const date = [year, lessTen(month), lessTen(day)].join(splitor)
  248. const time = [lessTen(hour), lessTen(minute), lessTen(second)].join(':')
  249. if (type === "dateTime") {
  250. return date + ' ' + time
  251. }
  252. return date
  253. }
  254. function lessTen(item) {
  255. return item < 10 ? '0' + item : item
  256. }
  257. // 获取指定日期当天或 n 天前零点的时间戳,丢弃时分秒
  258. function getTimeOfSomeDayAgo(days = 0, date = Date.now()) {
  259. const d = new Date(date)
  260. const oneDayTime = 24 * 60 * 60 * 1000
  261. let ymd = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join('/')
  262. ymd = ymd + ' 00:00:00'
  263. const someDaysAgoTime = new Date(ymd).getTime() - oneDayTime * days
  264. return someDaysAgoTime
  265. }
  266. // 判断时间差值 delta,单位为天
  267. function maxDeltaDay(times, delta = 2) {
  268. if (!times.length) return true
  269. const wunDay = 24 * 60 * 60 * 1000
  270. const [start, end] = times
  271. const max = end - start < wunDay * delta
  272. return max
  273. }
  274. // 查询 总设备数、总用户数, 通过 field 配置
  275. function getFieldTotal(query = this.query, field = "total_devices") {
  276. let fieldTotal
  277. if (typeof query === 'object') {
  278. query = stringifyQuery(query, false, ['uni_platform'])
  279. }
  280. const db = uniCloud.database()
  281. return db.collection('uni-stat-result')
  282. .where(query)
  283. .field(`${field} as temp_${field}, start_time`)
  284. .groupBy('start_time')
  285. .groupField(`sum(temp_${field}) as ${field}`)
  286. .orderBy('start_time', 'desc')
  287. .get()
  288. .then(cur => {
  289. const data = cur.result.data
  290. fieldTotal = data.length && data[0][field]
  291. fieldTotal = format(fieldTotal)
  292. this.panelData && this.panelData.forEach(item => {
  293. if (item.field === field) {
  294. item.value = fieldTotal
  295. }
  296. })
  297. return Promise.resolve(fieldTotal)
  298. })
  299. }
  300. // 防抖函数
  301. function debounce(fn, time = 100) {
  302. let timer = null
  303. return function(...args) {
  304. if (timer) clearTimeout(timer)
  305. timer = setTimeout(() => {
  306. fn.apply(this, args)
  307. }, time)
  308. }
  309. }
  310. const files = {}
  311. function fileToUrl(file) {
  312. for (const key in files) {
  313. if (files.hasOwnProperty(key)) {
  314. const oldFile = files[key]
  315. if (oldFile === file) {
  316. return key
  317. }
  318. }
  319. }
  320. var url = (window.URL || window.webkitURL).createObjectURL(file)
  321. files[url] = file
  322. return url
  323. }
  324. /**
  325. * 获取两个时间戳之间的所有时间
  326. * let start = new Date(1642694400000) // 2022-01-21 00:00:00
  327. * let end = new Date(1643644800000) // 2022-02-01 00:00:00
  328. * dateList = getAllDateCN(date1, date2)
  329. * @param {*} startTime
  330. * @param {*} endTime
  331. */
  332. function getAllDateCN(startTime, endTime) {
  333. let date_all = [];
  334. let i = 0;
  335. while (endTime.getTime() - startTime.getTime() >= 0) {
  336. // 获取日期和时间
  337. // let year = startTime.getFullYear()
  338. // let month = startTime.getMonth() + 1
  339. // let day = startTime.getDate()
  340. // let time = startTime.toLocaleTimeString()
  341. date_all[i] = startTime.getTime()
  342. // 获取每天00:00:00的时间戳
  343. // date_all[i] = new Date(startTime.toLocaleDateString()).getTime() / 1000;
  344. // 天数+1
  345. startTime.setDate(startTime.getDate() + 1);
  346. i += 1;
  347. }
  348. return date_all;
  349. }
  350. function createUniStatQuery(object) {
  351. return Object.assign({}, object, {
  352. type: "native_app",
  353. create_env: "uni-stat"
  354. })
  355. }
  356. export {
  357. stringifyQuery,
  358. stringifyField,
  359. stringifyGroupField,
  360. mapfields,
  361. getTimeOfSomeDayAgo,
  362. division,
  363. format,
  364. formatDate,
  365. parseDateTime,
  366. maxDeltaDay,
  367. debounce,
  368. fileToUrl,
  369. getFieldTotal,
  370. getAllDateCN,
  371. createUniStatQuery
  372. }