Преглед на файлове

输入框和树形下拉框封装

黄琪勇 преди 1 година
родител
ревизия
9ec1c79718

+ 3 - 38
src/assets/elementTheme.scss

@@ -15,55 +15,20 @@
 // :root {}
 /* 暗黑模式 */
 //html.dark {}
+
 //表头加颜色
 .el-table .el-table__header thead th {
    background-color: var(--el-bg-color-page);
 }
 
+/* 空元素全局样式 */
 .el-empty .el-empty__description p {
    font-weight: 400;
    font-size: 22px;
    color: #aaaaaa;
 }
 
-.el-cascader__dropdown {
-   .el-cascader-menu__list {
-      padding: 12px 0;
-   }
-   .el-cascader-node:not(.is-disabled):hover,
-   .el-cascader-node:not(.is-disabled):focus {
-      background-color: transparent;
-   }
-   .el-cascader-menu:last-child .el-cascader-node {
-      padding: 0 12px;
-      line-height: 40px;
-      height: 40px;
-   }
-   .el-cascader-node__prefix {
-      display: none;
-   }
-   .is-active .el-cascader-node__label {
-      color: #994d1c;
-   }
-   .el-cascader-node__label {
-      font-size: 16px;
-      border-radius: 8px;
-      &:hover {
-         color: #994d1c;
-         background: #fff3d7;
-      }
-   }
-}
-
-.el-popper.is-light {
-   box-shadow: rgba(0, 0, 0, 0.08) 0px 2px 17px 0px;
-   border-radius: 12px;
-   border: none;
-   .el-popper__arrow {
-      display: none;
-   }
-}
-
+/*  滚动条全局样式 */
 .el-scrollbar__thumb {
    opacity: 1;
    background-color: #ececec;

+ 75 - 30
src/components/dictionary/dictionary.vue

@@ -5,36 +5,31 @@
 -->
 <template>
    <el-cascader
-      class="dictionary"
-      v-model="myValue"
-      :disabled="props.disabled"
-      :size="props.size"
+      class="h_dictionary"
       :show-all-levels="false"
-      :options="props.options"
       :props="propsOpt"
       :clearable="props.clearable"
-      :placeholder="placeholder"
-      :popperClass="popperClass"
+      :popperClass="popperClass + ' dictionaryPopper'"
+      v-bind="$attrs"
    />
 </template>
 
 <script setup lang="ts">
-import { CascaderOption, CascaderProps, CascaderValue } from "element-plus"
-import { computed } from "vue"
+import { baseSize } from "@/libs/rem"
+import { CascaderProps } from "element-plus"
+import { computed, useAttrs } from "vue"
 import dictionaryCacheStore from "@/store/modules/dictionaryCache"
 
+const attrs = useAttrs()
 const dictionaryCacheStoreHook = dictionaryCacheStore()
 const props = withDefaults(
    defineProps<{
-      modelValue?: CascaderValue
-      options?: CascaderOption[]
       clearable?: boolean
       propsOpt?: Omit<CascaderProps, "lazyLoad" | "emitPath" | "lazy">
       dictionaryKey?: string
-      disabled?: boolean
-      size?: "default" | "small" | "large"
-      placeholder?: string
       popperClass?: string
+      width?: number
+      height?: number
    }>(),
    {
       clearable: true,
@@ -43,13 +38,8 @@ const props = withDefaults(
       }
    }
 )
-const emits = defineEmits<{
-   (e: "update:modelValue", value?: CascaderValue): void
-   (e: "change", value?: CascaderValue): void
-}>()
-
 const propsOpt: CascaderProps = {
-   emitPath: Array.isArray(props.modelValue) ? true : false, //当可能为多级字典时候 emitPath为true 值为数组模式
+   emitPath: Array.isArray(attrs.modelValue) ? true : false, //当可能为多级字典时候 emitPath为true 值为数组模式
    lazy: props.dictionaryKey ? true : false,
    leaf: "haveChild",
    async lazyLoad({ level, data }, resolve) {
@@ -60,19 +50,74 @@ const propsOpt: CascaderProps = {
 //赋值
 Object.assign(propsOpt, props.propsOpt)
 
-const myValue = computed({
-   get() {
-      return props.modelValue
-   },
-   set(value) {
-      emits("update:modelValue", value)
-      emits("change", value)
-   }
+const _h_width = computed(() => {
+   return props.width ? (props.width / baseSize).toFixed(5) + "rem" : "100%"
+})
+const _h_height = computed(() => {
+   return (((props.height || 32) - 4) / baseSize).toFixed(5) + "rem"
 })
 </script>
 
 <style lang="scss">
-.dictionary {
-   width: 100%;
+.h_dictionary {
+   flex-shrink: 0;
+   width: v-bind(_h_width);
+   .el-input {
+      --el-input-text-color: #333;
+      font-size: 16px;
+   }
+   .el-input__suffix {
+      font-size: 14px;
+   }
+   .el-input__wrapper {
+      border-radius: 20px;
+      box-shadow: none;
+      padding: 1px 26px 1px 16px;
+      border: 1px solid transparent;
+      &.is-focus {
+         border-color: #ff8057 !important;
+         box-shadow: 0px 0px 4px 0px rgba(255, 155, 109) !important;
+      }
+      .el-input__inner {
+         --el-input-inner-height: v-bind(_h_height);
+      }
+   }
+}
+
+.el-cascader__dropdown.el-popper.is-light.dictionaryPopper {
+   box-shadow: rgba(0, 0, 0, 0.08) 0px 2px 17px 0px;
+   border-radius: 12px;
+   border: none;
+   .el-cascader-menu__list {
+      padding: 12px 0;
+   }
+   .el-cascader-node:not(.is-disabled):hover,
+   .el-cascader-node:not(.is-disabled):focus {
+      background-color: transparent;
+   }
+   .el-cascader-menu {
+      &:last-child .el-cascader-node {
+         padding: 0 12px;
+         line-height: 40px;
+         height: 40px;
+      }
+   }
+   .el-cascader-node__prefix {
+      display: none;
+   }
+   .is-active .el-cascader-node__label {
+      color: #994d1c;
+   }
+   .el-cascader-node__label {
+      font-size: 16px;
+      border-radius: 8px;
+      &:hover {
+         color: #994d1c;
+         background: #fff3d7;
+      }
+   }
+   .el-popper__arrow {
+      display: none;
+   }
 }
 </style>

+ 2 - 0
src/components/myInput/index.ts

@@ -0,0 +1,2 @@
+import myInput from "./myInput.vue"
+export default myInput

+ 102 - 0
src/components/myInput/myInput.vue

@@ -0,0 +1,102 @@
+<!--
+* @FileDescription: input
+* @Author: 黄琪勇
+* @Date:2024-03-28 17:22:38
+-->
+<template>
+   <el-input class="h_myInput" v-bind="$attrs" @focus="handleInputFocus" @blur="handleInputBlur" :class="{ isInputFocus: isInputFocus }">
+      <template #prepend>
+         <slot v-if="$slots.prepend" name="prepend"></slot>
+         <img v-else class="imgSs" src="@/img/layout/ss.png" />
+      </template>
+      <template #append>
+         <slot v-if="$slots.append" name="append"></slot>
+         <div v-else class="btnSelect" @click="handleQuery">搜索</div>
+      </template>
+   </el-input>
+</template>
+
+<script setup lang="ts">
+import { computed, ref } from "vue"
+import { baseSize } from "@/libs/rem"
+
+const props = defineProps<{
+   width?: number
+   height?: number
+}>()
+const emits = defineEmits<{
+   (e: "handleQuery"): void
+}>()
+
+const _h_width = computed(() => {
+   return props.width ? (props.width / baseSize).toFixed(5) + "rem" : "100%"
+})
+const _h_height = computed(() => {
+   return ((props.height || 32) / baseSize).toFixed(5) + "rem"
+})
+
+// 选中样式
+const isInputFocus = ref(false)
+function handleInputFocus() {
+   isInputFocus.value = true
+}
+function handleInputBlur() {
+   isInputFocus.value = false
+}
+
+function handleQuery() {
+   emits("handleQuery")
+}
+</script>
+
+<style lang="scss">
+.h_myInput {
+   &.el-input {
+      flex-shrink: 0;
+      width: v-bind(_h_width);
+      height: v-bind(_h_height);
+      --el-input-text-color: #333;
+      font-size: 16px;
+      border: 1px solid transparent;
+      background: #fff;
+      border-radius: 21px;
+      & .isInputFocus {
+         border-color: #ff8057 !important;
+         box-shadow: 0px 0px 4px 0px rgba(255, 155, 109);
+      }
+   }
+   .el-input-group__prepend {
+      background-color: transparent;
+      box-shadow: none;
+      padding: 0 0 0 15px;
+   }
+   .el-input-group__append {
+      background-color: transparent;
+      box-shadow: none;
+      padding: 0 4px;
+   }
+   .el-input__wrapper {
+      box-shadow: none;
+      border-radius: 21px;
+   }
+   .imgSs {
+      width: 20px;
+      height: 20px;
+   }
+   .btnSelect {
+      width: 70px;
+      height: 36px;
+      background: linear-gradient(180deg, #ffab71 0%, #ff6e45 100%), #ffad49;
+      border-radius: 21px;
+      font-weight: 500;
+      font-size: 16px;
+      color: #ffffff;
+      line-height: 36px;
+      text-align: center;
+      cursor: pointer;
+      &:hover {
+         opacity: $opacity-hover;
+      }
+   }
+}
+</style>

+ 0 - 0
src/img/cloudTextbooks/ss.png → src/img/layout/ss.png


+ 20 - 101
src/views/cloudTextbooks/cloudTextbooks.vue

@@ -9,31 +9,25 @@
          <div class="headCon">
             <div class="operate">
                <dictionary
-                  class="classTypes"
-                  :popperClass="'classTypeOpt'"
+                  :popper-class="'classTypePopper'"
                   v-model="classType"
+                  :width="150"
+                  :height="40"
                   :options="classTypeOpt"
                   placeholder="课程类型"
                   @change="handleQuery"
                />
-               <el-input
-                  @keyup.enter="handleQuery"
-                  @input="handleInputQuery"
-                  @focus="handleInputFocus"
-                  @blur="handleInputBlur"
+               <myInput
+                  class="queryIpt"
                   v-model="queryStr"
+                  :width="382"
+                  :height="40"
                   placeholder="请输入教材名称"
+                  @keyup.enter="handleQuery"
+                  @input="handleInputQuery"
+                  @handleQuery="handleQuery"
                   clearable
-                  class="iptSelect"
-                  :class="{ isInputFocus: isInputFocus }"
-               >
-                  <template #prepend>
-                     <img class="imgSs" src="@/img/cloudTextbooks/ss.png" />
-                  </template>
-                  <template #append>
-                     <div class="btnSelect" @click="handleQuery">搜索</div>
-                  </template>
-               </el-input>
+               />
             </div>
          </div>
          <div class="cloudTextbooksCon">
@@ -75,6 +69,7 @@ import { useDataList } from "./useData"
 import { debounce } from "@/libs/tools"
 import { getLessonCoursewareSubjectList_gym } from "@/api/cloudTextbooks.api"
 import { httpAjax } from "@/plugin/httpAjax"
+import myInput from "@/components/myInput"
 
 const userStoreHook = userStore()
 const { handleGetList, listData, loading, handleListQuery } = useDataList()
@@ -96,15 +91,6 @@ const classType = ref("")
 const classTypeOpt = shallowRef<{ value: string; label: string }[]>([])
 const queryStr = ref("")
 
-// 选中样式
-const isInputFocus = ref(false)
-function handleInputFocus() {
-   isInputFocus.value = true
-}
-function handleInputBlur() {
-   isInputFocus.value = false
-}
-
 handleGetClassTypeOpt()
 handleGetList()
 
@@ -190,79 +176,8 @@ function handleClick(id: string) {
       flex-direction: row-reverse;
       .operate {
          display: flex;
-         & > :deep(.classTypes) {
-            flex-shrink: 0;
-            width: 150px;
-            .el-input {
-               --el-input-text-color: #333;
-               font-size: 16px;
-            }
-            .el-input__suffix {
-               font-size: 14px;
-            }
-            .el-input__wrapper {
-               border-radius: 20px;
-               box-shadow: none;
-               padding: 1px 26px 1px 16px;
-               border: 1px solid transparent;
-               &.is-focus {
-                  border-color: #ff8057 !important;
-                  box-shadow: 0px 0px 4px 0px rgba(255, 155, 109) !important;
-               }
-               .el-input__inner {
-                  --el-input-inner-height: 40px;
-               }
-            }
-         }
-         .isInputFocus {
-            border-color: #ff8057 !important;
-            box-shadow: 0px 0px 4px 0px rgba(255, 155, 109);
-         }
-         & > :deep(.iptSelect) {
-            border: 1px solid transparent;
+         .queryIpt {
             margin-left: 12px;
-            width: 382px;
-            background: #fff;
-            border-radius: 21px;
-            &.el-input {
-               --el-input-text-color: #333;
-               font-size: 16px;
-            }
-            .el-input-group__prepend {
-               background-color: transparent;
-               box-shadow: none;
-               padding: 0 0 0 15px;
-            }
-            .el-input-group__append {
-               background-color: transparent;
-               box-shadow: none;
-               padding: 0 4px;
-            }
-            .el-input__wrapper {
-               box-shadow: none;
-               .el-input__inner {
-                  --el-input-inner-height: 40px;
-               }
-            }
-            .imgSs {
-               width: 20px;
-               height: 20px;
-            }
-            .btnSelect {
-               width: 70px;
-               height: 36px;
-               background: linear-gradient(180deg, #ffab71 0%, #ff6e45 100%), #ffad49;
-               border-radius: 21px;
-               font-weight: 500;
-               font-size: 16px;
-               color: #ffffff;
-               line-height: 36px;
-               text-align: center;
-               cursor: pointer;
-               &:hover {
-                  opacity: $opacity-hover;
-               }
-            }
          }
       }
    }
@@ -368,8 +283,12 @@ function handleClick(id: string) {
       transform: translate(-50%, -50%);
    }
 }
-:global(.classTypeOpt.el-popper .el-cascader-menu) {
-   width: 150px;
-   min-width: auto;
+</style>
+<style lang="scss">
+.classTypePopper.el-cascader__dropdown.el-popper {
+   .el-cascader-menu {
+      width: 150px;
+      min-width: auto;
+   }
 }
 </style>

+ 12 - 7
src/viewsframe/layout/layout.vue

@@ -6,7 +6,7 @@
 <template>
    <div class="layout">
       <div class="head">
-         <el-dropdown :popper-options="{}" popper-class="headDropdown" class="avatar-con" trigger="click" @visible-change="visibleChange">
+         <el-dropdown popper-class="headDropdown" class="avatar-con" trigger="click" @visible-change="visibleChange">
             <div class="avatar">
                <div class="imgCon"><el-image class="avatarImg" :src="userInfo.avatar || require('@/img/layout/userImg.png')" /></div>
                <div class="name">
@@ -122,12 +122,6 @@ function handleLogout() {
       }
    }
 }
-:global(.headDropdown.el-dropdown__popper.el-popper) {
-   box-shadow: 0px 2px 17px 0px rgba(0, 0, 0, 0.08);
-   background: #ffffff;
-   border-radius: 16px;
-   inset: 84px 54px auto auto !important;
-}
 .dropdown {
    width: 300px;
    padding: 20px;
@@ -192,3 +186,14 @@ function handleLogout() {
    }
 }
 </style>
+<style lang="scss">
+.headDropdown.el-dropdown__popper.el-popper {
+   box-shadow: 0px 2px 17px 0px rgba(0, 0, 0, 0.08);
+   background: #ffffff;
+   border-radius: 16px;
+   inset: 84px 54px auto auto !important;
+   .el-popper__arrow {
+      display: none;
+   }
+}
+</style>