Explorar el Código

修改弹窗样式

lex-xin hace 3 meses
padre
commit
0224b57fff

+ 3 - 3
src/helpers/utils.ts

@@ -94,13 +94,13 @@ export const getHttpOrigin = () => {
  */
 export const formatterDatePicker = (type: any, option: any) => {
   if (type === 'year') {
-    option.text += '年'
+    option += '年'
   }
   if (type === 'month') {
-    option.text += '月'
+    option += '月'
   }
   if (type === 'day') {
-    option.text += '日'
+    option += '日'
   }
   return option
 }

+ 10 - 0
src/styles/README.md

@@ -0,0 +1,10 @@
+### components-ui
+
+1、在 Vant3.x 基础上封装一套独立样式,因环境差异较大数据应统一输入尽量不要请求接口;
+2、注意 Vant 库等必要依赖库的版本差异;
+3、组件采用 less 的方式编写;
+
+### 使用
+
+1、把项目中 index.less 在项目的根目录中使用;
+2、一些基础组件,只会在原生有 UI 组件上变更样式;

+ 54 - 0
src/styles/component-ui.less

@@ -0,0 +1,54 @@
+// 公用变量
+@import './global.less';
+
+// 选择框
+// 上拉选择 - ✅
+// 选择器 - ✅
+.van-picker {
+  --van-picker-toolbar-height: 44px !important;
+  .van-picker__toolbar {
+    position: relative;
+    &::after {
+      position: absolute;
+      box-sizing: border-box;
+      content: ' ';
+      pointer-events: none;
+      right: var(--van-padding-md);
+      bottom: 0;
+      left: var(--van-padding-md);
+      border-bottom: 1px solid var(--van-cell-border-color);
+      transform: scaleY(0.5);
+    }
+  }
+  .van-picker__columns {
+    padding: 0 24px;
+  }
+  .van-picker-column {
+    position: relative;
+    z-index: 1;
+  }
+  .van-picker__frame {
+    z-index: 0;
+    &::after {
+      background: var(--k-bg-4);
+      border-radius: 8px;
+    }
+  }
+  .van-picker__cancel,
+  .van-picker__confirm {
+    font-size: 15px;
+  }
+  .van-picker__cancel {
+    color: var(--k-gray-3);
+  }
+  .van-picker__confirm {
+    color: var(--k-font-primary);
+  }
+  .van-picker-column__item {
+    color: var(--k-gray-1);
+    font-size: 16px;
+  }
+  .van-picker-column__item--selected {
+    font-weight: 600;
+  }
+}

+ 129 - 0
src/styles/global.less

@@ -0,0 +1,129 @@
+// 注意:为什么要写两个重复的 :root?
+// 由于 vant 中的主题变量也是在 :root 下声明的,所以在有些情况下会由于优先级的问题无法成功覆盖。通过
+// :root:root 可以显式地让你所写内容的优先级更高一些,从而确保主题变量的成功覆盖。
+:root:root {
+  // 01 品牌色
+  --k-primary: #2dc7aa;
+
+  // 02 背景色
+  --k-bg-1: #fff;
+  --k-bg-2: #f8f8f8;
+  --k-bg-3: #f6f6f6;
+  --k-bg-4: #f2f2f2;
+
+  // 03 辅助色
+  --k-orange: #ffebdd;
+  --k-red: #f44541;
+  --k-blue: #64a9ff;
+  --k-purple: #8f80ff;
+
+  // 04 渐变色
+  --k-gradient-1: linear-gradient(90deg, #ff9c63 0%, #ff7144 100%);
+  --k-gradient-2: linear-gradient(270deg, #ff4f44 0%, #ffafab 100%);
+  --k-gradient-3: linear-gradient(90deg, #8cccff 0%, #459aff 100%);
+  --k-gradient-4: linear-gradient(90deg, #d4a9ff 0%, #8f80ff 100%);
+  --k-gradient-5: linear-gradient(90deg, #a9f0b4 0%, #09c58c 100%);
+
+  // 05 字体颜色
+  --k-font-primary: #2dc7aa;
+  --k-font-danger: #f44541;
+  --k-gray-1: #333333;
+  --k-gray-2: #666666;
+  --k-gray-3: #777777;
+  --k-gray-4: #aaaaaa;
+  --k-gray-5: #cccccc;
+
+  // 06 分割线
+  --k-hairline-dark: #eeeeee;
+  --k-hairline-shallow: #f2f2f2;
+
+  // 07 蒙层
+  --k-overlay-background-dark: rgba(0, 0, 0, 0.7);
+  --k-overlay-background-shallow: rgba(0, 0, 0, 0.5);
+
+  // 圆角
+  --k-radius-sm: 2px;
+  --k-radius-md: 4px;
+  --k-radius-lg: 8px;
+  --k-radius-xl: 10px;
+  --k-radius-max: 999px;
+
+  // 间距
+  --k-padding-base: 4px;
+  --k-padding-xs: 6px;
+  --k-padding-sm: 8px;
+  --k-padding-md: 12px;
+  --k-padding-lg: 16px;
+  --k-padding-xl: 20px;
+  --k-padding-page: 13px; // 页面是基础边距
+  --k-padding-card: 9px; // 卡片的基础边距
+
+  // 描边 投影
+  --k-border-color: var(--k-primary);
+  --k-border-width: 1px;
+  --k-shadow: 0px 2px 12px 0px rgba(100, 101, 102, 0.12);
+
+  // 设置Vant UI组件库中的默认样式;
+  --van-primary: var(--k-primary);
+  --van-primary-color: var(--van-primary);
+  --van-primary-text: var(--k-font-primary);
+  --van-text-color: var(--k-gray-1);
+
+  // 多选框
+  --van-checkbox-border-color: #dcdcdc;
+  --van-checkbox-label-color: var(--k-gray-1);
+  --van-checkbox-disabled-icon-color: #dcdcdc;
+  --van-checkbox-disabled-label-color: var(--k-gray-5);
+  --van-checkbox-disabled-background: #f7f8fa;
+
+  // 单选框
+  --van-radio-border-color: #dcdcdc;
+  --van-radio-disabled-icon-color: #dcdcdc;
+  --van-radio-disabled-background: #f7f8fa;
+
+  // 导航
+  --van-nav-bar-arrow-size: 20px;
+  --van-nav-bar-title-font-size: 18px;
+  --van-nav-bar-title-text-color: var(--k-gray-1);
+  --van-nav-bar-icon-color: var(--k-gray-1);
+
+  // tab 选择卡
+  --van-tab-text-color: var(--k-gray-3);
+  --van-tabs-bottom-bar-width: 40px;
+  --van-tab-active-text-color: var(--k-gray-1);
+
+  // 侧边导航栏(分类选择)
+  --van-sidebar-selected-border-width: 2px;
+  --van-sidebar-selected-border-height: 18px;
+  --van-sidebar-text-color: var(--k-gray-1);
+  --van-sidebar-selected-text-color: var(--k-primary);
+
+  // 宫格
+  --van-grid-item-text-color: var(--k-gray-1);
+  --van-grid-item-text-font-size: 14px;
+
+  // 步骤条
+  --van-step-horizontal-title-font-size: 14px;
+  --van-step-finish-text-color: var(--k-gray-1);
+  --van-step-text-color: #999;
+
+  // 按钮
+  --van-button-normal-font-size: 18px;
+
+  // 通知栏
+  --van-notice-bar-background: #ffe3d2;
+  --van-notice-bar-text-color: var(--k-font-primary);
+
+  // 开关
+  --van-switch-size: 22px;
+  --van-switch-width: calc(2em + 4px);
+  --van-switch-height: calc(1em + 4px);
+  // --van-switch-background: #fff;
+
+  // 折叠面板
+  --van-collapse-item-content-text-color: #999;
+
+  // 头部高度
+  --van-nav-bar-height: 44px;
+  --van-nav-bar-arrow-size: 22px;
+}

+ 1 - 0
src/styles/index.less

@@ -1,5 +1,6 @@
 @import url('./iconfont/iconfont.css');
 @import url('./font/index.less');
+@import url('./component-ui.less');
 
 :root {
   // Color Palette

+ 143 - 3
src/teacher/statistics/practice-statistics-detail/index.module.less

@@ -37,7 +37,7 @@
     color: #131415;
     line-height: 20px;
     &.active {
-      color: #2DC7AA;
+      color: #2dc7aa;
     }
     span {
       padding-left: 49px;
@@ -190,8 +190,8 @@
     }
     &:nth-child(5n),
     &:nth-child(3n) {
-      background: #F8F1E9;
-      color: #DF8010;
+      background: #f8f1e9;
+      color: #df8010;
     }
     &:nth-child(2n),
     &:nth-child(4n) {
@@ -244,3 +244,143 @@
     }
   }
 }
+
+.popupContainer {
+  // max-height: 504px;
+  // overflow-x: hidden;
+  // overflow-y: auto;
+  .popupTitle {
+    position: sticky;
+    z-index: 1;
+    top: 0;
+    text-align: center;
+    font-weight: 600;
+    font-size: 18px;
+    color: #333333;
+    line-height: 24px;
+    padding: 18px 0 12px;
+  }
+
+  .popupSearchList {
+    min-height: 30vh;
+    max-height: 50vh;
+    overflow: hidden auto;
+  }
+
+  .popupSection {
+    padding: 0 16px 18px;
+    .title {
+      display: flex;
+      justify-content: space-between;
+      padding-bottom: 10px;
+      span {
+        display: flex;
+        align-items: center;
+        font-weight: 600;
+        font-size: 15px;
+        color: #333333;
+        line-height: 18px;
+        &::before {
+          content: '';
+          display: inline-block;
+          width: 3px;
+          height: 12px;
+          background: linear-gradient(180deg, #59e5d4 0%, #2dc7aa 100%);
+          border-radius: 2px;
+          margin-right: 4px;
+        }
+      }
+    }
+
+    .timeCount {
+      display: flex;
+      align-items: center;
+
+      p {
+        margin-left: 10px;
+        flex: 1;
+        background: #f8f8f8;
+        border: 1px solid #f8f8f8;
+        border-radius: 4px;
+        font-size: 13px;
+        color: #999999;
+        line-height: 18px;
+        text-align: center;
+        padding: 6px 0;
+        &:first-child {
+          margin-left: 0;
+        }
+
+        &.active {
+          background: #e9fff8;
+          border-radius: 4px;
+          border: 1px solid #2dc7aa;
+          color: #2dc7aa;
+        }
+      }
+    }
+
+    .timeSubject {
+      flex-wrap: wrap;
+      margin-left: -5px;
+      margin-right: -5px;
+      p {
+        width: calc(33.333% - 10px);
+        padding: 6px 3px;
+        margin: 0 5px;
+        flex: none;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        margin-bottom: 9px;
+        box-sizing: border-box;
+        &:first-child {
+          margin-left: 5px;
+        }
+
+      }
+    }
+
+    .timeRang {
+      margin-top: 10px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      .timeInput {
+        width: 159px;
+        line-height: 32px;
+        text-align: center;
+        background: #f8f8f8;
+        border-radius: 4px;
+        font-size: 13px;
+        color: #999999;
+        cursor: pointer;
+      }
+
+      .timeUnit {
+        width: 12px;
+        height: 1px;
+        background: #d0d0d0;
+      }
+    }
+  }
+
+  .popupBottom {
+    position: sticky;
+    z-index: 1;
+    bottom: 0;
+    border-top: 1px solid #f2f2f2;
+    padding: 20px 13px 30px;
+    display: flex;
+    align-items: center;
+    :global {
+      .van-button {
+        font-size: 16px;
+      }
+      .van-button + .van-button {
+        margin-left: 15px;
+      }
+    }
+  }
+}

+ 99 - 9
src/teacher/statistics/practice-statistics-detail/index.tsx

@@ -1,19 +1,28 @@
-import { defineComponent, ref } from 'vue'
+import { defineComponent, reactive, ref } from 'vue'
 import styles from './index.module.less'
 import iconArrow1 from '../images/icon-arrow1.png'
 import iconArrow11 from '../images/icon-arrow1-1.png'
 import icon1 from '../images/icon-1.png'
 import icon2 from '../images/icon-2.png'
 import iconDownload from '../images/icon-download.png'
-import { Popup } from 'vant'
+import { Button, DatetimePicker, Popup } from 'vant'
 import Echats from './echats'
 import ColHeader from '@/components/col-header'
 import TheSticky from '@/components/the-sticky'
+import { formatterDatePicker } from '@/helpers/utils'
+import dayjs from 'dayjs'
 
 export default defineComponent({
   name: 'PracticeDetail',
   setup() {
-    const searchStatus = ref(true)
+    const searchStatus = ref(false)
+    const forms = reactive({
+      startTimeStatus: false,
+      endTimeMinDate: new Date(),
+      endTimeStatus: false,
+      startTime: new Date(),
+      endTime: null as any,
+    })
     return () => (
       <div class={styles.practiceDetail}>
         <TheSticky position="top">
@@ -131,19 +140,100 @@ export default defineComponent({
           </div>
         </div>
 
-        <Popup v-model:show={searchStatus.value} closeable round>
-          <div class={styles.popupSection}>
+        <Popup v-model:show={searchStatus.value} closeable round position="bottom">
+          <div class={styles.popupContainer}>
             <div class={styles.popupTitle}>筛选</div>
 
-            <div class={styles.popupSection}>
-              <div class={styles.title}>
-                <span>学员练习时长</span>
+            <div class={styles.popupSearchList}>
+              <div class={styles.popupSection}>
+                <div class={styles.title}>
+                  <span>学员练习时长</span>
+                </div>
+
+                <div class={styles.timeCount}>
+                  <p class={styles.active}>本月</p>
+                  <p>近三个月</p>
+                  <p>近半年</p>
+                  <p>近一年</p>
+                </div>
+
+                <div class={styles.timeRang}>
+                  <p class={styles.timeInput} onClick={() => forms.startTimeStatus = true}>起始时间</p>
+                  <p class={styles.timeUnit}></p>
+                  <p class={styles.timeInput} onClick={() => forms.endTimeStatus = true}>终止时间</p>
+                </div>
+              </div>
+
+              <div class={styles.popupSection}>
+                <div class={styles.title}>
+                  <span>声部</span>
+                </div>
+
+                <div class={[styles.timeCount, styles.timeSubject]}>
+                  <p class={styles.active}>本月</p>
+                  <p>近三个月</p>
+                  <p>近半年</p>
+                  <p>近一年近一年近一年</p>
+                  <p>近一年</p>
+                  <p>近一年近一年</p>
+                  <p>近一年</p>
+                  <p>近一年</p>
+                  <p>近一年近一年近一年</p>
+                  <p>近一年</p>
+                  <p>近一年近一年</p>
+                  <p>近一年</p>
+                  <p>近一年</p>
+                </div>
               </div>
+            </div>
 
-              <div class={styles.timeCount}></div>
+            <div class={styles.popupBottom}>
+              <Button round block type="default">重置</Button>
+              <Button round block type='primary'>确定</Button>
             </div>
           </div>
         </Popup>
+
+        {/* 开始日期 */}
+        <Popup
+          v-model:show={forms.startTimeStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}
+        >
+          <DatetimePicker
+            v-model={forms.startTime}
+            type="date"
+            formatter={formatterDatePicker}
+            onCancel={() => (forms.startTimeStatus = false)}
+            onConfirm={(val: any) => {
+              console.log(val, 'val')
+              forms.startTime = val
+              forms.startTimeStatus = false
+              forms.endTime = null as any
+              forms.endTimeMinDate = dayjs(val || new Date()).toDate()
+            }}
+          />
+        </Popup>
+        {/* 结束日期 */}
+        <Popup
+          v-model:show={forms.endTimeStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}
+        >
+          <DatetimePicker
+            v-model={forms.endTime}
+            type="date"
+            minDate={forms.endTimeMinDate}
+            formatter={formatterDatePicker}
+            onCancel={() => (forms.endTimeStatus = false)}
+            onConfirm={(val: any) => {
+              forms.endTime = val
+              forms.endTimeStatus = false
+            }}
+          />
+        </Popup>
       </div>
     )
   }