tabs.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <view
  3. class="tui-tabs-view"
  4. :class="[
  5. isFixed ? 'tui-tabs-fixed' : 'tui-tabs-relative',
  6. unlined ? 'tui-unlined' : '',
  7. isBoxShadow ? 'tui-tabs-view-shadow' : ''
  8. ]"
  9. :style="{
  10. height: height + 'rpx',
  11. padding: `0 ${padding}rpx`,
  12. background: bgColor,
  13. top: isFixed ? top + 'px' : 'auto'
  14. }"
  15. >
  16. <div
  17. class="item-wrap"
  18. :style="{ width: isAdd ? `calc(100% - ${addTabWidth + 30}rpx)` : '100%' }"
  19. >
  20. <!-- { 'border-left': borderLeft }, -->
  21. <view
  22. v-for="(item, index) in tabs"
  23. :key="index"
  24. :class="[
  25. 'tui-tabs-item',
  26. { active: currentTab == index },
  27. ]"
  28. :style="{ width: itemWidth }"
  29. @tap.stop="swichTabs(item, index)"
  30. >
  31. <view
  32. class="tui-tabs-title"
  33. :class="{
  34. 'tui-tabs-active': currentTab == index,
  35. 'tui-tabs-disabled': item.disabled,
  36. 'border-left': borderLeft && !(index == tabs.length -1)
  37. }"
  38. :style="{
  39. fontSize: size + 'rpx',
  40. lineHeight: size + 'rpx',
  41. fontWeight: bold && currentTab == index ? 'bold' : 'normal'
  42. }"
  43. >
  44. <div class="tabs-title">{{ item.name }}</div>
  45. <!-- tab value -->
  46. <div class="tabs-value" v-if="item.value || item.value == 0">
  47. {{ item.value }}
  48. </div>
  49. </view>
  50. </view>
  51. </div>
  52. <!-- tab add -->
  53. <div
  54. class="tabs-add"
  55. v-if="isAdd"
  56. :style="{ width: `${addTabWidth}rpx` }"
  57. @click="add"
  58. >
  59. <i class="iconfont" :class="[addIcon]"></i>
  60. <span>{{ addText }}</span>
  61. </div>
  62. <!-- <view
  63. class="tui-tabs-slider"
  64. :style="{
  65. transform: 'translateX(' + scrollLeft + 'px)',
  66. width: sliderWidth + 'rpx',
  67. height: sliderHeight + 'rpx',
  68. borderRadius: sliderRadius,
  69. bottom: bottom,
  70. marginBottom: bottom == '50%' ? '-' + sliderHeight / 2 + 'rpx' : 0
  71. }"
  72. ></view> -->
  73. </view>
  74. </template>
  75. <script>
  76. export default {
  77. name: "tuiTabs",
  78. props: {
  79. // 标签页
  80. tabs: {
  81. type: Array,
  82. default() {
  83. return [];
  84. }
  85. },
  86. // rpx
  87. height: {
  88. type: Number,
  89. default: 80
  90. },
  91. // rpx 只对左右padding起作用,上下为0
  92. padding: {
  93. type: Number,
  94. default: 30
  95. },
  96. // 背景色
  97. bgColor: {
  98. type: String,
  99. default: "#FFFFFF"
  100. },
  101. // 是否固定
  102. isFixed: {
  103. type: Boolean,
  104. default: false
  105. },
  106. // px
  107. top: {
  108. type: Number, // #ifndef H5
  109. default: 0, // #endif
  110. // #ifdef H5
  111. default: 0
  112. // #endif
  113. },
  114. // 是否去掉底部线条
  115. unlined: {
  116. type: Boolean,
  117. default: false
  118. },
  119. // 当前选项卡
  120. currentTab: {
  121. type: Number,
  122. default: 0
  123. },
  124. // 滑块宽度
  125. sliderWidth: {
  126. type: Number,
  127. default: 68
  128. },
  129. // 滑块高度
  130. sliderHeight: {
  131. type: Number,
  132. default: 6
  133. },
  134. sliderRadius: {
  135. type: String,
  136. default: "50rpx"
  137. },
  138. // 滑块bottom
  139. bottom: {
  140. type: String,
  141. default: "0"
  142. },
  143. // 标签页宽度
  144. itemWidth: {
  145. type: String,
  146. default: "25%"
  147. },
  148. // 字体颜色
  149. color: {
  150. type: String,
  151. default: "#999"
  152. },
  153. // 字体大小
  154. size: {
  155. type: Number,
  156. default: 28
  157. },
  158. // 选中后 是否加粗 ,未选中则无效
  159. bold: {
  160. type: Boolean,
  161. default: false
  162. },
  163. // 是否显示borer-right
  164. borderLeft: {
  165. type: Boolean,
  166. default: false
  167. },
  168. // 是否有新增按钮
  169. isAdd: {
  170. type: Boolean,
  171. default: false
  172. },
  173. // 新增按钮的icon
  174. addIcon: {
  175. type: String,
  176. default: "icontianjiakehu"
  177. },
  178. addText: {
  179. type: String,
  180. default: "添加"
  181. },
  182. // 是否显示box-shadow
  183. isBoxShadow: {
  184. type: Boolean,
  185. default: true
  186. }
  187. },
  188. watch: {
  189. currentTab() {
  190. this.checkCor();
  191. }
  192. },
  193. created() {
  194. setTimeout(() => {
  195. // 高度自适应
  196. uni.getSystemInfo({
  197. success: res => {
  198. this.winWidth = res.windowWidth;
  199. this.checkCor();
  200. }
  201. });
  202. }, 50);
  203. },
  204. data() {
  205. return {
  206. winWidth: 0,
  207. scrollLeft: 0,
  208. addTabWidth: 130
  209. };
  210. },
  211. computed: {
  212. // addTabWidth() {
  213. // return uni.upx2px(130)
  214. // }
  215. },
  216. methods: {
  217. checkCor: function() {
  218. let addTabWidth = this.isAdd ? uni.upx2px(this.addTabWidth + 30) : 0;
  219. let tabsNum = this.tabs.length;
  220. let padding = (this.winWidth / 750) * this.padding;
  221. let width = this.winWidth - padding * 2 - addTabWidth;
  222. let left =
  223. (width / tabsNum - (this.winWidth / 750) * this.sliderWidth) / 2 + padding;
  224. let scrollLeft = left;
  225. if (this.currentTab > 0) {
  226. scrollLeft = scrollLeft + (width / tabsNum) * this.currentTab;
  227. }
  228. this.scrollLeft = scrollLeft;
  229. },
  230. // 点击标题切换当前页时改变样式
  231. swichTabs: function(i, index) {
  232. let item = this.tabs[index];
  233. if (item && item.disabled) return;
  234. if (this.currentTab == index) {
  235. return false;
  236. } else {
  237. this.$emit("change", {
  238. index: Number(index),
  239. item: i
  240. });
  241. }
  242. },
  243. // 新增
  244. add() {
  245. uni.navigateTo({url:'/pagesClient/member/add'})
  246. // this.$emit("add");
  247. }
  248. }
  249. };
  250. </script>
  251. <style lang="scss" scoped>
  252. .tabs-add {
  253. @include disFlex(center, center);
  254. height: 60px;
  255. border-left: 1px solid $borderColor;
  256. padding-left: 30px;
  257. color: $fontColor3;
  258. .iconfont {
  259. margin-right: 10px;
  260. font-size: 30rpx;
  261. }
  262. }
  263. .tui-tabs-view {
  264. width: 100%;
  265. box-sizing: border-box;
  266. display: flex;
  267. align-items: center;
  268. justify-content: space-between;
  269. z-index: 9;
  270. .tui-tabs-item {
  271. &.border-left {
  272. position: relative;
  273. &::after {
  274. // content: '';
  275. // width: 2upx;
  276. // height: 65%;
  277. // position: absolute;
  278. // left: 0upx;
  279. // top: 50%;
  280. // transform: translate(0,-50%);
  281. // background-color: #ddd;
  282. }
  283. }
  284. }
  285. // .tui-tabs-item:first-child {
  286. // &.border-left {
  287. // &::after {
  288. // content: '';
  289. // }
  290. // }
  291. // }
  292. }
  293. .tui-tabs-view-shadow {
  294. box-shadow: 4px 4px 10px #eee;
  295. }
  296. .tui-tabs-relative {
  297. position: relative;
  298. }
  299. .tui-tabs-fixed {
  300. position: fixed;
  301. left: 0;
  302. }
  303. .tui-tabs-fixed::before,
  304. .tui-tabs-relative::before {
  305. content: "";
  306. position: absolute;
  307. border-bottom: 1upx solid #eaeef1;
  308. -webkit-transform: scaleY(0.5);
  309. transform: scaleY(0.5);
  310. bottom: 0;
  311. right: 0;
  312. left: 0;
  313. }
  314. .tui-unlined::before {
  315. border-bottom: 0 !important;
  316. }
  317. .item-wrap {
  318. width: 100%;
  319. height: 100%;
  320. display: flex;
  321. align-items: center;
  322. // justify-content: center;
  323. color: $fontColor3;
  324. overflow-x: scroll;
  325. }
  326. .tui-tabs-item {
  327. padding: 12upx 0;
  328. position: relative;
  329. display: flex;
  330. height: 100%;
  331. align-items: center;
  332. justify-content: center;
  333. flex-shrink: 0;
  334. &.active {
  335. &:after {
  336. display: block;
  337. position: absolute;
  338. width: 70upx;
  339. height: 6upx;
  340. bottom: 0;
  341. left: 50%;
  342. content: "";
  343. background-color: $mainColor;
  344. transform: translate(-50%, 0);
  345. }
  346. }
  347. }
  348. .tui-tabs-disabled {
  349. opacity: 0.6;
  350. }
  351. .tui-tabs-title {
  352. // display: flex;
  353. // align-items: center;
  354. // justify-content: center;
  355. position: relative;
  356. z-index: 2;
  357. width: 100%;
  358. &.border-left {
  359. &::after {
  360. content: '';
  361. width: 2upx;
  362. height: 40upx;
  363. position: absolute;
  364. right: 0upx;
  365. top: 50%;
  366. transform: translate(0,-50%);
  367. background-color: #ddd;
  368. }
  369. }
  370. &.border-left {
  371. }
  372. }
  373. .tabs-title {
  374. text-align: center;
  375. }
  376. .tabs-value {
  377. // @include disFlex(center, center);
  378. font-size: 24px;
  379. text-align: center;
  380. margin-top: 6px;
  381. }
  382. .tui-tabs-active {
  383. transition: all 0.15s ease-in-out;
  384. color: $mainColor;
  385. }
  386. .tui-tabs-slider {
  387. position: absolute;
  388. left: 0;
  389. transition: all 0.15s ease-in-out;
  390. z-index: 0;
  391. transform: translateZ(0);
  392. background: $mainColor;
  393. }
  394. </style>