From d1448cb0ef10f358bb7bddb4e1ec268515e0b787 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期二, 15 七月 2025 11:46:57 +0800 Subject: [PATCH] 项目初始化 --- uni_modules/uview-ui/components/u-subsection/u-subsection.vue | 299 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 299 insertions(+), 0 deletions(-) diff --git a/uni_modules/uview-ui/components/u-subsection/u-subsection.vue b/uni_modules/uview-ui/components/u-subsection/u-subsection.vue new file mode 100644 index 0000000..cc4d540 --- /dev/null +++ b/uni_modules/uview-ui/components/u-subsection/u-subsection.vue @@ -0,0 +1,299 @@ +<template> + <view + class="u-subsection" + ref="u-subsection" + :class="[`u-subsection--${mode}`]" + :style="[$u.addStyle(customStyle), wrapperStyle]" + > + <view + class="u-subsection__bar" + ref="u-subsection__bar" + :style="[barStyle]" + :class="[ + mode === 'button' && 'u-subsection--button__bar', + current === 0 && + mode === 'subsection' && + 'u-subsection__bar--first', + current > 0 && + current < list.length - 1 && + mode === 'subsection' && + 'u-subsection__bar--center', + current === list.length - 1 && + mode === 'subsection' && + 'u-subsection__bar--last', + ]" + ></view> + <view + class="u-subsection__item" + :class="[ + `u-subsection__item--${index}`, + index < list.length - 1 && + 'u-subsection__item--no-border-right', + index === 0 && 'u-subsection__item--first', + index === list.length - 1 && 'u-subsection__item--last', + ]" + :ref="`u-subsection__item--${index}`" + :style="[itemStyle(index)]" + @tap="clickHandler(index)" + v-for="(item, index) in list" + :key="index" + > + <text + class="u-subsection__item__text" + :style="[textStyle(index)]" + >{{ getText(item) }}</text + > + </view> + </view> +</template> + +<script> +// #ifdef APP-NVUE +const dom = uni.requireNativePlugin("dom"); +const animation = uni.requireNativePlugin("animation"); +// #endif +import props from "./props.js"; +/** + * Subsection 鍒嗘鍣� + * @description 璇ュ垎娈靛櫒涓�鑸敤浜庣敤鎴蜂粠鍑犱釜閫夐」涓�夋嫨鏌愪竴涓殑鍦烘櫙 + * @tutorial https://www.uviewui.com/components/subsection.html + * @property {Array} list tab鐨勬暟鎹� + * @property {String 锝� Number} current 褰撳墠娲诲姩鐨則ab鐨刬ndex锛堥粯璁� 0 锛� + * @property {String} activeColor 婵�娲绘椂鐨勯鑹诧紙榛樿 '#3c9cff' 锛� + * @property {String} inactiveColor 鏈縺娲绘椂鐨勯鑹诧紙榛樿 '#303133' 锛� + * @property {String} mode 妯″紡閫夋嫨锛宮ode=button涓烘寜閽舰寮忥紝mode=subsection鏃朵负鍒嗘妯″紡锛堥粯璁� 'button' 锛� + * @property {String 锝� Number} fontSize 瀛椾綋澶у皬锛屽崟浣峱x锛堥粯璁� 12 锛� + * @property {Boolean} bold 婵�娲婚�夐」鐨勫瓧浣撴槸鍚﹀姞绮楋紙榛樿 true 锛� + * @property {String} bgColor 缁勪欢鑳屾櫙棰滆壊锛宮ode涓篵utton鏃舵湁鏁堬紙榛樿 '#eeeeef' 锛� + * @property {Object} customStyle 瀹氫箟闇�瑕佺敤鍒扮殑澶栭儴鏍峰紡 + * @property {String} keyName 浠巂list`鍏冪礌瀵硅薄涓鍙栫殑閿悕锛堥粯璁� 'name' 锛� + * + * @event {Function} change 鍒嗘鍣ㄩ�夐」鍙戠敓鏀瑰彉鏃惰Е鍙� 鍥炶皟 index锛氶�夐」鐨刬ndex绱㈠紩鍊硷紝浠�0寮�濮� + * @example <u-subsection :list="list" :current="curNow" @change="sectionChange"></u-subsection> + */ +export default { + name: "u-subsection", + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // 缁勪欢灏哄 + itemRect: { + width: 0, + height: 0, + }, + }; + }, + watch: { + list(newValue, oldValue) { + this.init(); + }, + current: { + immediate: true, + handler(n) { + // #ifdef APP-NVUE + // 鍦ㄥ畨鍗搉vue涓婏紝濡傛灉閫氳繃translateX杩涜浣嶇Щ锛屽埌鏈�鍚庝竴涓椂锛屼細瀵艰嚧鍙充晶鏃犳硶缁樺埗鍦嗚 + // 鏁呯敤animation妯″潡杩涜浣嶇Щ + const ref = this.$refs?.["u-subsection__bar"]?.ref; + // 涓嶅瓨鍦╮ef鐨勬椂鍊�(鐞嗚В涓虹涓�娆″垵濮嬪寲鏃讹紝闇�瑕佹覆鏌揹om锛岃繘琛屼竴瀹氬欢鏃跺啀鑾峰彇ref)锛岃繖閲岀殑100ms鏄粡杩囨祴璇曞緱鍑虹殑缁撴灉(鏌愪簺瀹夊崜闇�瑕佸欢鏃朵箙涓�鐐�)锛屽嬁闅忔剰淇敼 + uni.$u.sleep(ref ? 0 : 100).then(() => { + animation.transition(this.$refs["u-subsection__bar"].ref, { + styles: { + transform: `translateX(${ + n * this.itemRect.width + }px)`, + transformOrigin: "center center", + }, + duration: 300, + }); + }); + // #endif + }, + }, + }, + computed: { + wrapperStyle() { + const style = {}; + // button妯″紡鏃讹紝璁剧疆鑳屾櫙鑹� + if (this.mode === "button") { + style.backgroundColor = this.bgColor; + } + return style; + }, + // 婊戝潡鐨勬牱寮� + barStyle() { + const style = {}; + style.width = `${this.itemRect.width}px`; + style.height = `${this.itemRect.height}px`; + // 閫氳繃translateX绉诲姩婊戝潡锛屽叾绉诲姩鐨勮窛绂讳负绱㈠紩*item鐨勫搴� + // #ifndef APP-NVUE + style.transform = `translateX(${ + this.current * this.itemRect.width + }px)`; + // #endif + if (this.mode === "subsection") { + // 鍦╯ubsection妯″紡涓嬶紝闇�瑕佸姩鎬佽缃粦鍧楃殑鍦嗚锛屽洜涓虹Щ鍔ㄦ粦鍧椾娇鐢ㄧ殑鏄痶ranslateX锛屾棤娉曢�氳繃鐖跺厓绱犺缃畂verflow: hidden闅愯棌婊戝潡鐨勭洿瑙� + style.backgroundColor = this.activeColor; + } + return style; + }, + // 鍒嗘鍣╥tem鐨勬牱寮� + itemStyle(index) { + return (index) => { + const style = {}; + if (this.mode === "subsection") { + // 璁剧疆border鐨勬牱寮� + style.borderColor = this.activeColor; + style.borderWidth = "1px"; + style.borderStyle = "solid"; + } + return style; + }; + }, + // 鍒嗘鍣ㄦ枃瀛楅鑹� + textStyle(index) { + return (index) => { + const style = {}; + style.fontWeight = + this.bold && this.current === index ? "bold" : "normal"; + style.fontSize = uni.$u.addUnit(this.fontSize); + // subsection妯″紡涓嬶紝婵�娲绘椂榛樿涓虹櫧鑹茬殑鏂囧瓧 + if (this.mode === "subsection") { + style.color = + this.current === index ? "#fff" : this.inactiveColor; + } else { + // button妯″紡涓嬶紝婵�娲绘椂鏂囧瓧棰滆壊榛樿涓篴ctiveColor + style.color = + this.current === index + ? this.activeColor + : this.inactiveColor; + } + return style; + }; + }, + }, + mounted() { + this.init(); + }, + methods: { + init() { + uni.$u.sleep().then(() => this.getRect()); + }, + // 鍒ゆ柇灞曠ず鏂囨湰 + getText(item) { + return typeof item === 'object' ? item[this.keyName] : item + }, + // 鑾峰彇缁勪欢鐨勫昂瀵� + getRect() { + // #ifndef APP-NVUE + this.$uGetRect(".u-subsection__item--0").then((size) => { + this.itemRect = size; + }); + // #endif + + // #ifdef APP-NVUE + const ref = this.$refs["u-subsection__item--0"][0]; + ref && + dom.getComponentRect(ref, (res) => { + this.itemRect = res.size; + }); + // #endif + }, + clickHandler(index) { + this.$emit("change", index); + }, + }, +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/components.scss"; + +.u-subsection { + @include flex; + position: relative; + overflow: hidden; + /* #ifndef APP-NVUE */ + width: 100%; + box-sizing: border-box; + /* #endif */ + + &--button { + height: 32px; + background-color: rgb(238, 238, 239); + padding: 3px; + border-radius: 3px; + align-items: stretch; + + &__bar { + background-color: #ffffff; + border-radius: 3px !important; + } + } + + &--subsection { + height: 30px; + } + + &__bar { + position: absolute; + /* #ifndef APP-NVUE */ + transition-property: transform, color; + transition-duration: 0.3s; + transition-timing-function: ease-in-out; + /* #endif */ + + &--first { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + } + + &--center { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + } + + &--last { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } + } + + &__item { + @include flex; + flex: 1; + justify-content: center; + align-items: center; + // vue鐜涓嬶紝闇�瑕佽缃浉瀵瑰畾浣嶏紝鍥犱负婊戝潡涓虹粷瀵瑰畾浣嶏紝item闇�瑕佸湪婊戝潡鐨勪笂闈� + position: relative; + + &--no-border-right { + border-right-width: 0 !important; + } + + &--first { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + } + + &--last { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } + + &__text { + font-size: 12px; + line-height: 12px; + @include flex; + align-items: center; + transition-property: color; + transition-duration: 0.3s; + } + } +} +</style> -- Gitblit v1.9.3