| | |
| | | <template> |
| | | <div style="padding: 0 15px;" @click="toggleClick"> |
| | | <svg :class="{'is-active':isActive}" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64"> |
| | | <path |
| | | d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" |
| | | /> |
| | | </svg> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineProps({ |
| | | isActive: { |
| | |
| | | emit('toggleClick'); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div style="padding: 0 15px;" @click="toggleClick"> |
| | | <svg :class="{'is-active':isActive}" class="hamburger" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="64" height="64"> |
| | | <path |
| | | d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" |
| | | /> |
| | | </svg> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .hamburger { |
| | |
| | | <template> |
| | | <div :class="{ 'show': show }" class="header-search"> |
| | | <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> |
| | | <el-select |
| | | ref="headerSearchSelectRef" |
| | | v-model="search" |
| | | :remote-method="querySearch" |
| | | filterable |
| | | default-first-option |
| | | remote |
| | | placeholder="Search" |
| | | class="header-search-select" |
| | | @change="change" |
| | | > |
| | | <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> |
| | | </el-select> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import Fuse from 'fuse.js' |
| | | import { getNormalPath } from '@/utils/ruoyi' |
| | |
| | | initFuse(list) |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <div :class="{ 'show': show }" class="header-search"> |
| | | <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> |
| | | <el-select |
| | | ref="headerSearchSelectRef" |
| | | v-model="search" |
| | | :remote-method="querySearch" |
| | | filterable |
| | | default-first-option |
| | | remote |
| | | placeholder="Search" |
| | | class="header-search-select" |
| | | @change="change" |
| | | > |
| | | <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> |
| | | </el-select> |
| | | </div> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | .header-search { |
| | |
| | | <template> |
| | | <div class="relative" :style="{ width: width }"> |
| | | <el-input v-model="modelValue" readonly @click="visible = !visible" placeholder="点击选择图标"> |
| | | <template #prepend> |
| | | <svg-icon :icon-class="modelValue as string"></svg-icon> |
| | | </template> |
| | | </el-input> |
| | | |
| | | <el-popover shadow="none" :visible="visible" placement="bottom-end" trigger="click" :width="450"> |
| | | <template #reference> |
| | | <div @click="visible = !visible" class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]"> |
| | | <i-ep-caret-top v-show="visible"></i-ep-caret-top> |
| | | <i-ep-caret-bottom v-show="!visible"></i-ep-caret-bottom> |
| | | </div> |
| | | </template> |
| | | |
| | | <el-input class="p-2" v-model="filterValue" placeholder="搜索图标" clearable @input="filterIcons" /> |
| | | |
| | | <el-scrollbar height="w-[200px]"> |
| | | <ul class="icon-list"> |
| | | <el-tooltip v-for="(iconName, index) in iconNames" :key="index" :content="iconName" placement="bottom" effect="light"> |
| | | <li class="icon-item" @click="selectedIcon(iconName)"> |
| | | <svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" /> |
| | | </li> |
| | | </el-tooltip> |
| | | </ul> |
| | | </el-scrollbar> |
| | | </el-popover> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import icons from '@/components/IconSelect/requireIcons'; |
| | | |
| | |
| | | visible.value = false; |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="relative" :style="{ width: width }"> |
| | | <el-input v-model="modelValue" readonly @click="visible = !visible" placeholder="点击选择图标"> |
| | | <template #prepend> |
| | | <svg-icon :icon-class="modelValue as string"></svg-icon> |
| | | </template> |
| | | </el-input> |
| | | |
| | | <el-popover shadow="none" :visible="visible" placement="bottom-end" trigger="click" :width="450"> |
| | | <template #reference> |
| | | <div @click="visible = !visible" class="cursor-pointer text-[#999] absolute right-[10px] top-0 height-[32px] leading-[32px]"> |
| | | <i-ep-caret-top v-show="visible"></i-ep-caret-top> |
| | | <i-ep-caret-bottom v-show="!visible"></i-ep-caret-bottom> |
| | | </div> |
| | | </template> |
| | | |
| | | <el-input class="p-2" v-model="filterValue" placeholder="搜索图标" clearable @input="filterIcons" /> |
| | | |
| | | <el-scrollbar height="w-[200px]"> |
| | | <ul class="icon-list"> |
| | | <el-tooltip v-for="(iconName, index) in iconNames" :key="index" :content="iconName" placement="bottom" effect="light"> |
| | | <li class="icon-item" @click="selectedIcon(iconName)"> |
| | | <svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" /> |
| | | </li> |
| | | </el-tooltip> |
| | | </ul> |
| | | </el-scrollbar> |
| | | </el-popover> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .el-divider--horizontal { |
| | |
| | | <template> |
| | | <el-image :src="`${realSrc}`" fit="cover" :style="`width:${realWidth};height:${realHeight};`" :preview-src-list="realSrcList" preview-teleported> |
| | | <template #error> |
| | | <div class="image-slot"> |
| | | <el-icon><picture-filled /></el-icon> |
| | | </div> |
| | | </template> |
| | | </el-image> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | const props = defineProps({ |
| | | src: { |
| | |
| | | typeof props.height == "string" ? props.height : `${props.height}px` |
| | | ); |
| | | </script> |
| | | |
| | | <template> |
| | | <el-image :src="`${realSrc}`" fit="cover" :style="`width:${realWidth};height:${realHeight};`" :preview-src-list="realSrcList" preview-teleported> |
| | | <template #error> |
| | | <div class="image-slot"> |
| | | <el-icon><picture-filled /></el-icon> |
| | | </div> |
| | | </template> |
| | | </el-image> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | .el-image { |
| | |
| | | <script setup lang="ts"> |
| | | import useAppStore from "@/store/modules/app"; |
| | | |
| | | const appStore = useAppStore(); |
| | | const size = computed(() => appStore.size); |
| | | |
| | | const sizeOptions = ref([ |
| | | { label: "较大", value: "large" }, |
| | | { label: "默认", value: "default" }, |
| | | { label: "稍小", value: "small" }, |
| | | ]); |
| | | |
| | | const handleSetSize = (size: string) => { |
| | | appStore.setSize(size); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div> |
| | | <el-dropdown trigger="click" @command="handleSetSize"> |
| | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import useAppStore from "@/store/modules/app"; |
| | | |
| | | const appStore = useAppStore(); |
| | | const size = computed(() => appStore.size); |
| | | |
| | | const sizeOptions = ref([ |
| | | { label: "较大", value: "large" }, |
| | | { label: "默认", value: "default" }, |
| | | { label: "稍小", value: "small" }, |
| | | ]); |
| | | |
| | | const handleSetSize = (size: string) => { |
| | | appStore.setSize(size); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .size-icon--style { |
| | | font-size: 18px; |
| | |
| | | <template> |
| | | <svg :class="svgClass" aria-hidden="true"> |
| | | <use :xlink:href="iconName" :fill="color" /> |
| | | </svg> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | const props = defineProps({ |
| | | iconClass: { |
| | |
| | | return 'svg-icon' |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <svg :class="svgClass" aria-hidden="true"> |
| | | <use :xlink:href="iconName" :fill="color" /> |
| | | </svg> |
| | | </template> |
| | | |
| | | <style scope lang="scss"> |
| | | .sub-el-icon, |
| | |
| | | <template> |
| | | <div class="el-tree-select"> |
| | | <el-select |
| | | style="width: 100%" |
| | | v-model="valueId" |
| | | ref="treeSelect" |
| | | :filterable="true" |
| | | :clearable="true" |
| | | @clear="clearHandle" |
| | | :filter-method="selectFilterData" |
| | | :placeholder="placeholder" |
| | | > |
| | | <el-option :value="valueId" :label="valueTitle"> |
| | | <el-tree |
| | | id="tree-option" |
| | | ref="selectTree" |
| | | :accordion="accordion" |
| | | :data="options" |
| | | :props="objMap" |
| | | :node-key="objMap.value" |
| | | :expand-on-click-node="false" |
| | | :default-expanded-keys="defaultExpandedKey" |
| | | :filter-node-method="filterNode" |
| | | @node-click="handleNodeClick" |
| | | ></el-tree> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { ElTreeSelect } from 'element-plus' |
| | | |
| | |
| | | color: $--color-primary; |
| | | } |
| | | </style> |
| | | |
| | | <template> |
| | | <div class="el-tree-select"> |
| | | <el-select |
| | | style="width: 100%" |
| | | v-model="valueId" |
| | | ref="treeSelect" |
| | | :filterable="true" |
| | | :clearable="true" |
| | | @clear="clearHandle" |
| | | :filter-method="selectFilterData" |
| | | :placeholder="placeholder" |
| | | > |
| | | <el-option :value="valueId" :label="valueTitle"> |
| | | <el-tree |
| | | id="tree-option" |
| | | ref="selectTree" |
| | | :accordion="accordion" |
| | | :data="options" |
| | | :props="objMap" |
| | | :node-key="objMap.value" |
| | | :expand-on-click-node="false" |
| | | :default-expanded-keys="defaultExpandedKey" |
| | | :filter-node-method="filterNode" |
| | | @node-click="handleNodeClick" |
| | | ></el-tree> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | | </template> |
| | |
| | | <template> |
| | | <div v-loading="loading" :style="'height:' + height"> |
| | | <iframe :src="url" frameborder="no" style="width: 100%; height: 100%" scrolling="auto" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | const props = defineProps({ |
| | | src: { |
| | |
| | | }; |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <div v-loading="loading" :style="'height:' + height"> |
| | | <iframe :src="url" frameborder="no" style="width: 100%; height: 100%" scrolling="auto" /> |
| | | </div> |
| | | </template> |
| | |
| | | <script setup lang="ts"> |
| | | import InnerLink from "../InnerLink/index.vue"; |
| | | import useTagsViewStore from '@/store/modules/tagsView'; |
| | | |
| | | const route = useRoute(); |
| | | const tagsViewStore = useTagsViewStore() |
| | | </script> |
| | | |
| | | <template> |
| | | <transition-group name="fade-transform" mode="out-in"> |
| | | <inner-link |
| | |
| | | ></inner-link> |
| | | </transition-group> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import InnerLink from "../InnerLink/index.vue"; |
| | | import useTagsViewStore from '@/store/modules/tagsView'; |
| | | |
| | | const route = useRoute(); |
| | | const tagsViewStore = useTagsViewStore() |
| | | </script> |
| | |
| | | <template> |
| | | <el-drawer v-model="showSettings" :withHeader="false" direction="rtl" size="300px" close-on-click-modal> |
| | | <div class="setting-drawer-title"> |
| | | <h3 class="drawer-title">主题风格设置</h3> |
| | | </div> |
| | | <div class="setting-drawer-block-checbox"> |
| | | <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')"> |
| | | <img src="@/assets/images/dark.svg" alt="dark" /> |
| | | <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> |
| | | <i aria-label="图标: check" class="anticon anticon-check"> |
| | | <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class> |
| | | <path |
| | | d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" |
| | | /> |
| | | </svg> |
| | | </i> |
| | | </div> |
| | | </div> |
| | | <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')"> |
| | | <img src="@/assets/images/light.svg" alt="light" /> |
| | | <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> |
| | | <i aria-label="图标: check" class="anticon anticon-check"> |
| | | <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class> |
| | | <path |
| | | d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" |
| | | /> |
| | | </svg> |
| | | </i> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="drawer-item"> |
| | | <span>主题颜色</span> |
| | | <span class="comp-style"> |
| | | <el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" /> |
| | | </span> |
| | | </div> |
| | | <el-divider /> |
| | | |
| | | <h3 class="drawer-title">系统布局配置</h3> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>开启 TopNav</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="topNav" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>开启 Tags-Views</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="tagsView" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>固定 Header</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="fixedHeader" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>显示 Logo</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="sidebarLogo" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>动态标题</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="dynamicTitle" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <el-divider /> |
| | | |
| | | <el-button type="primary" plain icon="DocumentAdd" @click="saveSetting">保存配置</el-button> |
| | | <el-button plain icon="Refresh" @click="resetSetting">重置配置</el-button> |
| | | </el-drawer> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useDynamicTitle } from '@/utils/dynamicTitle' |
| | | import useAppStore from '@/store/modules/app' |
| | |
| | | openSetting, |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <el-drawer v-model="showSettings" :withHeader="false" direction="rtl" size="300px" close-on-click-modal> |
| | | <div class="setting-drawer-title"> |
| | | <h3 class="drawer-title">主题风格设置</h3> |
| | | </div> |
| | | <div class="setting-drawer-block-checbox"> |
| | | <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')"> |
| | | <img src="@/assets/images/dark.svg" alt="dark" /> |
| | | <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> |
| | | <i aria-label="图标: check" class="anticon anticon-check"> |
| | | <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class> |
| | | <path |
| | | d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" |
| | | /> |
| | | </svg> |
| | | </i> |
| | | </div> |
| | | </div> |
| | | <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')"> |
| | | <img src="@/assets/images/light.svg" alt="light" /> |
| | | <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> |
| | | <i aria-label="图标: check" class="anticon anticon-check"> |
| | | <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class> |
| | | <path |
| | | d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" |
| | | /> |
| | | </svg> |
| | | </i> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="drawer-item"> |
| | | <span>主题颜色</span> |
| | | <span class="comp-style"> |
| | | <el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" /> |
| | | </span> |
| | | </div> |
| | | <el-divider /> |
| | | |
| | | <h3 class="drawer-title">系统布局配置</h3> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>开启 TopNav</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="topNav" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>开启 Tags-Views</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="tagsView" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>固定 Header</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="fixedHeader" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>显示 Logo</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="sidebarLogo" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <div class="drawer-item"> |
| | | <span>动态标题</span> |
| | | <span class="comp-style"> |
| | | <el-switch v-model="dynamicTitle" class="drawer-switch" /> |
| | | </span> |
| | | </div> |
| | | |
| | | <el-divider /> |
| | | |
| | | <el-button type="primary" plain icon="DocumentAdd" @click="saveSetting">保存配置</el-button> |
| | | <el-button plain icon="Refresh" @click="resetSetting">重置配置</el-button> |
| | | </el-drawer> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | .setting-drawer-title { |
| | |
| | | <template> |
| | | <component :is="type" v-bind="linkProps()"> |
| | | <slot /> |
| | | </component> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { isExternal } from '@/utils/validate' |
| | | |
| | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <component :is="type" v-bind="linkProps()"> |
| | | <slot /> |
| | | </component> |
| | | </template> |
| | |
| | | <script setup lang="ts"> |
| | | import variables from '@/assets/styles/variables.module.scss' |
| | | import logo from '@/assets/logo/logo.png' |
| | | import useSettingsStore from '@/store/modules/settings' |
| | | import { ComponentInternalInstance } from "vue"; |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | defineProps({ |
| | | collapse: { |
| | | type: Boolean, |
| | | required: true |
| | | } |
| | | }) |
| | | |
| | | const title = ref('RuoYi-Vue-Plus'); |
| | | const settingsStore = useSettingsStore(); |
| | | const sideTheme = computed(() => settingsStore.sideTheme); |
| | | </script> |
| | | |
| | | <template> |
| | | <div |
| | | class="sidebar-logo-container" |
| | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import variables from '@/assets/styles/variables.module.scss' |
| | | import logo from '@/assets/logo/logo.png' |
| | | import useSettingsStore from '@/store/modules/settings' |
| | | import { ComponentInternalInstance } from "vue"; |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | defineProps({ |
| | | collapse: { |
| | | type: Boolean, |
| | | required: true |
| | | } |
| | | }) |
| | | |
| | | const title = ref('RuoYi-Vue-Plus'); |
| | | const settingsStore = useSettingsStore(); |
| | | const sideTheme = computed(() => settingsStore.sideTheme); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .sidebarLogoFade-enter-active { |
| | | transition: opacity 1.5s; |
| | |
| | | <template> |
| | | <div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: bgColor }"> |
| | | <logo v-if="showLogo" :collapse="isCollapse" /> |
| | | <el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper"> |
| | | <transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in"> |
| | | <el-menu |
| | | :default-active="activeMenu as string" |
| | | :collapse="isCollapse" |
| | | :background-color="bgColor" |
| | | :text-color="textColor" |
| | | :unique-opened="true" |
| | | :active-text-color="theme" |
| | | :collapse-transition="false" |
| | | mode="vertical" |
| | | > |
| | | <sidebar-item v-for="(route, index) in sidebarRouters" :key="route.path + index" :item="route" :base-path="route.path" /> |
| | | </el-menu> |
| | | </transition> |
| | | </el-scrollbar> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import Logo from './Logo.vue' |
| | | import SidebarItem from './SidebarItem.vue' |
| | |
| | | const bgColor = computed(() => sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground); |
| | | const textColor = computed(() => sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor); |
| | | </script> |
| | | |
| | | <template> |
| | | <div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: bgColor }"> |
| | | <logo v-if="showLogo" :collapse="isCollapse" /> |
| | | <el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper"> |
| | | <transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in"> |
| | | <el-menu |
| | | :default-active="activeMenu as string" |
| | | :collapse="isCollapse" |
| | | :background-color="bgColor" |
| | | :text-color="textColor" |
| | | :unique-opened="true" |
| | | :active-text-color="theme" |
| | | :collapse-transition="false" |
| | | mode="vertical" |
| | | > |
| | | <sidebar-item v-for="(route, index) in sidebarRouters" :key="route.path + index" :item="route" :base-path="route.path" /> |
| | | </el-menu> |
| | | </transition> |
| | | </el-scrollbar> |
| | | </div> |
| | | </template> |
| | |
| | | <template> |
| | | <el-scrollbar ref="scrollContainerRef" :vertical="false" class="scroll-container" @wheel.prevent="handleScroll"> |
| | | <slot /> |
| | | </el-scrollbar> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import useTagsViewStore from '@/store/modules/tagsView' |
| | | import { ElScrollbar } from 'element-plus'; |
| | |
| | | moveToTarget, |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <el-scrollbar ref="scrollContainerRef" :vertical="false" class="scroll-container" @wheel.prevent="handleScroll"> |
| | | <slot /> |
| | | </el-scrollbar> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | .scroll-container { |
| | |
| | | <template> |
| | | <div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }"> |
| | | <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> |
| | | <side-bar v-if="!sidebar.hide" class="sidebar-container" /> |
| | | <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container"> |
| | | <div :class="{ 'fixed-header': fixedHeader }"> |
| | | <navbar ref="navbarRef" @setLayout="setLayout" /> |
| | | <tags-view v-if="needTagsView" /> |
| | | </div> |
| | | <app-main /> |
| | | <settings ref="settingRef" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import SideBar from './components/Sidebar/index.vue' |
| | | import { AppMain, Navbar, Settings, TagsView } from './components' |
| | |
| | | settingRef.value.openSetting(); |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }"> |
| | | <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> |
| | | <side-bar v-if="!sidebar.hide" class="sidebar-container" /> |
| | | <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container"> |
| | | <div :class="{ 'fixed-header': fixedHeader }"> |
| | | <navbar ref="navbarRef" @setLayout="setLayout" /> |
| | | <tags-view v-if="needTagsView" /> |
| | | </div> |
| | | <app-main /> |
| | | <settings ref="settingRef" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "@/assets/styles/mixin.scss"; |
| | |
| | | <script setup name="Cache" lang="ts"> |
| | | import { getCache } from '@/api/monitor/cache'; |
| | | import * as echarts from 'echarts'; |
| | | import { ComponentInternalInstance } from "vue"; |
| | | |
| | | const cache = ref<any>({}); |
| | | const commandstats = ref(); |
| | | const usedmemory = ref(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const getList = async () => { |
| | | proxy?.$modal.loading("正在加载缓存监控数据,请稍候!"); |
| | | const res = await getCache(); |
| | | proxy?.$modal.closeLoading(); |
| | | cache.value = res.data; |
| | | const commandstatsIntance = echarts.init(commandstats.value, "macarons"); |
| | | commandstatsIntance.setOption({ |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b} : {c} ({d}%)" |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "命令", |
| | | type: "pie", |
| | | roseType: "radius", |
| | | radius: [15, 95], |
| | | center: ["50%", "38%"], |
| | | data: res.data.commandStats, |
| | | animationEasing: "cubicInOut", |
| | | animationDuration: 1000 |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const usedmemoryInstance = echarts.init(usedmemory.value, "macarons"); |
| | | usedmemoryInstance.setOption({ |
| | | tooltip: { |
| | | formatter: "{b} <br/>{a} : " + cache.value.info.used_memory_human |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "峰值", |
| | | type: "gauge", |
| | | min: 0, |
| | | max: 1000, |
| | | detail: { |
| | | formatter: cache.value.info.used_memory_human |
| | | }, |
| | | data: [ |
| | | { |
| | | value: parseFloat(cache.value.info.used_memory_human), |
| | | name: "内存消耗" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | </script> |
| | | <template> |
| | | <div class="p-2"> |
| | | <el-row> |
| | |
| | | </el-row> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup name="Cache" lang="ts"> |
| | | import { getCache } from '@/api/monitor/cache'; |
| | | import * as echarts from 'echarts'; |
| | | import { ComponentInternalInstance } from "vue"; |
| | | |
| | | const cache = ref<any>({}); |
| | | const commandstats = ref(); |
| | | const usedmemory = ref(); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const getList = async () => { |
| | | proxy?.$modal.loading("正在加载缓存监控数据,请稍候!"); |
| | | const res = await getCache(); |
| | | proxy?.$modal.closeLoading(); |
| | | cache.value = res.data; |
| | | const commandstatsIntance = echarts.init(commandstats.value, "macarons"); |
| | | commandstatsIntance.setOption({ |
| | | tooltip: { |
| | | trigger: "item", |
| | | formatter: "{a} <br/>{b} : {c} ({d}%)" |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "命令", |
| | | type: "pie", |
| | | roseType: "radius", |
| | | radius: [15, 95], |
| | | center: ["50%", "38%"], |
| | | data: res.data.commandStats, |
| | | animationEasing: "cubicInOut", |
| | | animationDuration: 1000 |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const usedmemoryInstance = echarts.init(usedmemory.value, "macarons"); |
| | | usedmemoryInstance.setOption({ |
| | | tooltip: { |
| | | formatter: "{b} <br/>{a} : " + cache.value.info.used_memory_human |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "峰值", |
| | | type: "gauge", |
| | | min: 0, |
| | | max: 1000, |
| | | detail: { |
| | | formatter: cache.value.info.used_memory_human |
| | | }, |
| | | data: [ |
| | | { |
| | | value: parseFloat(cache.value.info.used_memory_human), |
| | | name: "内存消耗" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }) |
| | | </script> |
| | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="search" v-show="showSearch"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form-item label="参数名称" prop="configName"> |
| | | <el-input v-model="queryParams.configName" placeholder="请输入参数名称" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="参数键名" prop="configKey"> |
| | | <el-input v-model="queryParams.configKey" placeholder="请输入参数键名" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="系统内置" prop="configType"> |
| | | <el-select v-model="queryParams.configType" placeholder="系统内置" clearable> |
| | | <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间" style="width: 308px;"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> |
| | | <el-button icon="Refresh" @click="resetQuery">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </transition> |
| | | <el-card shadow="never"> |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:config:add']">新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:config:edit']"> |
| | | 修改 |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:config:remove']"> |
| | | 删除 |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:config:export']">导出</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Refresh" @click="handleRefreshCache" v-hasPermi="['system:config:remove']">刷新缓存</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="参数主键" align="center" prop="configId" v-if="false" /> |
| | | <el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="参数键值" align="center" prop="configValue" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="系统内置" align="center" prop="configType"> |
| | | <template #default="scope"> |
| | | <dict-tag :options="sys_yes_no" :value="scope.row.configType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| | | <template #default="scope"> |
| | | <span>{{ parseTime(scope.row.createTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="修改" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:config:edit']"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="删除" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:config:remove']"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- 添加或修改参数配置对话框 --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-form ref="configFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="参数名称" prop="configName"> |
| | | <el-input v-model="form.configName" placeholder="请输入参数名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="参数键名" prop="configKey"> |
| | | <el-input v-model="form.configKey" placeholder="请输入参数键名" /> |
| | | </el-form-item> |
| | | <el-form-item label="参数键值" prop="configValue"> |
| | | <el-input v-model="form.configValue" placeholder="请输入参数键值" /> |
| | | </el-form-item> |
| | | <el-form-item label="系统内置" prop="configType"> |
| | | <el-radio-group v-model="form.configType"> |
| | | <el-radio v-for="dict in sys_yes_no" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="cancel">取 消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup name="Config" lang="ts"> |
| | | import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config"; |
| | | import { ConfigForm, ConfigQuery, ConfigVO } from "@/api/system/config/types"; |
| | |
| | | getList(); |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="p-2"> |
| | | <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> |
| | | <div class="search" v-show="showSearch"> |
| | | <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> |
| | | <el-form-item label="参数名称" prop="configName"> |
| | | <el-input v-model="queryParams.configName" placeholder="请输入参数名称" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="参数键名" prop="configKey"> |
| | | <el-input v-model="queryParams.configKey" placeholder="请输入参数键名" clearable style="width: 240px" @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="系统内置" prop="configType"> |
| | | <el-select v-model="queryParams.configType" placeholder="系统内置" clearable> |
| | | <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间" style="width: 308px;"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> |
| | | <el-button icon="Refresh" @click="resetQuery">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </transition> |
| | | <el-card shadow="never"> |
| | | <template #header> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:config:add']">新增</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['system:config:edit']"> |
| | | 修改 |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:config:remove']"> |
| | | 删除 |
| | | </el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:config:export']">导出</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button type="danger" plain icon="Refresh" @click="handleRefreshCache" v-hasPermi="['system:config:remove']">刷新缓存</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | </el-row> |
| | | </template> |
| | | |
| | | <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="参数主键" align="center" prop="configId" v-if="false" /> |
| | | <el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="参数键值" align="center" prop="configValue" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="系统内置" align="center" prop="configType"> |
| | | <template #default="scope"> |
| | | <dict-tag :options="sys_yes_no" :value="scope.row.configType" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="创建时间" align="center" prop="createTime" width="180"> |
| | | <template #default="scope"> |
| | | <span>{{ parseTime(scope.row.createTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-tooltip content="修改" placement="top"> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:config:edit']"></el-button> |
| | | </el-tooltip> |
| | | <el-tooltip content="删除" placement="top"> |
| | | <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:config:remove']"></el-button> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- 添加或修改参数配置对话框 --> |
| | | <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> |
| | | <el-form ref="configFormRef" :model="form" :rules="rules" label-width="80px"> |
| | | <el-form-item label="参数名称" prop="configName"> |
| | | <el-input v-model="form.configName" placeholder="请输入参数名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="参数键名" prop="configKey"> |
| | | <el-input v-model="form.configKey" placeholder="请输入参数键名" /> |
| | | </el-form-item> |
| | | <el-form-item label="参数键值" prop="configValue"> |
| | | <el-input v-model="form.configValue" placeholder="请输入参数键值" /> |
| | | </el-form-item> |
| | | <el-form-item label="系统内置" prop="configType"> |
| | | <el-radio-group v-model="form.configType"> |
| | | <el-radio v-for="dict in sys_yes_no" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确 定</el-button> |
| | | <el-button @click="cancel">取 消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | |
| | | <script setup name="Profile" lang="ts"> |
| | | import userAvatar from "./userAvatar.vue"; |
| | | import userInfo from "./userInfo.vue"; |
| | | import resetPwd from "./resetPwd.vue"; |
| | | import { getUserProfile } from "@/api/system/user"; |
| | | |
| | | const activeTab = ref("userinfo"); |
| | | const state = ref<{ user: any; roleGroup: string; postGroup: string}>({ |
| | | user: {}, |
| | | roleGroup: '', |
| | | postGroup: '' |
| | | }); |
| | | |
| | | const userForm = ref({}); |
| | | |
| | | const getUser = async () => { |
| | | const res = await getUserProfile(); |
| | | state.value.user = res.data.user; |
| | | userForm.value = { ...res.data.user } |
| | | state.value.roleGroup = res.data.roleGroup; |
| | | state.value.postGroup = res.data.postGroup; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getUser(); |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="p-2"> |
| | | <el-row :gutter="20"> |
| | |
| | | </el-row> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup name="Profile" lang="ts"> |
| | | import userAvatar from "./userAvatar.vue"; |
| | | import userInfo from "./userInfo.vue"; |
| | | import resetPwd from "./resetPwd.vue"; |
| | | import { getUserProfile } from "@/api/system/user"; |
| | | |
| | | const activeTab = ref("userinfo"); |
| | | const state = ref<{ user: any; roleGroup: string; postGroup: string}>({ |
| | | user: {}, |
| | | roleGroup: '', |
| | | postGroup: '' |
| | | }); |
| | | |
| | | const userForm = ref({}); |
| | | |
| | | const getUser = async () => { |
| | | const res = await getUserProfile(); |
| | | state.value.user = res.data.user; |
| | | userForm.value = { ...res.data.user } |
| | | state.value.roleGroup = res.data.roleGroup; |
| | | state.value.postGroup = res.data.postGroup; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getUser(); |
| | | }) |
| | | </script> |
| | |
| | | <template> |
| | | <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px"> |
| | | <el-form-item label="旧密码" prop="oldPassword"> |
| | | <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password /> |
| | | </el-form-item> |
| | | <el-form-item label="新密码" prop="newPassword"> |
| | | <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password /> |
| | | </el-form-item> |
| | | <el-form-item label="确认密码" prop="confirmPassword"> |
| | | <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="submit">保存</el-button> |
| | | <el-button type="danger" @click="close">关闭</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { updateUserPwd } from '@/api/system/user'; |
| | | import { ComponentInternalInstance } from 'vue'; |
| | |
| | | proxy?.$tab.closePage(); |
| | | }; |
| | | </script> |
| | | |
| | | <template> |
| | | <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px"> |
| | | <el-form-item label="旧密码" prop="oldPassword"> |
| | | <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password /> |
| | | </el-form-item> |
| | | <el-form-item label="新密码" prop="newPassword"> |
| | | <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password /> |
| | | </el-form-item> |
| | | <el-form-item label="确认密码" prop="confirmPassword"> |
| | | <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="submit">保存</el-button> |
| | | <el-button type="danger" @click="close">关闭</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | |
| | | <template> |
| | | <div class="user-info-head" @click="editCropper()"> |
| | | <img :src="options.img as string" title="点击上传头像" class="img-circle img-lg" /> |
| | | <el-dialog :title="title" v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog"> |
| | | <el-row> |
| | | <el-col :xs="24" :md="12" :style="{ height: '350px' }"> |
| | | <vue-cropper |
| | | ref="cropper" |
| | | :img="options.img" |
| | | :info="true" |
| | | :autoCrop="options.autoCrop" |
| | | :autoCropWidth="options.autoCropWidth" |
| | | :autoCropHeight="options.autoCropHeight" |
| | | :fixedBox="options.fixedBox" |
| | | :outputType="options.outputType" |
| | | @realTime="realTime" |
| | | v-if="visible" |
| | | /> |
| | | </el-col> |
| | | <el-col :xs="24" :md="12" :style="{ height: '350px' }"> |
| | | <div class="avatar-upload-preview"> |
| | | <img :src="options.previews.url" :style="options.previews.img" /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <br /> |
| | | <el-row> |
| | | <el-col :lg="2" :md="2"> |
| | | <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload"> |
| | | <el-button> |
| | | 选择 |
| | | <el-icon class="el-icon--right"><Upload /></el-icon> |
| | | </el-button> |
| | | </el-upload> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 2 }" :md="2"> |
| | | <el-button icon="Plus" @click="changeScale(1)"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 1 }" :md="2"> |
| | | <el-button icon="Minus" @click="changeScale(-1)"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 1 }" :md="2"> |
| | | <el-button icon="RefreshLeft" @click="rotateLeft()"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 1 }" :md="2"> |
| | | <el-button icon="RefreshRight" @click="rotateRight()"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 2, offset: 6 }" :md="2"> |
| | | <el-button type="primary" @click="uploadImg()">提 交</el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import "vue-cropper/dist/index.css"; |
| | | import { VueCropper } from "vue-cropper"; |
| | |
| | | options.visible = false; |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="user-info-head" @click="editCropper()"> |
| | | <img :src="options.img as string" title="点击上传头像" class="img-circle img-lg" /> |
| | | <el-dialog :title="title" v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog"> |
| | | <el-row> |
| | | <el-col :xs="24" :md="12" :style="{ height: '350px' }"> |
| | | <vue-cropper |
| | | ref="cropper" |
| | | :img="options.img" |
| | | :info="true" |
| | | :autoCrop="options.autoCrop" |
| | | :autoCropWidth="options.autoCropWidth" |
| | | :autoCropHeight="options.autoCropHeight" |
| | | :fixedBox="options.fixedBox" |
| | | :outputType="options.outputType" |
| | | @realTime="realTime" |
| | | v-if="visible" |
| | | /> |
| | | </el-col> |
| | | <el-col :xs="24" :md="12" :style="{ height: '350px' }"> |
| | | <div class="avatar-upload-preview"> |
| | | <img :src="options.previews.url" :style="options.previews.img" /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <br /> |
| | | <el-row> |
| | | <el-col :lg="2" :md="2"> |
| | | <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload"> |
| | | <el-button> |
| | | 选择 |
| | | <el-icon class="el-icon--right"><Upload /></el-icon> |
| | | </el-button> |
| | | </el-upload> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 2 }" :md="2"> |
| | | <el-button icon="Plus" @click="changeScale(1)"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 1 }" :md="2"> |
| | | <el-button icon="Minus" @click="changeScale(-1)"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 1 }" :md="2"> |
| | | <el-button icon="RefreshLeft" @click="rotateLeft()"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 1, offset: 1 }" :md="2"> |
| | | <el-button icon="RefreshRight" @click="rotateRight()"></el-button> |
| | | </el-col> |
| | | <el-col :lg="{ span: 2, offset: 6 }" :md="2"> |
| | | <el-button type="primary" @click="uploadImg()">提 交</el-button> |
| | | </el-col> |
| | | </el-row> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | .user-info-head { |
| | |
| | | <template> |
| | | <el-form ref="userRef" :model="userForm" :rules="rules" label-width="80px"> |
| | | <el-form-item label="用户昵称" prop="nickName"> |
| | | <el-input v-model="userForm.nickName" maxlength="30" /> |
| | | </el-form-item> |
| | | <el-form-item label="手机号码" prop="phonenumber"> |
| | | <el-input v-model="userForm.phonenumber" maxlength="11" /> |
| | | </el-form-item> |
| | | <el-form-item label="邮箱" prop="email"> |
| | | <el-input v-model="userForm.email" maxlength="50" /> |
| | | </el-form-item> |
| | | <el-form-item label="性别"> |
| | | <el-radio-group v-model="userForm.sex"> |
| | | <el-radio label="0">男</el-radio> |
| | | <el-radio label="1">女</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="submit">保存</el-button> |
| | | <el-button type="danger" @click="close">关闭</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { updateUserProfile } from "@/api/system/user"; |
| | | import { FormRules } from "element-plus"; |
| | |
| | | proxy?.$tab.closePage(); |
| | | }; |
| | | </script> |
| | | |
| | | <template> |
| | | <el-form ref="userRef" :model="userForm" :rules="rules" label-width="80px"> |
| | | <el-form-item label="用户昵称" prop="nickName"> |
| | | <el-input v-model="userForm.nickName" maxlength="30" /> |
| | | </el-form-item> |
| | | <el-form-item label="手机号码" prop="phonenumber"> |
| | | <el-input v-model="userForm.phonenumber" maxlength="11" /> |
| | | </el-form-item> |
| | | <el-form-item label="邮箱" prop="email"> |
| | | <el-input v-model="userForm.email" maxlength="50" /> |
| | | </el-form-item> |
| | | <el-form-item label="性别"> |
| | | <el-radio-group v-model="userForm.sex"> |
| | | <el-radio label="0">男</el-radio> |
| | | <el-radio label="1">女</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="submit">保存</el-button> |
| | | <el-button type="danger" @click="close">关闭</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </template> |
| | |
| | | <script setup lang="ts"> |
| | | import { PropType } from 'vue'; |
| | | |
| | | const prop = defineProps({ |
| | | info: { |
| | | type: Object as PropType<any>, |
| | | default: () => { |
| | | return {}; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | const infoForm = computed(() => prop.info) |
| | | |
| | | // 表单校验 |
| | | const rules = ref({ |
| | | tableName: [{ required: true, message: "请输入表名称", trigger: "blur" }], |
| | | tableComment: [{ required: true, message: "请输入表描述", trigger: "blur" }], |
| | | className: [{ required: true, message: "请输入实体类名称", trigger: "blur" }], |
| | | functionAuthor: [{ required: true, message: "请输入作者", trigger: "blur" }] |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <el-form ref="basicInfoForm" :model="infoForm" :rules="rules" label-width="150px"> |
| | | <el-row> |
| | |
| | | </el-row> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { PropType } from 'vue'; |
| | | |
| | | const prop = defineProps({ |
| | | info: { |
| | | type: Object as PropType<any>, |
| | | default: () => { |
| | | return {}; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | const infoForm = computed(() => prop.info) |
| | | |
| | | // 表单校验 |
| | | const rules = ref({ |
| | | tableName: [{ required: true, message: "请输入表名称", trigger: "blur" }], |
| | | tableComment: [{ required: true, message: "请输入表描述", trigger: "blur" }], |
| | | className: [{ required: true, message: "请输入实体类名称", trigger: "blur" }], |
| | | functionAuthor: [{ required: true, message: "请输入作者", trigger: "blur" }] |
| | | }); |
| | | </script> |
| | |
| | | <script setup lang="ts"> |
| | | import { listMenu } from '@/api/system/menu'; |
| | | import { ComponentInternalInstance, PropType } from 'vue'; |
| | | |
| | | interface MenuOptionsType { |
| | | menuId: number; |
| | | menuName: string; |
| | | children: MenuOptionsType[] | undefined; |
| | | } |
| | | |
| | | const subColumns = ref<any>([]); |
| | | const menuOptions = ref<Array<MenuOptionsType>>([]); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object as PropType<any>, |
| | | default: null |
| | | }, |
| | | tables: { |
| | | type: Array as PropType<any[]>, |
| | | default: null |
| | | } |
| | | }); |
| | | |
| | | const infoForm = computed(() => props.info); |
| | | |
| | | const table = computed(() => props.tables); |
| | | |
| | | // 表单校验 |
| | | const rules = ref({ |
| | | tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }], |
| | | packageName: [{ required: true, message: "请输入生成包路径", trigger: "blur" }], |
| | | moduleName: [{ required: true, message: "请输入生成模块名", trigger: "blur" }], |
| | | businessName: [{ required: true, message: "请输入生成业务名", trigger: "blur" }], |
| | | functionName: [{ required: true, message: "请输入生成功能名", trigger: "blur" }] |
| | | }); |
| | | const subSelectChange = () => { |
| | | infoForm.value.subTableFkName = ""; |
| | | } |
| | | const tplSelectChange = (value: string) => { |
| | | if (value !== "sub") { |
| | | infoForm.value.subTableName = ""; |
| | | infoForm.value.subTableFkName = ""; |
| | | } |
| | | } |
| | | const setSubTableColumns = (value: string) => { |
| | | table.value.forEach(item => { |
| | | const name = item.tableName; |
| | | if (value === name) { |
| | | subColumns.value = item.columns; |
| | | return; |
| | | } |
| | | }) |
| | | } |
| | | /** 查询菜单下拉树结构 */ |
| | | const getMenuTreeselect = async () => { |
| | | const res = await listMenu(); |
| | | const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId"); |
| | | if (data) { |
| | | menuOptions.value = data |
| | | } |
| | | } |
| | | |
| | | watch(() => props.info.subTableName, val => { |
| | | setSubTableColumns(val); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getMenuTreeselect(); |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <el-form ref="genInfoForm" :model="infoForm" :rules="rules" label-width="150px"> |
| | | <el-row> |
| | |
| | | </template> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { listMenu } from '@/api/system/menu'; |
| | | import { ComponentInternalInstance, PropType } from 'vue'; |
| | | |
| | | interface MenuOptionsType { |
| | | menuId: number; |
| | | menuName: string; |
| | | children: MenuOptionsType[] | undefined; |
| | | } |
| | | |
| | | const subColumns = ref<any>([]); |
| | | const menuOptions = ref<Array<MenuOptionsType>>([]); |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | |
| | | const props = defineProps({ |
| | | info: { |
| | | type: Object as PropType<any>, |
| | | default: null |
| | | }, |
| | | tables: { |
| | | type: Array as PropType<any[]>, |
| | | default: null |
| | | } |
| | | }); |
| | | |
| | | const infoForm = computed(() => props.info); |
| | | |
| | | const table = computed(() => props.tables); |
| | | |
| | | // 表单校验 |
| | | const rules = ref({ |
| | | tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }], |
| | | packageName: [{ required: true, message: "请输入生成包路径", trigger: "blur" }], |
| | | moduleName: [{ required: true, message: "请输入生成模块名", trigger: "blur" }], |
| | | businessName: [{ required: true, message: "请输入生成业务名", trigger: "blur" }], |
| | | functionName: [{ required: true, message: "请输入生成功能名", trigger: "blur" }] |
| | | }); |
| | | const subSelectChange = () => { |
| | | infoForm.value.subTableFkName = ""; |
| | | } |
| | | const tplSelectChange = (value: string) => { |
| | | if (value !== "sub") { |
| | | infoForm.value.subTableName = ""; |
| | | infoForm.value.subTableFkName = ""; |
| | | } |
| | | } |
| | | const setSubTableColumns = (value: string) => { |
| | | table.value.forEach(item => { |
| | | const name = item.tableName; |
| | | if (value === name) { |
| | | subColumns.value = item.columns; |
| | | return; |
| | | } |
| | | }) |
| | | } |
| | | /** 查询菜单下拉树结构 */ |
| | | const getMenuTreeselect = async () => { |
| | | const res = await listMenu(); |
| | | const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId"); |
| | | if (data) { |
| | | menuOptions.value = data |
| | | } |
| | | } |
| | | |
| | | watch(() => props.info.subTableName, val => { |
| | | setSubTableColumns(val); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getMenuTreeselect(); |
| | | }) |
| | | </script> |