This commit is contained in:
songgaoshuai 2023-10-18 15:17:38 +08:00
commit a6d47a8ad4
15 changed files with 202 additions and 197 deletions

View File

@ -18,7 +18,7 @@
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "2.1.0", "@element-plus/icons-vue": "2.1.0",
"@vueup/vue-quill": "1.1.0", "@vueup/vue-quill": "1.2.0",
"@vueuse/core": "9.5.0", "@vueuse/core": "9.5.0",
"animate.css": "4.1.1", "animate.css": "4.1.1",
"await-to-js": "^3.0.0", "await-to-js": "^3.0.0",

View File

@ -1,4 +1,5 @@
export interface OperLogQuery extends PageQuery { export interface OperLogQuery extends PageQuery {
operIp: string;
title: string; title: string;
operName: string; operName: string;
businessType: string; businessType: string;

View File

@ -20,7 +20,7 @@ export function getConfig(configId: string | number): AxiosPromise<ConfigVO> {
} }
// 根据参数键名查询参数值 // 根据参数键名查询参数值
export function getConfigKey(configKey: string): AxiosPromise<ConfigVO> { export function getConfigKey(configKey: string): AxiosPromise<String> {
return request({ return request({
url: '/system/config/configKey/' + configKey, url: '/system/config/configKey/' + configKey,
method: 'get' method: 'get'

View File

@ -136,7 +136,7 @@ export const updateUserPwd = (oldPassword: string, newPassword: string) => {
headers: { headers: {
isEncrypt: true isEncrypt: true
}, },
params: data data: data
}); });
}; };

View File

@ -227,23 +227,4 @@
margin-right: 16px; margin-right: 16px;
} }
} }
// the scroll bar appears when the sub-menu is too long
> .el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
} }

View File

