Quellcode durchsuchen

feat: 完成主页7+6静态页面编写

huangziyang vor 2 Wochen
Ursprung
Commit
5a76d6a5fe

+ 13 - 9
components/Container/Container.vue

@@ -9,7 +9,7 @@
       v-if="showTitle"
     >
       <uni-nav-bar
-        :left-icon="showBack ? 'arrow-left' : ''"
+        :left-icon="showBack ? 'left' : ''"
         @clickLeft="onBack"
         :border="false"
         :title="title"
@@ -36,6 +36,7 @@
         :style="{
           height: `${safeArea.height}px`,
           whiteSpace: scrollX ? 'nowrap' : 'normal',
+          ...scrollStyle,
         }"
       >
         <slot></slot>
@@ -46,6 +47,7 @@
       </view>
     </scroll-view>
     <view
+      v-if="$slots.footer"
       class="bottom-button"
       :style="{
         width: `${safeArea.width}px`,
@@ -58,10 +60,10 @@
 </template>
 
 <script setup>
-import pages from '@/pages.json'
+import pages from "@/pages.json";
 import { ref, onMounted, watchEffect } from "vue";
 import { getRoute, router } from "../../utils/router";
-import { getRect } from "../../utils/utils";
+import { getRect } from "../../utils";
 import { getCurrentInstance } from "vue";
 
 const props = defineProps({
@@ -89,9 +91,9 @@ const props = defineProps({
     type: String,
     default: "",
   },
-  style: {
-    type: [String, Object],
-    default: "",
+  scrollStyle: {
+    type: Object,
+    default: () => ({}),
   },
   onBack: Function,
   showBack: {
@@ -106,7 +108,7 @@ const props = defineProps({
     type: String,
     default: "#fff",
   },
-  title: String
+  title: String,
 });
 
 const emit = defineEmits(["onSafeAreaChange"]);
@@ -133,12 +135,14 @@ onMounted(() => {
     ...systemInfo.safeArea,
     source: systemInfo.safeArea,
   };
-  const isTarbarPage = pages.tabBar.list.map(item => item.pagePath).includes(getRoute().routeList[0].path)
+  const isTarbarPage = pages.tabBar.list
+    .map((item) => item.pagePath)
+    .includes(getRoute().routeList[0].path);
   if (isTarbarPage) {
     // 高度再减掉tabbar高度
     safeArea.value.height -= 50;
     // 减去系统导航栏高度
-    safeArea.value.height -= (systemInfo.statusBarHeight - 18);
+    safeArea.value.height -= systemInfo.statusBarHeight - 18;
   }
   // 24是内边距
   safeArea.value.width -= 24;

+ 4 - 1
main.js

@@ -23,6 +23,7 @@ app.$mount()
 // #ifdef VUE3
 import { createSSRApp } from 'vue'
 import App from './App.vue'
+import * as Pinia from 'pinia';
 // 全局请求
 import http from './utils/request.js'
 // 精度计算
@@ -34,6 +35,7 @@ import ext from './utils/ext.js'
 
 export function createApp() {
   const app = createSSRApp(App)
+  app.use(Pinia.createPinia())
   // 挂载全局属性
   app.config.globalProperties.$http = http
   // 挂载全局属性
@@ -42,7 +44,8 @@ export function createApp() {
   app.config.globalProperties.$checkAccess = checkAccess
   app.config.globalProperties.$ext = ext
   return {
-    app
+    app,
+    Pinia
   }
 }
 // #endif

+ 15 - 4
pages.json

@@ -3,25 +3,36 @@
     {
       "path": "pages/home/index",
       "style": {
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "navigationBarTitleText": "首页"
       }
     },
     {
       "path": "pages/learn/index",
       "style": {
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "navigationBarTitleText": "学习本"
       }
     },
     {
       "path": "pages/challenge/index",
       "style": {
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "navigationBarTitleText": "挑战"
       }
     },
     {
       "path": "pages/user/index",
       "style": {
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "navigationBarTitleText": "我的"
+      }
+    },
+    {
+      "path": "pages/regulations/index",
+      "style": {
+        "navigationStyle": "custom",
+        "navigationBarTitleText": "法规"
       }
     },
     {

+ 141 - 3
pages/home/index.vue

@@ -1,23 +1,96 @@
 <template>
-  <Container title="首页" :showBack="false">
+  <Container
+    title="首页"
+    :showBack="false"
+    :scrollStyle="{
+      paddingLeft: 0,
+      paddingRight: 0,
+    }"
+  >
     <view class="home">
+      <!-- 倒计时 -->
       <view class="time">
         <view>倒计时</view>
         <view>151天</view>
       </view>
+      <!-- 轮播图 -->
+      <swiper class="swiper" circular autoplay>
+        <swiper-item>
+          <view class="swiper-item">A</view>
+        </swiper-item>
+        <swiper-item>
+          <view class="swiper-item">B</view>
+        </swiper-item>
+        <swiper-item>
+          <view class="swiper-item">C</view>
+        </swiper-item>
+      </swiper>
+      <!-- 公告 -->
+      <view class="notice">
+        <view class="title">公告</view>
+        <view>这是公告</view>
+      </view>
+      <!-- 2025新大纲 -->
+      <view class="new_outline">
+        <uni-section title="基础用法" type="line">
+          <view class="p-20">
+            <uni-segmented-control
+              :flex="false"
+              :current="current"
+              :values="items"
+              style-type="text"
+              @clickItem="(e) => (current = e.currentIndex)"
+            />
+            <!-- 执业药师 -->
+            <view v-if="current === 0" class="grid">
+              <view v-for="item in 7" class="flex" @click="clickClass">
+                <view class="bg-red"></view>
+                <view> 执业药师{{ item }} </view>
+              </view>
+            </view>
+            <!-- 药学职称 -->
+            <view v-if="current === 1" class="grid"
+              ><view v-for="item in 7" class="flex" @click="clickClass">
+                <view class="bg-red"></view>
+                <view> 药学职称{{ item }} </view>
+              </view></view
+            >
+          </view>
+        </uni-section>
+      </view>
     </view>
+    <uni-section title="往年真题" type="line">
+      <!-- 往年真题 -->
+      <view class="grid-3">
+        <view v-for="item in 7" class="flex">
+          <view class="bg-red"></view>
+          <view> 执业药师{{ item }} </view>
+        </view>
+      </view>
+    </uni-section>
   </Container>
 </template>
 
-<script setup lang="ts">
+<script setup>
+import { ref } from "vue";
+
 import Container from "../../components/Container/Container.vue";
+import { router } from "../../utils/router";
+
+const current = ref(0);
+const items = ref(["标签1", "标签2"]);
+
+const clickClass = () => {
+  router.push({
+    url: '/pages/regulations/index'
+  })
+}
 </script>
 
 <style scoped lang="scss">
 .home {
   display: flex;
   flex-direction: column;
-  align-items: center;
   gap: 20rpx;
 
   .time {
@@ -26,5 +99,70 @@ import Container from "../../components/Container/Container.vue";
     justify-content: center;
     gap: 80rpx;
   }
+
+  .swiper {
+    height: 320rpx;
+    border: 1rpx solid #000000;
+    width: 100%;
+    .swiper-item {
+      display: block;
+      height: 320rpx;
+      line-height: 320rpx;
+      text-align: center;
+      background-color: red;
+    }
+  }
+
+  .notice {
+    display: flex;
+    align-items: center;
+    gap: 20rpx;
+    padding-left: 26rpx;
+  }
+
+  .new_outline {
+    border: 1rpx solid #000000;
+  }
+}
+
+.title {
+  font-family: "PingFang SC, PingFang SC";
+  font-weight: 700;
+  font-size: 32rpx;
+  color: #000000;
+}
+
+.p-20 {
+  padding: 0 30rpx 30rpx;
+  display: flex;
+  flex-direction: column;
+  gap: 20rpx;
+}
+
+.grid {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 20rpx;
+}
+
+.grid-3 {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 20rpx;
+  height: 100%;
+}
+
+.flex {
+  display: flex;
+  flex-direction: column;
+  gap: 20rpx;
+  align-items: center;
+  justify-content: center;
+}
+
+.bg-red {
+  width: 149rpx;
+  height: 80rpx;
+  background: #d9d9d9;
 }
 </style>

+ 1 - 1
pages/login/index.vue

@@ -79,7 +79,7 @@ export default {
                 uni.setStorageSync("shopId", re.data.shop_id);
               }
               // 跳转到页面
-				uni.redirectTo({ url: "/pages/user/index" });
+				uni.switchTab({ url: "/pages/user/index" });
             } else {
               uni.showToast({
                 title: re.msg,

+ 0 - 55
pages/mine/index.vue

@@ -1,55 +0,0 @@
-<template>
-  <Topic :topics="list" mode="practice" @answerChange="answerChange"></Topic>
-</template>
-
-<script setup>
-import Topic from "@/components/Topic/Topic.vue";
-const list = {
-  ques: [
-    {
-      id: 1,
-      title: "测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目测试题目",
-      questions: [
-        { label: "测试1", value: 1 },
-        { label: "测试2", value: 2 },
-        { label: "测试3", value: 3 },
-        { label: "测试4", value: 4 },
-        { label: "测试5", value: 5 },
-      ],
-      anslist: [2],
-    },
-    {
-      id: 2,
-      title: "测试题目",
-      questions: [
-        { label: "测试1", value: 1 },
-        { label: "测试2", value: 2 },
-        { label: "测试3", value: 3 },
-        { label: "测试4", value: 4 },
-        { label: "测试5", value: 5 },
-      ],
-      anslist: [2, 4],
-    },
-
-    {
-      id: 3,
-      title: "测试题目",
-			mode: '综合分析题',
-      questions: [
-        { label: "测试1", value: 1 },
-        { label: "测试2", value: 2 },
-        { label: "测试3", value: 3 },
-        { label: "测试4", value: 4 },
-        { label: "测试5", value: 5 },
-      ],
-      anslist: [2, 3],
-    },
-  ],
-};
-
-const answerChange = (item) => {
-  console.log(item);
-};
-</script>
-
-<style></style>

+ 261 - 0
pages/regulations/index.vue

@@ -0,0 +1,261 @@
+<template>
+  <Container
+    title="法规"
+    :scrollY="maskStyle.height < 0"
+    @onSafeAreaChange="onSafeAreaChange"
+  >
+    <uni-collapse
+      ref="collapse"
+      v-model="value"
+      class="class-content"
+      @change="onChnage"
+    >
+      <view class="free-content">
+        <uni-collapse-item
+          :open="index <= 1"
+          :title="`第${numberConvertToUppercase(index + 1)}章 ${item.title}`"
+          v-for="(item, index) in chaptersList.slice(0, 2)"
+          :key="item.id"
+          class="text"
+        >
+          <view class="-mt-20">
+            <view class="content" v-for="(i, ind) in item.children" :key="i.id">
+              <view class="text"
+                >{{ `第${numberConvertToUppercase(ind + 1)}节` }}
+                {{ i.title }}</view
+              >
+              <view class="buttons">
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment"
+                  v-if="i.isStudied === 0"
+                  >开始学习</view
+                >
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment warning"
+                  v-if="i.isStudied > 0 && i.isStudied < 100"
+                  >继续学习</view
+                >
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment"
+                  v-if="i.isStudied === 100"
+                  >去练习</view
+                >
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment success"
+                  v-if="i.isStudied === 100"
+                  >已学习</view
+                >
+              </view>
+            </view>
+          </view>
+        </uni-collapse-item>
+      </view>
+      <!-- 付费功能 -->
+      <view class="pay-content">
+        <view
+          class="modal-mask"
+          :style="{
+            height: `${maskStyle.height}px`,
+            width: `${maskStyle.width}px`,
+          }"
+        >
+          <uni-icons type="locked" color="#fff" size="35"></uni-icons>
+          <view class="modal-wrapper">邀请好友可解锁</view>
+        </view>
+        <uni-collapse-item
+          :title="`第${numberConvertToUppercase(index + 3)}章 ${item.title}`"
+          v-for="(item, index) in chaptersList.slice(2)"
+          :key="item.id"
+          class="text"
+        >
+          <view class="-mt-20">
+            <view class="content" v-for="(i, ind) in item.children" :key="i.id">
+              <view class="text"
+                >{{ `第${numberConvertToUppercase(ind + 1)}节` }}
+                {{ i.title }}</view
+              >
+              <view class="buttons">
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment"
+                  v-if="i.isStudied === 0"
+                  >开始学习</view
+                >
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment warning"
+                  v-if="i.isStudied > 0 && i.isStudied < 100"
+                  >继续学习</view
+                >
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment"
+                  v-if="i.isStudied === 100"
+                  >去练习</view
+                >
+                <view
+                  @click="onClickButton(i.isStudied)"
+                  class="comment success"
+                  v-if="i.isStudied === 100"
+                  >已学习</view
+                >
+              </view>
+            </view>
+          </view>
+        </uni-collapse-item>
+      </view>
+    </uni-collapse>
+  </Container>
+</template>
+
+<script setup name="regulations">
+import Container from "../../components/Container/Container.vue";
+import { ref, getCurrentInstance } from "vue";
+import { numberConvertToUppercase, getRect } from "../../utils";
+const collapse = ref(null);
+const value = ref("");
+const instance = getCurrentInstance();
+const safeArea = ref({});
+const maskStyle = ref({
+  height: 0,
+  width: 0,
+});
+
+const chaptersList = ref(
+  new Array(10)
+    .fill({
+      title: "测试1",
+      id: 1,
+      children: new Array(5)
+        .fill({
+          id: 11,
+        })
+        .map((item, index) => {
+          return {
+            title: `测试1-${index + 1}`,
+            id: index + item.id,
+            isStudied: index === 1 ? 0 : index === 2 ? 20 : 100,
+          };
+        }),
+    })
+    .map((iten, index) => {
+      return {
+        ...iten,
+        title: `测试${index + 1}`,
+        id: index + 1,
+      };
+    })
+);
+
+const onClickButton = (isStudied) => {
+  console.log(isStudied);
+};
+
+const resolveHeight = () =>
+  setTimeout(() => {
+    getRect({
+      name: ".free-content",
+      instance,
+      onSuccess(res) {
+        maskStyle.value.width = safeArea.value?.source?.width || 0;
+        maskStyle.value.height = safeArea.value.height - res.height;
+      },
+    });
+    // 动画300需要等待
+  }, 300);
+
+const onSafeAreaChange = (s) => {
+  safeArea.value = s;
+  resolveHeight();
+};
+
+const onChnage = () => {
+  resolveHeight();
+};
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+.text {
+  font-family: PingFang SC, PingFang SC;
+  font-weight: 500;
+  font-size: 28rpx;
+  color: #000000;
+}
+
+.content {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 20rpx 4rpx 40rpx;
+  .buttons {
+    display: flex;
+    gap: 10rpx;
+  }
+  .comment {
+    width: 132rpx;
+    height: 48rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #fff;
+    color: $primary;
+    border: 1px solid $primary;
+    font-family: "PingFang SC, PingFang SC";
+    font-weight: 500;
+    font-size: 28rpx;
+    color: #002fa7;
+    border-radius: 4rpx;
+  }
+
+  .comment.success {
+    color: $success;
+    border: 1px solid $success;
+  }
+
+  .comment.warning {
+    color: $warning;
+    border: 1px solid $warning;
+  }
+}
+
+.class-content {
+  height: 100%;
+}
+
+.pay-content {
+  flex: 1;
+  position: relative;
+
+  .modal-mask {
+    background-color: rgba($color: #858585, $alpha: 0.8);
+    position: absolute;
+    height: 100%;
+    z-index: 9999;
+    left: -24rpx;
+    display: flex;
+    align-items: center;
+    flex-direction: column;
+    justify-content: center;
+    gap: 34rpx;
+  }
+}
+
+.modal-wrapper {
+  width: 685rpx;
+  height: 64rpx;
+  background: #dfdfdf;
+  font-family: PingFang SC, PingFang SC;
+  font-weight: 500;
+  font-size: 28rpx;
+  color: #000000;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+</style>

+ 9 - 5
pages/user/index.vue

@@ -1,5 +1,6 @@
 <template>
-  <view>
+  <Container title="我的" :showBack="false">
+    <view>
     <view class="user_box">
       <view class="box_left">
         <navigator url="/pages/user/settings">
@@ -13,7 +14,7 @@
       </view>
       <view class="box_right">
         <navigator url="/pages/user/settings" class="setting_page" v-if="is_login">
-          <image class="setting_icon" src="https://kailin-mp.oss-cn-shenzhen.aliyuncs.com/static/icon/setting.png"></image>
+          <uni-icons type="gear" size="30"></uni-icons>
         </navigator>
       </view>
     </view>
@@ -23,15 +24,15 @@
       </navigator>
 	  <navigator class="navigator_item" url="/pages/orders/index">
 	    <view class="navigator_title">订单记录</view>
-		<view class="navigator_title_ico">></view>
+		<view class="navigator_title_ico"><uni-icons type="right" size="20"></uni-icons></view>
 	  </navigator>
 	  <navigator class="navigator_item" url="/">
 	    <view class="navigator_title">分享有礼</view>
-		<view class="navigator_title_ico">></view>
+		<view class="navigator_title_ico"><uni-icons type="right" size="20"></uni-icons></view>
 	  </navigator>
 	  <navigator class="navigator_item" url="/">
 	    <view class="navigator_title">邀请有礼</view>
-		<view class="navigator_title_ico">></view>
+		<view class="navigator_title_ico"><uni-icons type="right" size="20"></uni-icons></view>
 	  </navigator>
     </view>
     <view class="packet_content" v-if="show_packet">
@@ -39,9 +40,12 @@
       <image src="https://kailin-mp.oss-cn-shenzhen.aliyuncs.com/static/icon/red_packet.gif" class="red_packet" @click="_getredpacket" />
     </view>
   </view>
+  </Container>
 </template>
 
 <script>
+import Container from "../../components/Container/Container.vue";
+
 export default {
   data() {
     return {

+ 10 - 0
store/user.js

@@ -0,0 +1,10 @@
+import { defineStore } from 'pinia'
+
+export const useUserStore = defineStore('user', () => {
+	const count = ref(0);
+	function increment() {
+		count.value++;
+	}
+
+	return { count, increment };
+});

+ 4 - 1
uni.scss

@@ -4,6 +4,9 @@ $uni-primary: #002FA7;
 $uni-primary-disable:#94bcff;
 $uni-primary-light: #F3F6FF;
 
+$primary: #002FA7;
+
 $success: #00be00;
 $error: #f00;
-$default: #e7e7e7;
+$default: #e7e7e7;
+$warning: #ff9900;

+ 150 - 141
uni_modules/uni-section/components/uni-section/uni-section.vue

@@ -1,167 +1,176 @@
 <template>
-	<view class="uni-section">
-		<view class="uni-section-header" @click="onClick">
-				<view class="uni-section-header__decoration" v-if="type" :class="type" />
-        <slot v-else name="decoration"></slot>
+  <view class="uni-section">
+    <view class="uni-section-header" @click="onClick">
+      <view class="uni-section-header__decoration" v-if="type" :class="type" />
+      <slot v-else name="decoration"></slot>
 
-        <view class="uni-section-header__content">
-          <text :style="{'font-size':titleFontSize,'color':titleColor}" class="uni-section__content-title" :class="{'distraction':!subTitle}">{{ title }}</text>
-          <text v-if="subTitle" :style="{'font-size':subTitleFontSize,'color':subTitleColor}" class="uni-section-header__content-sub">{{ subTitle }}</text>
-        </view>
+      <view class="uni-section-header__content">
+        <text
+          :style="{ 'font-size': titleFontSize, color: titleColor }"
+          class="uni-section__content-title"
+          :class="{ distraction: !subTitle }"
+          >{{ title }}</text
+        >
+        <text
+          v-if="subTitle"
+          :style="{ 'font-size': subTitleFontSize, color: subTitleColor }"
+          class="uni-section-header__content-sub"
+          >{{ subTitle }}</text
+        >
+      </view>
 
-        <view class="uni-section-header__slot-right">
-          <slot name="right"></slot>
-        </view>
-		</view>
+      <view class="uni-section-header__slot-right">
+        <slot name="right"></slot>
+      </view>
+    </view>
 
-		<view class="uni-section-content" :style="{padding: _padding}">
-			<slot />
-		</view>
-	</view>
+    <view class="uni-section-content" :style="{ padding: _padding }">
+      <slot />
+    </view>
+  </view>
 </template>
 
 <script>
+/**
+ * Section 标题栏
+ * @description 标题栏
+ * @property {String} type = [line|circle|square] 标题装饰类型
+ * 	@value line 竖线
+ * 	@value circle 圆形
+ * 	@value square 正方形
+ * @property {String} title 主标题
+ * @property {String} titleFontSize 主标题字体大小
+ * @property {String} titleColor 主标题字体颜色
+ * @property {String} subTitle 副标题
+ * @property {String} subTitleFontSize 副标题字体大小
+ * @property {String} subTitleColor 副标题字体颜色
+ * @property {String} padding 默认插槽 padding
+ */
 
-	/**
-	 * Section 标题栏
-	 * @description 标题栏
-	 * @property {String} type = [line|circle|square] 标题装饰类型
-	 * 	@value line 竖线
-	 * 	@value circle 圆形
-	 * 	@value square 正方形
-	 * @property {String} title 主标题
-	 * @property {String} titleFontSize 主标题字体大小
-	 * @property {String} titleColor 主标题字体颜色
-	 * @property {String} subTitle 副标题
-	 * @property {String} subTitleFontSize 副标题字体大小
-	 * @property {String} subTitleColor 副标题字体颜色
-	 * @property {String} padding 默认插槽 padding
-	 */
-
-	export default {
-		name: 'UniSection',
-    emits:['click'],
-		props: {
-			type: {
-				type: String,
-				default: ''
-			},
-			title: {
-				type: String,
-				required: true,
-				default: ''
-			},
-      titleFontSize: {
-        type: String,
-        default: '14px'
-      },
-			titleColor:{
-				type: String,
-				default: '#333'
-			},
-			subTitle: {
-				type: String,
-				default: ''
-			},
-      subTitleFontSize: {
-        type: String,
-        default: '12px'
-      },
-      subTitleColor: {
-        type: String,
-        default: '#999'
-      },
-			padding: {
-				type: [Boolean, String],
-				default: false
-			}
-		},
-    computed:{
-      _padding(){
-        if(typeof this.padding === 'string'){
-          return this.padding
-        }
+export default {
+  name: "UniSection",
+  emits: ["click"],
+  props: {
+    type: {
+      type: String,
+      default: "",
+    },
+    title: {
+      type: String,
+      required: true,
+      default: "",
+    },
+    titleFontSize: {
+      type: String,
+      default: "14px",
+    },
+    titleColor: {
+      type: String,
+      default: "#333",
+    },
+    subTitle: {
+      type: String,
+      default: "",
+    },
+    subTitleFontSize: {
+      type: String,
+      default: "12px",
+    },
+    subTitleColor: {
+      type: String,
+      default: "#999",
+    },
+    padding: {
+      type: [Boolean, String],
+      default: false,
+    },
+  },
+  computed: {
+    _padding() {
+      if (typeof this.padding === "string") {
+        return this.padding;
+      }
 
-        return this.padding?'10px':''
+      return this.padding ? "10px" : "";
+    },
+  },
+  watch: {
+    title(newVal) {
+      if (uni.report && newVal !== "") {
+        uni.report("title", newVal);
       }
     },
-		watch: {
-			title(newVal) {
-				if (uni.report && newVal !== '') {
-					uni.report('title', newVal)
-				}
-			}
-		},
-    methods: {
-			onClick() {
-				this.$emit('click')
-			}
-		}
-	}
+  },
+  methods: {
+    onClick() {
+      this.$emit("click");
+    },
+  },
+};
 </script>
-<style lang="scss" >
-	$uni-primary: #2979ff !default;
+<style lang="scss">
+$uni-primary: #2979ff !default;
 
-	.uni-section {
-		background-color: #fff;
-    .uni-section-header {
-      position: relative;
-      /* #ifndef APP-NVUE */
-      display: flex;
-      /* #endif */
-      flex-direction: row;
-      align-items: center;
-      padding: 12px 10px;
-      font-weight: normal;
+.uni-section {
+  background-color: #fff;
+  .uni-section-header {
+    position: relative;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    align-items: center;
+    padding: 12px 10px;
+    font-weight: normal;
 
-      &__decoration{
-        margin-right: 6px;
-        background-color: $uni-primary;
-        &.line {
-          width: 4px;
-          height: 12px;
-          border-radius: 10px;
-        }
+    &__decoration {
+      margin-right: 6px;
+      background: #d9d9d9;
+      &.line {
+        width: 4rpx;
+        height: 27rpx;
+        border-radius: 10px;
+      }
 
-        &.circle {
-          width: 8px;
-          height: 8px;
-          border-top-right-radius: 50px;
-          border-top-left-radius: 50px;
-          border-bottom-left-radius: 50px;
-          border-bottom-right-radius: 50px;
-        }
+      &.circle {
+        width: 8px;
+        height: 8px;
+        border-top-right-radius: 50px;
+        border-top-left-radius: 50px;
+        border-bottom-left-radius: 50px;
+        border-bottom-right-radius: 50px;
+      }
 
-        &.square {
-          width: 8px;
-          height: 8px;
-        }
+      &.square {
+        width: 8px;
+        height: 8px;
       }
+    }
 
-      &__content {
-        /* #ifndef APP-NVUE */
-        display: flex;
-        /* #endif */
-        flex-direction: column;
-        flex: 1;
-        color: #333;
+    &__content {
+      /* #ifndef APP-NVUE */
+      display: flex;
+      /* #endif */
+      flex-direction: column;
+      flex: 1;
+      color: #333;
 
-        .distraction {
-          flex-direction: row;
-          align-items: center;
-        }
-        &-sub {
-          margin-top: 2px;
-        }
+      .distraction {
+        flex-direction: row;
+        align-items: center;
       }
-
-      &__slot-right{
-        font-size: 14px;
+      &-sub {
+        margin-top: 2px;
       }
     }
 
-    .uni-section-content{
+    &__slot-right {
       font-size: 14px;
     }
-	}
+  }
+
+  .uni-section-content {
+    font-size: 14px;
+  }
+}
 </style>

+ 178 - 130
uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue

@@ -1,146 +1,194 @@
 <template>
-	<view :class="[styleType === 'text'?'segmented-control--text' : 'segmented-control--button' ]"
-		:style="{ borderColor: styleType === 'text' ? '' : activeColor }" class="segmented-control">
-		<view v-for="(item, index) in values" :class="[styleType === 'text' ? '' : 'segmented-control__item--button',
-					index === 0 && styleType === 'button' ? 'segmented-control__item--button--first' : '',
-					index === values.length - 1 && styleType === 'button' ? 'segmented-control__item--button--last':'']" :key="index"
-			:style="{backgroundColor: index === currentIndex && styleType === 'button' ? activeColor : styleType === 'button' ?inActiveColor:'transparent', borderColor: index === currentIndex && styleType === 'text' || styleType === 'button' ? activeColor : inActiveColor}"
-			class="segmented-control__item" @click="_onClick(index)">
-			<view>
-				<text
-					:style="{color:index === currentIndex? styleType === 'text'? activeColor: '#fff': styleType === 'text'? '#000': activeColor}"
-					class="segmented-control__text"
-					:class="styleType === 'text' && index === currentIndex ? 'segmented-control__item--text': ''">{{ item }}</text>
-			</view>
-
-		</view>
-	</view>
+  <view
+    :class="[
+      styleType === 'text'
+        ? 'segmented-control--text'
+        : 'segmented-control--button',
+    ]"
+    :style="{ borderColor: styleType === 'text' ? '' : activeColor, gap: !flex ? '20rpx':0 }"
+    class="segmented-control"
+  >
+    <view
+      v-for="(item, index) in values"
+      :class="[
+        styleType === 'text' ? '' : 'segmented-control__item--button',
+        index === 0 && styleType === 'button'
+          ? 'segmented-control__item--button--first'
+          : '',
+        index === values.length - 1 && styleType === 'button'
+          ? 'segmented-control__item--button--last'
+          : '',
+      ]"
+      :key="index"
+      :style="{
+        backgroundColor:
+          index === currentIndex && styleType === 'button'
+            ? activeColor
+            : styleType === 'button'
+            ? inActiveColor
+            : 'transparent',
+        borderColor:
+          (index === currentIndex && styleType === 'text') ||
+          styleType === 'button'
+            ? activeColor
+            : inActiveColor,
+        flex: flex ?  1  : '',
+      }"
+      class="segmented-control__item"
+      @click="_onClick(index)"
+    >
+      <view>
+        <text
+          :style="{
+            color:
+              index === currentIndex
+                ? styleType === 'text'
+                  ? activeColor
+                  : '#fff'
+                : styleType === 'text'
+                ? '#000'
+                : activeColor,
+          }"
+          class="segmented-control__text"
+          :class="
+            styleType === 'text' && index === currentIndex
+              ? 'segmented-control__item--text'
+              : ''
+          "
+          >{{ item }}</text
+        >
+      </view>
+    </view>
+  </view>
 </template>
 
 <script>
-	/**
-	 * SegmentedControl 分段器
-	 * @description 用作不同视图的显示
-	 * @tutorial https://ext.dcloud.net.cn/plugin?id=54
-	 * @property {Number} current 当前选中的tab索引值,从0计数
-	 * @property {String} styleType = [button|text] 分段器样式类型
-	 * 	@value button 按钮类型
-	 * 	@value text 文字类型
-	 * @property {String} activeColor 选中的标签背景色与边框颜色
-	 * @property {String} inActiveColor 未选中的标签背景色与边框颜色
-	 * @property {Array} values 选项数组
-	 * @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
-	 */
+/**
+ * SegmentedControl 分段器
+ * @description 用作不同视图的显示
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=54
+ * @property {Number} current 当前选中的tab索引值,从0计数
+ * @property {String} styleType = [button|text] 分段器样式类型
+ * 	@value button 按钮类型
+ * 	@value text 文字类型
+ * @property {String} activeColor 选中的标签背景色与边框颜色
+ * @property {String} inActiveColor 未选中的标签背景色与边框颜色
+ * @property {Array} values 选项数组
+ * @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
+ */
 
-	export default {
-		name: 'UniSegmentedControl',
-		emits: ['clickItem'],
-		props: {
-			current: {
-				type: Number,
-				default: 0
-			},
-			values: {
-				type: Array,
-				default () {
-					return []
-				}
-			},
-			activeColor: {
-				type: String,
-				default: '#2979FF'
-			},
-			inActiveColor: {
-				type: String,
-				default: 'transparent'
-			},
-			styleType: {
-				type: String,
-				default: 'button'
-			}
-		},
-		data() {
-			return {
-				currentIndex: 0
-			}
-		},
-		watch: {
-			current(val) {
-				if (val !== this.currentIndex) {
-					this.currentIndex = val
-				}
-			}
-		},
-		computed: {},
-		created() {
-			this.currentIndex = this.current
-		},
-		methods: {
-			_onClick(index) {
-				if (this.currentIndex !== index) {
-					this.currentIndex = index
-					this.$emit('clickItem', {
-						currentIndex: index
-					})
-				}
-			}
+export default {
+  name: "UniSegmentedControl",
+  emits: ["clickItem"],
+  props: {
+    current: {
+      type: Number,
+      default: 0,
+    },
+    values: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    activeColor: {
+      type: String,
+      default: "#2979FF",
+    },
+    inActiveColor: {
+      type: String,
+      default: "transparent",
+    },
+    styleType: {
+      type: String,
+      default: "button",
+    },
+		flex: {
+			type: Boolean,
+			default: true,
 		}
-	}
+  },
+  data() {
+    return {
+      currentIndex: 0,
+    };
+  },
+  watch: {
+    current(val) {
+      if (val !== this.currentIndex) {
+        this.currentIndex = val;
+      }
+    },
+  },
+  computed: {},
+  created() {
+    this.currentIndex = this.current;
+  },
+  methods: {
+    _onClick(index) {
+      if (this.currentIndex !== index) {
+        this.currentIndex = index;
+        this.$emit("clickItem", {
+          currentIndex: index,
+        });
+      }
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.segmented-control {
-		/* #ifndef APP-NVUE */
-		display: flex;
-		box-sizing: border-box;
-		/* #endif */
-		flex-direction: row;
-		height: 36px;
-		overflow: hidden;
-		/* #ifdef H5 */
-		cursor: pointer;
-		/* #endif */
-	}
+.segmented-control {
+  /* #ifndef APP-NVUE */
+  display: flex;
+  box-sizing: border-box;
+  /* #endif */
+  flex-direction: row;
+  height: 36px;
+  overflow: hidden;
+  /* #ifdef H5 */
+  cursor: pointer;
+  /* #endif */
+}
 
-	.segmented-control__item {
-		/* #ifndef APP-NVUE */
-		display: inline-flex;
-		box-sizing: border-box;
-		/* #endif */
-		position: relative;
-		flex: 1;
-		justify-content: center;
-		align-items: center;
-	}
+.segmented-control__item {
+  /* #ifndef APP-NVUE */
+  display: inline-flex;
+  box-sizing: border-box;
+  /* #endif */
+  position: relative;
+  justify-content: center;
+  align-items: center;
+}
 
-	.segmented-control__item--button {
-		border-style: solid;
-		border-top-width: 1px;
-		border-bottom-width: 1px;
-		border-right-width: 1px;
-		border-left-width: 0;
-	}
+.segmented-control__item--button {
+  border-style: solid;
+  border-top-width: 1px;
+  border-bottom-width: 1px;
+  border-right-width: 1px;
+  border-left-width: 0;
+}
 
-	.segmented-control__item--button--first {
-		border-left-width: 1px;
-		border-top-left-radius: 5px;
-		border-bottom-left-radius: 5px;
-	}
+.segmented-control__item--button--first {
+  border-left-width: 1px;
+  border-top-left-radius: 5px;
+  border-bottom-left-radius: 5px;
+}
 
-	.segmented-control__item--button--last {
-		border-top-right-radius: 5px;
-		border-bottom-right-radius: 5px;
-	}
+.segmented-control__item--button--last {
+  border-top-right-radius: 5px;
+  border-bottom-right-radius: 5px;
+}
 
-	.segmented-control__item--text {
-		border-bottom-style: solid;
-		border-bottom-width: 2px;
-		padding: 6px 0;
-	}
+.segmented-control__item--text {
+  border-bottom-style: solid;
+  border-bottom-width: 2px;
+  padding: 6px 0;
+}
 
-	.segmented-control__text {
-		font-size: 14px;
-		line-height: 20px;
-		text-align: center;
-	}
+.segmented-control__text {
+  font-size: 14px;
+  line-height: 20px;
+  text-align: center;
+}
 </style>

+ 54 - 0
utils/index.js

@@ -0,0 +1,54 @@
+// 获取元素宽高
+export const getRect = ({ name, onSuccess, instance, multiple }) => {
+  // 创建一个选择器查询对象
+  const select = uni.createSelectorQuery().in(instance.proxy);
+  // 选择指定元素,并获取其矩形信息
+  select
+    .select(name)
+    .boundingClientRect((rect) => {
+      // 如果rect是一个数组,则返回
+      if (!rect) return;
+      if (Array.isArray(rect)) return multiple ? rect : rect[0];
+      // 如果onSuccess存在,则调用onSuccess函数,并传入rect的高度
+      onSuccess?.(rect);
+    })
+    .exec();
+};
+
+//- 小写数字转换成大写, 只处理到[0 ~ 99]
+export const numberConvertToUppercase = (num) => {
+  num = Number(num);
+  const upperCaseNumber = [
+    "零",
+    "一",
+    "二",
+    "三",
+    "四",
+    "五",
+    "六",
+    "七",
+    "八",
+    "九",
+    "十",
+    "百",
+    "千",
+    "万",
+    "亿",
+  ];
+  let length = String(num).length;
+  if (length == 1) {
+    return upperCaseNumber[num];
+  } else if (length == 2) {
+    if (num == 10) {
+      return upperCaseNumber[num];
+    } else if (num > 10 && num < 20) {
+      return "十" + upperCaseNumber[String(num).charAt(1)];
+    } else {
+      return (
+        upperCaseNumber[String(num).charAt(0)] +
+        "十" +
+        upperCaseNumber[String(num).charAt(1)].replace("零", "")
+      );
+    }
+  }
+};

+ 0 - 16
utils/utils.js

@@ -1,16 +0,0 @@
-// 获取元素宽高
-export const getRect = ({ name, onSuccess, instance }) => {
-  // 创建一个选择器查询对象
-  const select = uni.createSelectorQuery().in(instance.proxy);
-  // 选择指定元素,并获取其矩形信息
-  select
-    .select(name)
-    .boundingClientRect((rect) => {
-      // 如果rect是一个数组,则返回
-      if (!rect) return;
-      if (Array.isArray(rect)) return rect[0];
-      // 如果onSuccess存在,则调用onSuccess函数,并传入rect的高度
-      onSuccess?.(rect);
-    })
-    .exec();
-};