uni-stat-tabs.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. <template>
  2. <view class="uni-stat--tab-x">
  3. <view v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</view>
  4. <view class="uni-stat--tab">
  5. <view v-if="!renderTabs.length" class="uni-stat--tab-item uni-stat--tab-item-disabled"
  6. :class="[`uni-stat--tab-item-${type}`]">
  7. {{placeholder}}
  8. </view>
  9. <view v-else v-for="(item, index) in renderTabs" :key="index" @click="change(item, index)"
  10. class="uni-stat--tab-item" :class="[
  11. index === currentTab ? `uni-stat--tab-item-${type}-active` : '' , `uni-stat--tab-item-${type}`,
  12. item.disabled ? 'uni-stat--tab-item-disabled' : ''
  13. ]">
  14. <!-- #ifdef MP -->
  15. {{item.name}}
  16. <!-- #endif -->
  17. <!-- #ifndef MP -->
  18. <uni-tooltip>
  19. {{item.name}}
  20. <uni-icons v-if="item.tooltip" type="help" color="#666" />
  21. <template v-if="item.tooltip" v-slot:content>
  22. <view class="uni-stat-tooltip-s">
  23. {{item.tooltip}}
  24. </view>
  25. </template>
  26. </uni-tooltip>
  27. <!-- #endif -->
  28. </view>
  29. </view>
  30. </view>
  31. </template>
  32. <script>
  33. export default {
  34. name: "uni-stat-tabs",
  35. data() {
  36. return {
  37. currentTab: 0,
  38. renderTabs: [],
  39. cacheKey: "uni-admin-statTabsData"
  40. };
  41. },
  42. props: {
  43. type: {
  44. type: String,
  45. default: 'line'
  46. },
  47. value: {
  48. type: [String, Number],
  49. default: ''
  50. },
  51. modelValue: {
  52. type: [String, Number],
  53. default: ''
  54. },
  55. current: {
  56. type: [String, Number],
  57. default: 0
  58. },
  59. mode: {
  60. type: String,
  61. default: ''
  62. },
  63. today: {
  64. type: Boolean,
  65. default: false
  66. },
  67. yesterday: {
  68. type: Boolean,
  69. default: true
  70. },
  71. disabled: {
  72. type: Boolean,
  73. default: false
  74. },
  75. tooltip: {
  76. type: Boolean,
  77. default: false
  78. },
  79. all: {
  80. type: Boolean,
  81. default: true
  82. },
  83. label: {
  84. type: String,
  85. default: ''
  86. },
  87. placeholder: {
  88. type: String,
  89. default: '暂无选项'
  90. },
  91. tabs: {
  92. type: Array,
  93. default: () => {
  94. return []
  95. }
  96. }
  97. },
  98. created() {
  99. this.last = `${this.mode.replace('-', '_')}_last_data`
  100. },
  101. mounted() {
  102. this.init()
  103. },
  104. computed:{
  105. },
  106. watch: {
  107. current: {
  108. immediate: true,
  109. handler(val) {
  110. this.currentTab = val
  111. }
  112. },
  113. // value(val) {
  114. // this.currentTab = val
  115. // },
  116. tabs: {
  117. immediate: false,
  118. handler(val) {
  119. this.init()
  120. }
  121. },
  122. renderTabs(val) {
  123. const index = this.current
  124. if (this.mode && val.length && index >= 0) {
  125. this.$nextTick(function() {
  126. const item = this.renderTabs[index]
  127. this.change(item, index)
  128. })
  129. }
  130. }
  131. },
  132. methods: {
  133. init() {
  134. if (this.mode.indexOf('platform') > -1) {
  135. this.renderTabs = this.getCache() || [];
  136. this.getPlatform()
  137. } else if (this.mode === 'date') {
  138. const dates = [{
  139. _id: 7,
  140. name: '最近七天',
  141. }, {
  142. _id: 30,
  143. name: '最近30天',
  144. }, {
  145. _id: 90,
  146. name: '最近90天',
  147. }]
  148. if (this.yesterday) {
  149. dates.unshift({
  150. _id: 1,
  151. name: '昨天',
  152. })
  153. }
  154. if (this.today) {
  155. dates.unshift({
  156. _id: 0,
  157. name: '今天',
  158. })
  159. }
  160. this.renderTabs = dates
  161. } else {
  162. this.renderTabs = this.tabs
  163. }
  164. },
  165. change(item, index) {
  166. if (item.disabled) return
  167. const id = item._id
  168. const name = item.name
  169. this.currentTab = index
  170. this.emit(id, index, name, item)
  171. },
  172. emit(id, index, name, item) {
  173. this.$emit('change', id, index, name, item)
  174. this.$emit('input', id, index, name)
  175. this.$emit('update:modelValue', id, index, name)
  176. },
  177. getPlatform() {
  178. const db = uniCloud.database()
  179. const appList = db.collection('uni-stat-app-platforms')
  180. .get()
  181. .then(res => {
  182. let platforms = res.result.data
  183. platforms = platforms.filter(p => p.hasOwnProperty('enable') ? p.enable : true)
  184. platforms.sort((a, b) => a.order - b.order)
  185. if (this.mode === 'platform-channel') {
  186. platforms = platforms.filter(item => /^android|ios$/.test(item.code))
  187. let _id = platforms.map(p => `platform_id == "${p._id}"`).join(' || ')
  188. _id = `(${_id})`
  189. this.setAllItem(platforms, _id)
  190. } else if (this.mode === 'platform-scene') {
  191. platforms = platforms.filter(item => /mp-/.test(item.code))
  192. let _id = platforms.map(p => `platform_id == "${p._id}"`).join(' || ')
  193. _id = `(${_id})`
  194. this.setAllItem(platforms, _id)
  195. } else {
  196. this.setAllItem(platforms)
  197. }
  198. this.setCache(platforms);
  199. this.renderTabs = platforms
  200. })
  201. },
  202. setAllItem(platforms, _id = '', name = '全部') {
  203. this.all && platforms.unshift({
  204. name,
  205. _id
  206. })
  207. },
  208. // 获取当前缓存key
  209. getCurrentCacheKey(){
  210. return this.mode;
  211. },
  212. // 获取缓存
  213. getCache(name=this.getCurrentCacheKey()){
  214. let cacheData = uni.getStorageSync(this.cacheKey) || {};
  215. return cacheData[name];
  216. },
  217. // 设置缓存
  218. setCache(value, name=this.getCurrentCacheKey()){
  219. let cacheData = uni.getStorageSync(this.cacheKey) || {};
  220. cacheData[name] = value;
  221. uni.setStorageSync(this.cacheKey, cacheData);
  222. },
  223. // 删除缓存
  224. removeCache(name=this.getCurrentCacheKey()){
  225. let cacheData = uni.getStorageSync(this.cacheKey) || {};
  226. delete cacheData[name];
  227. uni.setStorageSync(this.cacheKey, cacheData);
  228. },
  229. }
  230. }
  231. </script>
  232. <style lang="scss">
  233. .uni-stat-tooltip-s {
  234. width: 160px;
  235. white-space: normal;
  236. }
  237. .uni-label-text {
  238. font-size: 14px;
  239. font-weight: bold;
  240. color: #555;
  241. margin-top: 17px;
  242. margin-bottom: 17px;
  243. margin-right: 5px;
  244. // display: flex;
  245. // align-items: center;
  246. // justify-content: center;
  247. }
  248. .uni-stat--tab-x {
  249. display: flex;
  250. margin: 0 15px;
  251. white-space: nowrap;
  252. }
  253. .uni-stat--tab {
  254. display: flex;
  255. flex-wrap: wrap;
  256. }
  257. .uni-stat {
  258. &--tab {
  259. &-item {
  260. white-space: nowrap;
  261. font-size: 14px;
  262. color: #666;
  263. text-align: center;
  264. cursor: pointer;
  265. box-sizing: border-box;
  266. margin: 15px 0;
  267. &-disabled {
  268. cursor: unset;
  269. opacity: 0.4;
  270. }
  271. &-line {
  272. margin-right: 30px;
  273. padding: 2px 0;
  274. border-bottom: 1px solid transparent;
  275. &:last-child {
  276. margin-right: 0;
  277. }
  278. &-active {
  279. color: $uni-color-primary;
  280. border-bottom: 1px solid $uni-color-primary;
  281. // &-disabled {
  282. // color: #666;
  283. // border-color: #666;
  284. // }
  285. }
  286. }
  287. &-boldLine {
  288. box-sizing: border-box;
  289. margin-right: 30px;
  290. padding: 2px 0;
  291. border-bottom: 2px solid transparent;
  292. &:last-child {
  293. margin-right: 0;
  294. }
  295. &-active {
  296. box-sizing: border-box;
  297. color: $uni-color-primary;
  298. border-bottom: 2px solid $uni-color-primary;
  299. }
  300. }
  301. &-box {
  302. padding: 5px 15px;
  303. border: 1px solid #dcdfe6;
  304. // margin: 0;
  305. &:not(:last-child) {
  306. border-right-color: transparent;
  307. }
  308. &-active {
  309. box-sizing: border-box;
  310. border: 1px solid $uni-color-primary !important;
  311. }
  312. }
  313. }
  314. }
  315. }
  316. /* #ifndef APP-NVUE */
  317. @media screen and (max-width: 500px) {
  318. .hide-on-phone {
  319. display: none;
  320. }
  321. .uni-stat--tab {
  322. flex-wrap: unset;
  323. overflow-x: auto !important;
  324. }
  325. /* #ifdef H5 */
  326. ::-webkit-scrollbar {
  327. display: none;
  328. }
  329. /* #endif */
  330. }
  331. /* #endif */
  332. </style>