@ -9,13 +9,13 @@
name="file" name="file"
:show-file-list="false" :show-file-list="false"
:headers="upload.headers" :headers="upload.headers"
style="display: none" ref="uploadRef"
v-if="type === 'url'" v-if="type === 'url'"
> >
</el-upload> </el-upload>
<div class="editor"> <div class="editor">
<quill-editor <quill-editor
ref="myQuillEditor" ref="quillEditorRef"
v-model:content="content" v-model:content="content"
contentType="html" contentType="html"
@textChange="(e: any) => $emit('update:modelValue', content)" @textChange="(e: any) => $emit('update:modelValue', content)"
@ -53,7 +53,7 @@ const upload = reactive<UploadOption>({
headers: globalHeaders(), headers: globalHeaders(),
url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload' url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload'
}) })
const myQuillEditor = ref(); const quillEditorRef = ref();
const options = ref({ const options = ref({
theme: "snow", theme: "snow",
@ -86,7 +86,7 @@ const options = ref({
}, },
} }
}, },
placeholder: '请输入内容', placeholder: "请输入内容",
readOnly: props.readOnly, readOnly: props.readOnly,
}); });
@ -110,10 +110,10 @@ watch(() => props.modelValue, (v) => {
// //
const handleUploadSuccess = (res: any) => { const handleUploadSuccess = (res: any) => {
//
let quill = toRaw(myQuillEditor.value).getQuill();
// //
if (res.code === 200) { if (res.code === 200) {
//
let quill = toRaw(quillEditorRef.value).getQuill();
// //
let length = quill.selection.savedRange.index; let length = quill.selection.savedRange.index;
// res // res
@ -129,6 +129,13 @@ const handleUploadSuccess = (res: any) => {
// //
const handleBeforeUpload = (file: any) => { const handleBeforeUpload = (file: any) => {
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
const isJPG = type.includes(file.type);
//
if (!isJPG) {
proxy?.$modal.msgError(`图片格式错误!`);
return false;
}
// //
if (props.fileSize) { if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize; const isLt = file.size / 1024 / 1024 < props.fileSize;
@ -149,95 +156,80 @@ const handleUploadError = (err: any) => {
</script> </script>
<style> <style>
.editor-img-uploader {
display: none;
}
.editor, .editor,
.ql-toolbar { .ql-toolbar {
white-space: pre-wrap !important; white-space: pre-wrap !important;
line-height: normal !important; line-height: normal !important;
} }
.quill-img { .quill-img {
display: none; display: none;
} }
.ql-snow .ql-tooltip[data-mode="link"]::before { .ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:"; content: "请输入链接地址:";
} }
.ql-snow .ql-tooltip.ql-editing a.ql-action::after { .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0; border-right: 0;
content: "保存"; content: "保存";
padding-right: 0; padding-right: 0;
} }
.ql-snow .ql-tooltip[data-mode="video"]::before { .ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:"; content: "请输入视频地址:";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label::before, .ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before { .ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px"; content: "14px";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px"; content: "10px";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px"; content: "18px";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px"; content: "32px";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label::before, .ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before { .ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本"; content: "文本";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1"; content: "标题1";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2"; content: "标题2";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3"; content: "标题3";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4"; content: "标题4";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5"; content: "标题5";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6"; content: "标题6";
} }
.ql-snow .ql-picker.ql-font .ql-picker-label::before, .ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before { .ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体"; content: "标准字体";
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体"; content: "衬线字体";
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体"; content: "等宽字体";

View File

@ -1,6 +1,6 @@
<template> <template>
<div :class="{ 'show': show }" class="header-search"> <div :class="{ 'show': show }" class="header-search">
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> <svg-icon class-name="search-icon" icon-class="search" @click.stop="click"/>
<el-select <el-select
ref="headerSearchSelectRef" ref="headerSearchSelectRef"
v-model="search" v-model="search"
@ -12,21 +12,22 @@
class="header-search-select" class="header-search-select"
@change="change" @change="change"
> >
<el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> <el-option v-for="option in options" :key="option.item.path" :value="option.item"
:label="option.item.title.join(' > ')"/>
</el-select> </el-select>
</div> </div>
</template> </template>
<script setup lang="ts" name="HeaderSearch"> <script setup lang="ts" name="HeaderSearch">
import Fuse from 'fuse.js'; import Fuse from 'fuse.js';
import { getNormalPath } from '@/utils/ruoyi'; import {getNormalPath} from '@/utils/ruoyi';
import { isHttp } from '@/utils/validate'; import {isHttp} from '@/utils/validate';
import usePermissionStore from '@/store/modules/permission'; import usePermissionStore from '@/store/modules/permission';
import { RouteOption } from 'vue-router'; import {RouteOption} from 'vue-router';
type Router = Array<{ type Router = Array<{
path: string; path: string;
title: string[]; title: string[];
}> }>
const search = ref(''); const search = ref('');
@ -39,88 +40,99 @@ const router = useRouter();
const routes = computed(() => usePermissionStore().routes); const routes = computed(() => usePermissionStore().routes);
const click = () => { const click = () => {
show.value = !show.value show.value = !show.value
if (show.value) { if (show.value) {
headerSearchSelectRef.value && headerSearchSelectRef.value.focus() headerSearchSelectRef.value && headerSearchSelectRef.value.focus()
} }
}; };
const close = () => { const close = () => {
headerSearchSelectRef.value && headerSearchSelectRef.value.blur() headerSearchSelectRef.value && headerSearchSelectRef.value.blur()
options.value = [] options.value = []
show.value = false show.value = false
} }
const change = (val: any) => { const change = (val: any) => {
const path = val.path; const path = val.path;
if (isHttp(path)) { const query = val.query;
// http(s):// if (isHttp(path)) {
const pindex = path.indexOf("http"); // http(s)://
window.open(path.substr(pindex, path.length), "_blank"); const pindex = path.indexOf("http");
window.open(path.substr(pindex, path.length), "_blank");
} else {
if (query) {
router.push({ path: path, query: JSON.parse(query) });
} else { } else {
router.push(path) router.push(path)
} }
search.value = '' }
options.value = [] search.value = ''
nextTick(() => { options.value = []
show.value = false nextTick(() => {
}) show.value = false
})
} }
const initFuse = (list: Router) => { const initFuse = (list: Router) => {
fuse.value = new Fuse(list, { fuse.value = new Fuse(list, {
shouldSort: true, shouldSort: true,
threshold: 0.4, threshold: 0.4,
location: 0, location: 0,
distance: 100, distance: 100,
minMatchCharLength: 1, minMatchCharLength: 1,
keys: [{ keys: [{
name: 'title', name: 'title',
weight: 0.7 weight: 0.7
}, { }, {
name: 'path', name: 'path',
weight: 0.3 weight: 0.3
}] }]
}) })
} }
// Filter out the routes that can be displayed in the sidebar // Filter out the routes that can be displayed in the sidebar
// And generate the internationalized title // And generate the internationalized title
const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = []) => { const generateRoutes = (routes: RouteOption[], basePath = '', prefixTitle: string[] = [], query: any = {}) => {
let res: Router = [] let res: Router = []
routes.forEach(r => { routes.forEach(r => {
// skip hidden router // skip hidden router
if (!r.hidden) { if (!r.hidden) {
const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path; const p = r.path.length > 0 && r.path[0] === '/' ? r.path : '/' + r.path;
const data = { const data = {
path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path, path: !isHttp(r.path) ? getNormalPath(basePath + p) : r.path,
title: [...prefixTitle] title: [...prefixTitle],
} query: ''
if (r.meta && r.meta.title) { }
data.title = [...data.title, r.meta.title]; if (r.meta && r.meta.title) {
if (r.redirect !== 'noRedirect') { data.title = [...data.title, r.meta.title];
// only push the routes with title if (r.redirect !== 'noRedirect') {
// special case: need to exclude parent router without redirect // only push the routes with title
res.push(data); // special case: need to exclude parent router without redirect
} res.push(data);
}
// recursive child routes
if (r.children) {
const tempRoutes = generateRoutes(r.children, data.path, data.title);
if (tempRoutes.length >= 1) {
res = [...res, ...tempRoutes];
}
}
} }
}) }
return res;
if (r.query) {
data.query = r.query
}
// recursive child routes
if (r.children) {
const tempRoutes = generateRoutes(r.children, data.path, data.title, data.query);
if (tempRoutes.length >= 1) {
res = [...res, ...tempRoutes];
}
}
}
})
return res;
} }
const querySearch = (query: string) => { const querySearch = (query: string) => {
if (query !== '') { if (query !== '') {
options.value = fuse.value.search(query) options.value = fuse.value.search(query)
} else { } else {
options.value = [] options.value = []
} }
} }
onMounted(() => { onMounted(() => {
searchPool.value = generateRoutes(routes.value); searchPool.value = generateRoutes(routes.value);
}) })
// watchEffect(() => { // watchEffect(() => {
@ -128,54 +140,54 @@ onMounted(() => {
// }) // })
watch(show, (value) => { watch(show, (value) => {
if (value) { if (value) {
document.body.addEventListener('click', close) document.body.addEventListener('click', close)
} else { } else {
document.body.removeEventListener('click', close) document.body.removeEventListener('click', close)
} }
}) })
watch(searchPool, (list) => { watch(searchPool, (list) => {
initFuse(list) initFuse(list)
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.header-search { .header-search {
font-size: 0 !important; font-size: 0 !important;
.search-icon { .search-icon {
cursor: pointer; cursor: pointer;
font-size: 18px; font-size: 18px;
vertical-align: middle; vertical-align: middle;
}
.header-search-select {
font-size: 18px;
transition: width 0.2s;
width: 0;
overflow: hidden;
background: transparent;
border-radius: 0;
display: inline-block;
vertical-align: middle;
:deep(.el-input__inner) {
border-radius: 0;
border: 0;
padding-left: 0;
padding-right: 0;
box-shadow: none !important;
border-bottom: 1px solid #d9d9d9;
vertical-align: middle;
} }
}
&.show {
.header-search-select { .header-search-select {
font-size: 18px; width: 210px;
transition: width 0.2s; margin-left: 10px;
width: 0;
overflow: hidden;
background: transparent;
border-radius: 0;
display: inline-block;
vertical-align: middle;
:deep(.el-input__inner) {
border-radius: 0;
border: 0;
padding-left: 0;
padding-right: 0;
box-shadow: none !important;
border-bottom: 1px solid #d9d9d9;
vertical-align: middle;
}
}
&.show {
.header-search-select {
width: 210px;
margin-left: 10px;
}
} }
}
} }
</style> </style>

View File

@ -7,13 +7,25 @@
<el-tooltip class="item" effect="dark" content="刷新" placement="top"> <el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button circle icon="Refresh" @click="refresh()" /> <el-button circle icon="Refresh" @click="refresh()" />
</el-tooltip> </el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns"> <el-tooltip class="item" effect="dark" content="显示/隐藏列" placement="top" v-if="columns">
<el-button circle icon="Menu" @click="showColumn()" /> <div>
<el-popover placement="bottom" trigger="click">
<div class="tree-header">显示/隐藏列</div>
<el-tree
ref="columnRef"
:data="columns"
show-checkbox
@check="columnChange"
node-key="key"
:props="{ label: 'label', children: 'children' }"
></el-tree>
<template #reference>
<el-button circle icon="Menu" />
</template>
</el-popover>
</div>
</el-tooltip> </el-tooltip>
</el-row> </el-row>
<el-dialog :title="title" v-model="open" append-to-body>
<el-transfer :titles="['显示', '隐藏']" v-model="value" :data="columns" @change="dataChange"></el-transfer>
</el-dialog>
</div> </div>
</template> </template>
@ -29,15 +41,9 @@ const props = defineProps({
gutter: propTypes.number.def(10), gutter: propTypes.number.def(10),
}) })
const columnRef = ref<ElTreeInstance>();
const emits = defineEmits(['update:showSearch', 'queryTable']); const emits = defineEmits(['update:showSearch', 'queryTable']);
//
const value = ref<Array<number>>([]);
//
const title = ref("显示/隐藏");
//
const open = ref(false);
const style = computed(() => { const style = computed(() => {
const ret: any = {}; const ret: any = {};
if (props.gutter) { if (props.gutter) {
@ -56,23 +62,19 @@ function refresh() {
emits("queryTable"); emits("queryTable");
} }
// //
function dataChange(data: TransferKey[]) { function columnChange(...args: any[]) {
props.columns?.forEach((item) => { props.columns?.forEach((item) => {
item.visible = !data.includes(item.key); item.visible = args[1].checkedKeys.includes(item.key);
}) })
}
// dialog
const showColumn = () => {
open.value = true;
} }
// //
onMounted(() => { onMounted(() => {
props.columns?.forEach((item) => { props.columns?.forEach((item) => {
if (!item.visible) { if (item.visible) {
value.value.push(item.key); columnRef.value?.setChecked(item.key, true, false);
// value.value.push(item.key);
} }
}) })
}) })
@ -91,4 +93,9 @@ onMounted(() => {
.my-el-transfer { .my-el-transfer {
text-align: center; text-align: center;
} }
.tree-header{
width: 100%;
line-height: 24px;
text-align: center;
}
</style> </style>

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-if="!item.hidden"> <div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow"> <template v-if="hasOneShowingChild(item, item.children) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)"> <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
<svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" /> <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" />
@ -18,10 +18,10 @@
</template> </template>
<sidebar-item <sidebar-item
v-for="child in item.children" v-for="(child) in item.children as RouteOption[]"
:key="child.path" :key="child.path"
:is-nest="true" :is-nest="true"
:item="child as RouteOption" :item="child"
:base-path="resolvePath(child.path)" :base-path="resolvePath(child.path)"
class="nest-menu" class="nest-menu"
/> />
@ -34,7 +34,6 @@ import { isExternal } from '@/utils/validate'
import AppLink from './Link.vue' import AppLink from './Link.vue'
import { getNormalPath } from '@/utils/ruoyi' import { getNormalPath } from '@/utils/ruoyi'
import { RouteOption } from "vue-router"; import { RouteOption } from "vue-router";
import { PropType } from "vue";
const props = defineProps({ const props = defineProps({
// route object // route object
@ -54,7 +53,7 @@ const props = defineProps({
const onlyOneChild = ref<any>({}); const onlyOneChild = ref<any>({});
const hasOneShowingChild = (children:RouteOption[] = [], parent: RouteOption) => { const hasOneShowingChild = (parent: RouteOption, children?:RouteOption[]) => {
if (!children) { if (!children) {
children = []; children = [];
} }
@ -76,9 +75,13 @@ const hasOneShowingChild = (children:RouteOption[] = [], parent: RouteOption) =>
// Show parent if there are no child router to display // Show parent if there are no child router to display
if (showingChildren.length === 0) { if (showingChildren.length === 0) {
onlyOneChild.value = { ...parent, path: '', noShowingChildren: true } onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
if (parent.name === '2222') {
console.log(onlyOneChild.value)
}
return true return true
} }
return false return false
}; };

View File

@ -4,7 +4,7 @@
<el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper"> <el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
<transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in"> <transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in">
<el-menu <el-menu
:default-active="activeMenu as string" :default-active="activeMenu"
:collapse="isCollapse" :collapse="isCollapse"
:background-color="bgColor" :background-color="bgColor"
:text-color="textColor" :text-color="textColor"
@ -27,6 +27,7 @@ import variables from '@/assets/styles/variables.module.scss'
import useAppStore from '@/store/modules/app' import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings' import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission' import usePermissionStore from '@/store/modules/permission'
import { RouteOption } from "vue-router";
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute(); const route = useRoute();
@ -34,7 +35,7 @@ const appStore = useAppStore()
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
const permissionStore = usePermissionStore() const permissionStore = usePermissionStore()
const sidebarRouters = computed(() => permissionStore.sidebarRouters); const sidebarRouters = computed<RouteOption[]>(() => permissionStore.sidebarRouters);
const showLogo = computed(() => settingsStore.sidebarLogo); const showLogo = computed(() => settingsStore.sidebarLogo);
const sideTheme = computed(() => settingsStore.sideTheme); const sideTheme = computed(() => settingsStore.sideTheme);
const theme = computed(() => settingsStore.theme); const theme = computed(() => settingsStore.theme);

View File

@ -13,6 +13,7 @@ declare global {
key: number; key: number;
label: string; label: string;
visible: boolean; visible: boolean;
children?: Array<FieldOption>;
} }
/** /**

View File

@ -4,6 +4,9 @@
<div class="mb-[10px]"> <div class="mb-[10px]">
<el-card shadow="hover"> <el-card shadow="hover">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="操作地址" prop="operIp">
<el-input v-model="queryParams.operIp" placeholder="请输入操作地址" clearable style="width: 240px;" @keyup.enter="handleQuery"/>
</el-form-item>
<el-form-item label="系统模块" prop="title"> <el-form-item label="系统模块" prop="title">
<el-input v-model="queryParams.title" placeholder="请输入系统模块" clearable style="width: 240px;" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.title" placeholder="请输入系统模块" clearable style="width: 240px;" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
@ -83,7 +86,7 @@
sortable="custom" sortable="custom"
:sort-orders="['descending', 'ascending']" :sort-orders="['descending', 'ascending']"
/> />
<el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" /> <el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
<el-table-column label="操作状态" align="center" prop="status"> <el-table-column label="操作状态" align="center" prop="status">
<template #default="scope"> <template #default="scope">
<dict-tag :options="sys_common_status" :value="scope.row.status" /> <dict-tag :options="sys_common_status" :value="scope.row.status" />
@ -215,6 +218,7 @@ const data = reactive<PageData<OperLogForm, OperLogQuery>>({
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
operIp: '',
title: '', title: '',
operName: '', operName: '',
businessType: '', businessType: '',

View File

@ -229,7 +229,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" v-if="form.menuType !== 'F'"> <el-col :span="12">
<el-form-item> <el-form-item>
<template #label> <template #label>
<span> <span>

View File

@ -194,7 +194,7 @@ const { queryParams, form, rules } = toRefs(data);
const getList = async () => { const getList = async () => {
loading.value = true; loading.value = true;
const res = await proxy?.getConfigKey("sys.oss.previewListResource"); const res = await proxy?.getConfigKey("sys.oss.previewListResource");
previewListResource.value = res?.msg === undefined ? true : res.msg === 'true'; previewListResource.value = res?.data === undefined ? true : res.data === 'true';
const response = await listOss(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, "CreateTime")); const response = await listOss(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, "CreateTime"));
ossList.value = response.rows; ossList.value = response.rows;
total.value = response.total; total.value = response.total;

View File

@ -320,7 +320,7 @@ const total = ref(0);
const dateRange = ref<[DateModelType, DateModelType]>(['', '']); const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
const deptName = ref(''); const deptName = ref('');
const deptOptions = ref<DeptVO[]>([]); const deptOptions = ref<DeptVO[]>([]);
const initPassword = ref('123456'); const initPassword = ref<String>('');
const postOptions = ref<PostVO[]>([]); const postOptions = ref<PostVO[]>([]);
const roleOptions = ref<RoleVO[]>([]); const roleOptions = ref<RoleVO[]>([]);
/*** 用户导入参数 */ /*** 用户导入参数 */
@ -340,13 +340,13 @@ const upload = reactive<ImportOption>({
}) })
// //
const columns = ref<FieldOption[]>([ const columns = ref<FieldOption[]>([
{ key: 0, label: `用户编号`, visible: false }, { key: 0, label: `用户编号`, visible: false,children: [] },
{ key: 1, label: `用户名称`, visible: true }, { key: 1, label: `用户名称`, visible: true,children: [] },
{ key: 2, label: `用户昵称`, visible: true }, { key: 2, label: `用户昵称`, visible: true,children: [] },
{ key: 3, label: `部门`, visible: true }, { key: 3, label: `部门`, visible: true,children: [] },
{ key: 4, label: `手机号码`, visible: true }, { key: 4, label: `手机号码`, visible: true,children: [] },
{ key: 5, label: `状态`, visible: true }, { key: 5, label: `状态`, visible: true,children: [] },
{ key: 6, label: `创建时间`, visible: true } { key: 6, label: `创建时间`, visible: true,children: [] }
]) ])
@ -561,7 +561,7 @@ const handleAdd = async () => {
await initTreeData(); await initTreeData();
postOptions.value = data.posts; postOptions.value = data.posts;
roleOptions.value = data.roles; roleOptions.value = data.roles;
form.value.password = initPassword.value; form.value.password = initPassword.value.toString();
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
const handleUpdate = async (row?: UserForm) => { const handleUpdate = async (row?: UserForm) => {
@ -613,6 +613,9 @@ const resetForm = () => {
onMounted(() => { onMounted(() => {
getTreeSelect() // getTreeSelect() //
getList() // getList() //
proxy?.getConfigKey("sys.user.initPassword").then(response => {
initPassword.value = response.data;
});
}); });
</script> </script>