mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-08 22:57:11 +08:00
refactor: eslint src --fix
This commit is contained in:
@@ -6,4 +6,4 @@ const BASE_URL = '/captcha'
|
||||
/** @desc 获取图片验证码 */
|
||||
export function getImageCaptcha() {
|
||||
return http.get<Common.ImageCaptchaResp>(`${BASE_URL}/img`)
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import http from '@/utils/http'
|
||||
import type { LabelValueState } from '@/types/global'
|
||||
import type { TreeNodeData } from '@arco-design/web-vue'
|
||||
import type {OptionQuery} from '@/apis'
|
||||
import type { OptionQuery } from '@/apis'
|
||||
|
||||
const BASE_URL = '/common'
|
||||
|
||||
@@ -33,4 +33,4 @@ export function listOption(params: OptionQuery) {
|
||||
/** @desc 上传文件 */
|
||||
export function uploadFile(data: FormData) {
|
||||
return http.post(`${BASE_URL}/file`, data)
|
||||
}
|
||||
}
|
||||
|
@@ -9,4 +9,3 @@ export * from './auth/type'
|
||||
export * from './common/type'
|
||||
export * from './monitor/type'
|
||||
export * from './system/type'
|
||||
|
||||
|
@@ -43,7 +43,7 @@ export interface LogDetailResp extends LogResp {
|
||||
responseHeaders: string
|
||||
responseBody: string
|
||||
}
|
||||
export interface LogQuery{
|
||||
export interface LogQuery {
|
||||
description?: string
|
||||
module?: string
|
||||
ip?: string
|
||||
|
@@ -221,4 +221,4 @@ export interface BasicConfigRecordResp {
|
||||
site_copyright?: string
|
||||
site_logo?: string
|
||||
site_favicon?: string
|
||||
}
|
||||
}
|
||||
|
@@ -1,21 +1,11 @@
|
||||
<template>
|
||||
<span v-if="!dictItem"></span>
|
||||
<span v-else-if="!dictItem.color">{{ dictItem.label }}</span>
|
||||
<a-tag v-else-if="dictItem.color === 'primary'" color="arcoblue">{{
|
||||
dictItem.label
|
||||
}}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'success'" color="green">{{
|
||||
dictItem.label
|
||||
}}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'warning'" color="orangered">{{
|
||||
dictItem.label
|
||||
}}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'error'" color="red">{{
|
||||
dictItem.label
|
||||
}}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'default'" color="gray">{{
|
||||
dictItem.label
|
||||
}}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'primary'" color="arcoblue">{{ dictItem.label }}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'success'" color="green">{{ dictItem.label }}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'warning'" color="orangered">{{ dictItem.label }}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'error'" color="red">{{ dictItem.label }}</a-tag>
|
||||
<a-tag v-else-if="dictItem.color === 'default'" color="gray">{{ dictItem.label }}</a-tag>
|
||||
<a-tag v-else :color="dictItem.color">{{ dictItem.label }}</a-tag>
|
||||
</template>
|
||||
|
||||
@@ -27,19 +17,17 @@ defineOptions({ name: 'GiCellTag' })
|
||||
const props = defineProps({
|
||||
dict: {
|
||||
type: Array<LabelValueState>,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const dictItem = computed(() =>
|
||||
props.dict.find(
|
||||
(d) => d.value === String(props.value) || d.value === Number(props.value),
|
||||
),
|
||||
);
|
||||
props.dict.find((d) => d.value === String(props.value) || d.value === Number(props.value))
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="gi-footer">{{appStore.getCopyright()}}</div>
|
||||
<div class="gi-footer">{{ appStore.getCopyright() }}</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Dayjs from 'dayjs'
|
||||
import {useAppStore} from "@/stores";
|
||||
import { useAppStore } from '@/stores'
|
||||
|
||||
const appStore = useAppStore();
|
||||
const appStore = useAppStore()
|
||||
|
||||
defineOptions({ name: 'GiFooter' })
|
||||
|
||||
|
@@ -90,7 +90,7 @@ const searchValue = ref('') // 搜索词
|
||||
// 图标列表
|
||||
const isGridView = ref(false)
|
||||
|
||||
let iconList: string[] = []
|
||||
const iconList: string[] = []
|
||||
for (const path in SvgIconModules) {
|
||||
console.log(path)
|
||||
const name = path.replace('/src/assets/icons/', '').replace('.svg', '')
|
||||
|
@@ -1,10 +1,6 @@
|
||||
<template>
|
||||
<div class="json_pretty_container">
|
||||
<vue-json-pretty
|
||||
:path="'res'"
|
||||
:data="JSONObject"
|
||||
:show-length="true"
|
||||
/>
|
||||
<vue-json-pretty :path="'res'" :data="JSONObject" :show-length="true" />
|
||||
<icon-copy class="copy_icon" @click="onCopy(JSONObject)" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -29,12 +25,12 @@ const onCopy = (data: object) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.json_pretty_container{
|
||||
.json_pretty_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
.copy_icon{
|
||||
.copy_icon {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
@@ -42,4 +38,4 @@ const onCopy = (data: object) => {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<icon-copy :size="16" @click="copyText"/>
|
||||
<icon-copy :size="16" @click="copyText" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Message } from "@arco-design/web-vue"
|
||||
interface Props{
|
||||
value:any
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
interface Props {
|
||||
value: any
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {})
|
||||
const copyText=()=>{
|
||||
const copyText = () => {
|
||||
const textarea = document.createElement('textarea')
|
||||
textarea.value = props.value
|
||||
document.body.appendChild(textarea)
|
||||
@@ -20,9 +20,9 @@ const copyText=()=>{
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.content{
|
||||
.content {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@@ -10,16 +10,11 @@ import { Message, Notification } from '@arco-design/web-vue'
|
||||
interface NavigatorWithMsSaveOrOpenBlob extends Navigator {
|
||||
msSaveOrOpenBlob(blob: Blob, fileName: string): void
|
||||
}
|
||||
export const useDownload = async (
|
||||
api: () => Promise<any>,
|
||||
isNotify = true,
|
||||
tempName: string = '',
|
||||
fileType = '.xlsx'
|
||||
) => {
|
||||
export const useDownload = async (api: () => Promise<any>, isNotify = true, tempName = '', fileType = '.xlsx') => {
|
||||
try {
|
||||
const res = await api()
|
||||
if (res.headers['content-disposition']) {
|
||||
tempName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]);
|
||||
tempName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1])
|
||||
} else {
|
||||
tempName = tempName ? tempName : new Date().getTime() + fileType
|
||||
}
|
||||
@@ -36,7 +31,7 @@ export const useDownload = async (
|
||||
const blob = new Blob([res.data])
|
||||
// 兼容 edge 不支持 createObjectURL 方法
|
||||
if ('msSaveOrOpenBlob' in (navigator as unknown as NavigatorWithMsSaveOrOpenBlob)) {
|
||||
; (window.navigator as unknown as NavigatorWithMsSaveOrOpenBlob).msSaveOrOpenBlob(blob, tempName + fileType)
|
||||
;(window.navigator as unknown as NavigatorWithMsSaveOrOpenBlob).msSaveOrOpenBlob(blob, tempName + fileType)
|
||||
}
|
||||
const blobUrl = window.URL.createObjectURL(blob)
|
||||
const exportFile = document.createElement('a')
|
||||
|
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<section class="system-logo" :class="{ collapsed: props.collapsed }" @click="toHome">
|
||||
<img class="logo" :src="appStore.getLogo() ?? '@/assets/images/logo.svg'" alt="logo"/>
|
||||
<span class="system-name">{{ appStore.getTitle()}}</span>
|
||||
<img class="logo" :src="appStore.getLogo() ?? '@/assets/images/logo.svg'" alt="logo" />
|
||||
<span class="system-name">{{ appStore.getTitle() }}</span>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useAppStore} from "@/stores";
|
||||
import { useAppStore } from '@/stores'
|
||||
|
||||
const appStore= useAppStore();
|
||||
const appStore = useAppStore()
|
||||
|
||||
interface Props {
|
||||
collapsed?: boolean
|
||||
|
@@ -54,7 +54,7 @@ const mode = computed(() => {
|
||||
|
||||
// 是否默认展开选中的菜单
|
||||
const autoOpenSelected = computed(() => {
|
||||
return ['left', 'mix'].includes(appStore.layout);
|
||||
return ['left', 'mix'].includes(appStore.layout)
|
||||
})
|
||||
|
||||
// 当前页面激活菜单路径,先从路由里面找
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import router from '@/router'
|
||||
import {useUserStore, useRouteStore, useAppStore} from '@/stores'
|
||||
import { useUserStore, useRouteStore, useAppStore } from '@/stores'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { isHttp } from '@/utils/validate'
|
||||
|
||||
@@ -15,8 +15,8 @@ export const resetHasRouteFlag = () => {
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const userStore = useUserStore()
|
||||
const routeStore = useRouteStore()
|
||||
const appStore = useAppStore();
|
||||
appStore.initWebConfig();
|
||||
const appStore = useAppStore()
|
||||
appStore.initWebConfig()
|
||||
|
||||
// 判断该用户是否登录
|
||||
if (getToken()) {
|
||||
|
@@ -12,7 +12,7 @@ const storeSetup = () => {
|
||||
const webConfig = reactive({}) as BasicConfigRecordResp
|
||||
|
||||
const getLogo = () => {
|
||||
return webConfig.site_logo;
|
||||
return webConfig.site_logo
|
||||
}
|
||||
const getFavicon = () => {
|
||||
return webConfig.site_favicon
|
||||
@@ -26,17 +26,17 @@ const storeSetup = () => {
|
||||
|
||||
// 初始化系统配置
|
||||
const initWebConfig = () => {
|
||||
listOption({
|
||||
listOption({
|
||||
code: ['site_title', 'site_copyright', 'site_favicon', 'site_logo']
|
||||
}).then((res) => {
|
||||
const resMap = new Map()
|
||||
res.data.forEach((item) => {
|
||||
resMap.set(item.label, item.value)
|
||||
})
|
||||
webConfig.site_title=resMap.get('site_title');
|
||||
webConfig.site_copyright=resMap.get('site_copyright');
|
||||
webConfig.site_logo=resMap.get('site_logo');
|
||||
webConfig.site_favicon=resMap.get('site_favicon');
|
||||
webConfig.site_title = resMap.get('site_title')
|
||||
webConfig.site_copyright = resMap.get('site_copyright')
|
||||
webConfig.site_logo = resMap.get('site_logo')
|
||||
webConfig.site_favicon = resMap.get('site_favicon')
|
||||
document.title = resMap.get('site_title')
|
||||
document
|
||||
.querySelector('link[rel="shortcut icon"]')
|
||||
@@ -46,7 +46,7 @@ const storeSetup = () => {
|
||||
|
||||
// 保存系统配置
|
||||
const saveWebConfig = (config: BasicConfigRecordResp) => {
|
||||
Object.assign(webConfig,config)
|
||||
Object.assign(webConfig, config)
|
||||
document.title = config.site_title || ''
|
||||
document
|
||||
.querySelector('link[rel="shortcut icon"]')
|
||||
@@ -118,4 +118,4 @@ const storeSetup = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const useAppStore = defineStore('app', storeSetup, {persist: true})
|
||||
export const useAppStore = defineStore('app', storeSetup, { persist: true })
|
||||
|
1
src/types/global.d.ts
vendored
1
src/types/global.d.ts
vendored
@@ -20,7 +20,6 @@ export interface DictState {
|
||||
items: Array<LabelValueState>
|
||||
}
|
||||
|
||||
|
||||
/** 状态(1:启用;2:禁用) */
|
||||
type Status = 1 | 2
|
||||
|
||||
|
@@ -61,7 +61,7 @@ http.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
const { data } = response
|
||||
const { success, code, msg } = data
|
||||
if(response.request.responseType==='blob'){
|
||||
if (response.request.responseType === 'blob') {
|
||||
NProgress.done()
|
||||
return response
|
||||
}
|
||||
@@ -186,4 +186,4 @@ const download = <T = any>(url: string, params?: object, config?: AxiosRequestCo
|
||||
...config
|
||||
})
|
||||
}
|
||||
export default { get, post, put, patch, del, request, requestNative,download }
|
||||
export default { get, post, put, patch, del, request, requestNative, download }
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { isExternal } from "@/utils/validate";
|
||||
import { browse, mapTree } from "xe-utils";
|
||||
import _ from "lodash";
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import { browse, mapTree } from 'xe-utils'
|
||||
import _ from 'lodash'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
|
||||
export function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
|
||||
return obj[key]
|
||||
@@ -76,7 +76,7 @@ export function isEmpty(data: unknown) {
|
||||
if (data === '' || data === 'undefined' || data === undefined || data === null || data === 'null') {
|
||||
return true
|
||||
}
|
||||
return JSON.stringify(data) == '{}' || JSON.stringify(data) == '[]' || JSON.stringify(data) == '[{}]';
|
||||
return JSON.stringify(data) == '{}' || JSON.stringify(data) == '[]' || JSON.stringify(data) == '[{}]'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,12 +243,12 @@ export const formatFileSize = (fileSize: number) => {
|
||||
const size = srcSize / 1024 ** index
|
||||
return `${size.toFixed(2)} ${unitArr[index]}`
|
||||
}
|
||||
export const copyText =(text:any) =>{
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
export const copyText = (text: any) => {
|
||||
const textarea = document.createElement('textarea')
|
||||
textarea.value = text
|
||||
document.body.appendChild(textarea)
|
||||
textarea.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(textarea)
|
||||
Message.success('复制成功')
|
||||
}
|
||||
}
|
||||
|
@@ -22,16 +22,16 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
interface ImageType {
|
||||
src: string;
|
||||
title: string;
|
||||
link: string;
|
||||
src: string
|
||||
title: string
|
||||
link: string
|
||||
}
|
||||
|
||||
const imageList: ImageType[] = [
|
||||
{
|
||||
src: `https://doc.charles7c.top/img/sponsor/ad/roovps.jpg?${new Date().getTime()}`,
|
||||
title: 'ROOVPS',
|
||||
link: 'https://roovps.com/cart',
|
||||
},
|
||||
];
|
||||
link: 'https://roovps.com/cart'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
|
@@ -7,8 +7,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-bg {
|
||||
|
@@ -20,7 +20,7 @@
|
||||
>
|
||||
<h3 class="login-right__title">
|
||||
<img :src="appStore.getLogo()" alt="Logo" height="33" />
|
||||
<span>{{appStore.getTitle()}}</span>
|
||||
<span>{{ appStore.getTitle() }}</span>
|
||||
</h3>
|
||||
<a-form-item field="username">
|
||||
<a-input v-model="form.username" placeholder="请输入用户名" allow-clear>
|
||||
@@ -57,25 +57,24 @@
|
||||
<GiThemeBtn class="theme-btn"></GiThemeBtn>
|
||||
<LoginBg></LoginBg>
|
||||
|
||||
<!-- <div class="footer">
|
||||
<!-- <div class="footer">
|
||||
<div class="beian">
|
||||
<div class="below text" v-html="appStore.getCopyright()"></div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getImageCaptcha } from '@/apis'
|
||||
import { Message, type FormInstance } from '@arco-design/web-vue'
|
||||
import LoginBg from './components/LoginBg/index.vue'
|
||||
import {useAppStore, useUserStore} from '@/stores'
|
||||
import { useAppStore, useUserStore } from '@/stores'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { useLoading } from '@/hooks'
|
||||
import { encryptByRsa } from '@/utils/encrypt'
|
||||
|
||||
const appStore = useAppStore();
|
||||
const appStore = useAppStore()
|
||||
|
||||
defineOptions({ name: 'Login' })
|
||||
|
||||
|
@@ -77,7 +77,9 @@ const columns: TableInstance['columns'] = [
|
||||
value: '2'
|
||||
}
|
||||
],
|
||||
filter: () =>{return true},
|
||||
filter: () => {
|
||||
return true
|
||||
},
|
||||
alignLeft: true
|
||||
}
|
||||
},
|
||||
|
@@ -2,7 +2,9 @@
|
||||
<a-drawer v-model:visible="visible" title="日志详情" :width="720" :footer="false">
|
||||
<a-descriptions title="基本信息" :column="2" size="large" class="general-description">
|
||||
<a-descriptions-item label="日志 ID">{{ dataDetail?.id }}</a-descriptions-item>
|
||||
<a-descriptions-item label="Trace ID" >{{ dataDetail?.traceId }}<TextCopy :value="dataDetail?.traceId" /></a-descriptions-item>
|
||||
<a-descriptions-item label="Trace ID"
|
||||
>{{ dataDetail?.traceId }}<TextCopy :value="dataDetail?.traceId"
|
||||
/></a-descriptions-item>
|
||||
<a-descriptions-item label="操作人">{{ dataDetail?.createUserString }}</a-descriptions-item>
|
||||
<a-descriptions-item label="操作时间">{{ dataDetail?.createTime }}</a-descriptions-item>
|
||||
<a-descriptions-item label="操作内容">{{ dataDetail?.description }}</a-descriptions-item>
|
||||
@@ -16,12 +18,8 @@
|
||||
<a-tag v-else color="red">失败</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="耗时">
|
||||
<a-tag v-if="dataDetail?.timeTaken > 500" color="red">
|
||||
{{ dataDetail?.timeTaken }}ms
|
||||
</a-tag>
|
||||
<a-tag v-else-if="dataDetail?.timeTaken > 200" color="orange">
|
||||
{{ dataDetail?.timeTaken }}ms
|
||||
</a-tag>
|
||||
<a-tag v-if="dataDetail?.timeTaken > 500" color="red"> {{ dataDetail?.timeTaken }}ms </a-tag>
|
||||
<a-tag v-else-if="dataDetail?.timeTaken > 200" color="orange"> {{ dataDetail?.timeTaken }}ms </a-tag>
|
||||
<a-tag v-else color="green">{{ dataDetail?.timeTaken }} ms</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求 URI" :span="2">
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<a-tab-pane key="2" title="操作日志" />
|
||||
</a-tabs>
|
||||
<keep-alive>
|
||||
<component :is="PaneMap[activeKey]" />
|
||||
<component :is="PaneMap[activeKey]" />
|
||||
</keep-alive>
|
||||
</a-card>
|
||||
</div>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
</div>
|
||||
<div class="page"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -10,7 +9,6 @@ defineOptions({ name: 'Notification' })
|
||||
|
||||
const route = useRoute()
|
||||
const form = reactive({ name: '' })
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -76,7 +76,6 @@ defineOptions({ name: 'Profile' })
|
||||
|
||||
const route = useRoute()
|
||||
const userStore = useUserStore()
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
</div>
|
||||
<div class="page"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -10,7 +9,6 @@ defineOptions({ name: 'Security' })
|
||||
|
||||
const route = useRoute()
|
||||
const form = reactive({ name: '' })
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -6,32 +6,32 @@
|
||||
{{ siteFavicon?.name }}
|
||||
<template #extra>
|
||||
{{ siteFavicon?.description }}
|
||||
<br/>
|
||||
<br />
|
||||
<a-upload
|
||||
:file-list="faviconFile ? [faviconFile] : []"
|
||||
accept="image/*"
|
||||
:show-file-list="false"
|
||||
:custom-request="handleUploadFavicon"
|
||||
@change="handleChangeFavicon"
|
||||
:file-list="faviconFile ? [faviconFile] : []"
|
||||
accept="image/*"
|
||||
:show-file-list="false"
|
||||
:custom-request="handleUploadFavicon"
|
||||
@change="handleChangeFavicon"
|
||||
>
|
||||
<template #upload-button>
|
||||
<div
|
||||
:class="`arco-upload-list-item${
|
||||
:class="`arco-upload-list-item${
|
||||
faviconFile && faviconFile.status === 'error' ? ' arco-upload-list-item-error' : ''
|
||||
}`"
|
||||
>
|
||||
<div
|
||||
v-if="faviconFile && faviconFile.url"
|
||||
class="arco-upload-list-picture custom-upload-avatar favicon"
|
||||
v-if="faviconFile && faviconFile.url"
|
||||
class="arco-upload-list-picture custom-upload-avatar favicon"
|
||||
>
|
||||
<img :src="faviconFile.url" alt="favicon"/>
|
||||
<img :src="faviconFile.url" alt="favicon" />
|
||||
<div v-if="isEdit" class="arco-upload-list-picture-mask favicon">
|
||||
<IconEdit/>
|
||||
<IconEdit />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="arco-upload-picture-card favicon">
|
||||
<div class="arco-upload-picture-card-text">
|
||||
<icon-upload/>
|
||||
<icon-upload />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,29 +45,29 @@
|
||||
{{ siteLogo?.name }}
|
||||
<template #extra>
|
||||
{{ siteLogo?.description }}
|
||||
<br/>
|
||||
<br />
|
||||
<a-upload
|
||||
:file-list="logoFile ? [logoFile] : []"
|
||||
accept="image/*"
|
||||
:show-file-list="false"
|
||||
:custom-request="handleUploadLogo"
|
||||
@change="handleChangeLogo"
|
||||
:file-list="logoFile ? [logoFile] : []"
|
||||
accept="image/*"
|
||||
:show-file-list="false"
|
||||
:custom-request="handleUploadLogo"
|
||||
@change="handleChangeLogo"
|
||||
>
|
||||
<template #upload-button>
|
||||
<div
|
||||
:class="`arco-upload-list-item${
|
||||
:class="`arco-upload-list-item${
|
||||
logoFile && logoFile.status === 'error' ? ' arco-upload-list-item-error' : ''
|
||||
}`"
|
||||
>
|
||||
<div v-if="logoFile && logoFile.url" class="arco-upload-list-picture custom-upload-avatar logo">
|
||||
<img :src="logoFile.url" alt="Logo"/>
|
||||
<img :src="logoFile.url" alt="Logo" />
|
||||
<div v-if="isEdit" class="arco-upload-list-picture-mask logo">
|
||||
<IconEdit/>
|
||||
<IconEdit />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="arco-upload-picture-card logo">
|
||||
<div class="arco-upload-picture-card-text">
|
||||
<icon-upload/>
|
||||
<icon-upload />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,47 +78,47 @@
|
||||
</a-list-item>
|
||||
<a-list-item style="padding-top: 13px; border: none">
|
||||
<a-form-item class="input-item" :label="siteTitle?.name" field="site_title">
|
||||
<a-input v-model="form.site_title" placeholder="请输入网站标题" :max-length="18"/>
|
||||
<a-input v-model="form.site_title" placeholder="请输入网站标题" :max-length="18" />
|
||||
</a-form-item>
|
||||
<a-form-item class="input-item" :label="siteCopyright?.name" field="site_copyright" tooltip="支持HTML标签">
|
||||
<a-textarea
|
||||
v-model="form.site_copyright"
|
||||
placeholder="请输入版权信息"
|
||||
:auto-size="{
|
||||
v-model="form.site_copyright"
|
||||
placeholder="请输入版权信息"
|
||||
:auto-size="{
|
||||
minRows: 3
|
||||
}"
|
||||
show-word-limit
|
||||
show-word-limit
|
||||
/>
|
||||
</a-form-item>
|
||||
<div style="margin-top: 20px">
|
||||
<a-space>
|
||||
<a-button v-if="!isEdit" @click="toResetValue">
|
||||
<template #icon>
|
||||
<icon-undo/>
|
||||
<icon-undo />
|
||||
</template>
|
||||
恢复默认
|
||||
</a-button>
|
||||
<a-button v-if="!isEdit" type="primary" @click="toEdit">
|
||||
<template #icon>
|
||||
<icon-edit/>
|
||||
<icon-edit />
|
||||
</template>
|
||||
修改
|
||||
</a-button>
|
||||
<a-button v-if="isEdit" type="primary" @click="handleSave">
|
||||
<template #icon>
|
||||
<icon-save/>
|
||||
<icon-save />
|
||||
</template>
|
||||
保存
|
||||
</a-button>
|
||||
<a-button v-if="isEdit" @click="reset">
|
||||
<template #icon>
|
||||
<icon-refresh/>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
<a-button v-if="isEdit" @click="handleCancel">
|
||||
<template #icon>
|
||||
<icon-undo/>
|
||||
<icon-undo />
|
||||
</template>
|
||||
取消
|
||||
</a-button>
|
||||
@@ -130,17 +130,17 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type {OptionResp} from '@/apis'
|
||||
import {list, resetValue, save, uploadFile} from '@/apis'
|
||||
import {useAppStore} from '@/stores'
|
||||
import {type FileItem, type FormInstance, type RequestOption, Message, Modal} from '@arco-design/web-vue'
|
||||
import {useForm} from '@/hooks'
|
||||
import type { OptionResp } from '@/apis'
|
||||
import { list, resetValue, save, uploadFile } from '@/apis'
|
||||
import { useAppStore } from '@/stores'
|
||||
import { type FileItem, type FormInstance, type RequestOption, Message, Modal } from '@arco-design/web-vue'
|
||||
import { useForm } from '@/hooks'
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const dataList = ref<OptionResp[]>([])
|
||||
const isEdit = ref(false)
|
||||
const logoFile = ref<FileItem>({uid: '-1'})
|
||||
const faviconFile = ref<FileItem>({uid: '-2'})
|
||||
const logoFile = ref<FileItem>({ uid: '-1' })
|
||||
const faviconFile = ref<FileItem>({ uid: '-2' })
|
||||
const siteTitle = ref<OptionResp>()
|
||||
const siteCopyright = ref<OptionResp>()
|
||||
const siteLogo = ref<OptionResp>()
|
||||
@@ -148,11 +148,11 @@ const siteFavicon = ref<OptionResp>()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const rules: FormInstance['rules'] = {
|
||||
site_title: [{required: true, message: '请输入系统标题'}],
|
||||
site_copyright: [{required: true, message: '请输入版权信息'}]
|
||||
site_title: [{ required: true, message: '请输入系统标题' }],
|
||||
site_copyright: [{ required: true, message: '请输入版权信息' }]
|
||||
}
|
||||
|
||||
const {form} = useForm({
|
||||
const { form } = useForm({
|
||||
site_title: '',
|
||||
site_copyright: '',
|
||||
site_logo: '',
|
||||
@@ -169,10 +169,10 @@ const query = reactive({
|
||||
* 重置表单
|
||||
*/
|
||||
const reset = () => {
|
||||
form.site_title=siteTitle.value?.value || '';
|
||||
form.site_copyright= siteCopyright.value?.value || '';
|
||||
form.site_logo= siteLogo.value?.value || '';
|
||||
form. site_favicon=siteFavicon.value?.value || ''
|
||||
form.site_title = siteTitle.value?.value || ''
|
||||
form.site_copyright = siteCopyright.value?.value || ''
|
||||
form.site_logo = siteLogo.value?.value || ''
|
||||
form.site_favicon = siteFavicon.value?.value || ''
|
||||
logoFile.value.url = siteLogo.value?.value
|
||||
faviconFile.value.url = siteFavicon.value?.value
|
||||
}
|
||||
@@ -226,21 +226,21 @@ const handleSave = () => {
|
||||
* @param options /
|
||||
*/
|
||||
const handleUploadLogo = (options: RequestOption) => {
|
||||
const controller = new AbortController();
|
||||
(async function requestWrap() {
|
||||
const {onProgress, onError, onSuccess, fileItem, name = 'file'} = options
|
||||
const controller = new AbortController()
|
||||
;(async function requestWrap() {
|
||||
const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
|
||||
onProgress(20)
|
||||
const formData = new FormData()
|
||||
formData.append(name as string, fileItem.file as Blob)
|
||||
uploadFile(formData)
|
||||
.then((res) => {
|
||||
onSuccess(res)
|
||||
form.site_logo = res.data.url
|
||||
Message.success(res.msg)
|
||||
})
|
||||
.catch((error) => {
|
||||
onError(error)
|
||||
})
|
||||
.then((res) => {
|
||||
onSuccess(res)
|
||||
form.site_logo = res.data.url
|
||||
Message.success(res.msg)
|
||||
})
|
||||
.catch((error) => {
|
||||
onError(error)
|
||||
})
|
||||
})()
|
||||
return {
|
||||
abort() {
|
||||
@@ -257,19 +257,19 @@ const handleUploadLogo = (options: RequestOption) => {
|
||||
const handleUploadFavicon = (options: RequestOption) => {
|
||||
const controller = new AbortController()
|
||||
;(async function requestWrap() {
|
||||
const {onProgress, onError, onSuccess, fileItem, name = 'file'} = options
|
||||
const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
|
||||
onProgress(20)
|
||||
const formData = new FormData()
|
||||
formData.append(name as string, fileItem.file as Blob)
|
||||
uploadFile(formData)
|
||||
.then((res) => {
|
||||
onSuccess(res)
|
||||
form.site_favicon = res.data.url
|
||||
Message.success(res.msg)
|
||||
})
|
||||
.catch((error) => {
|
||||
onError(error)
|
||||
})
|
||||
.then((res) => {
|
||||
onSuccess(res)
|
||||
form.site_favicon = res.data.url
|
||||
Message.success(res.msg)
|
||||
})
|
||||
.catch((error) => {
|
||||
onError(error)
|
||||
})
|
||||
})()
|
||||
return {
|
||||
abort() {
|
||||
|
@@ -89,7 +89,7 @@ const { form, resetForm } = useForm<DeptReq>({
|
||||
name: '',
|
||||
parentId: undefined,
|
||||
sort: 999,
|
||||
status: 1,
|
||||
status: 1
|
||||
})
|
||||
|
||||
// 重置
|
||||
|
@@ -147,7 +147,7 @@ const onDelete = async (item: DeptResp) => {
|
||||
}
|
||||
|
||||
// 导出
|
||||
const onExport = ()=>{
|
||||
const onExport = () => {
|
||||
useDownload(() => exportDept(queryForm))
|
||||
}
|
||||
|
||||
|
@@ -55,12 +55,7 @@
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="组件路径" field="component" v-if="form.type === 2">
|
||||
<a-input
|
||||
v-if="form.isExternal"
|
||||
v-model.trim="form.component"
|
||||
placeholder="请输入组件路径"
|
||||
allow-clear
|
||||
/>
|
||||
<a-input v-if="form.isExternal" v-model.trim="form.component" placeholder="请输入组件路径" allow-clear />
|
||||
<a-input v-else v-model.trim="form.component" placeholder="请输入组件路径" allow-clear>
|
||||
<template #prepend>@/views/</template>
|
||||
<template #append>.vue</template>
|
||||
@@ -241,7 +236,6 @@ const save = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'save-success'): void
|
||||
}>()
|
||||
|
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="visible"
|
||||
title="角色详情"
|
||||
:width="width >= 580 ? 580 : '100%'"
|
||||
:footer="false"
|
||||
>
|
||||
<a-drawer v-model:visible="visible" title="角色详情" :width="width >= 580 ? 580 : '100%'" :footer="false">
|
||||
<a-descriptions title="基础信息" :column="2" size="large" class="general-description">
|
||||
<a-descriptions-item label="ID" :span="2">{{ dataDetail?.id }}</a-descriptions-item>
|
||||
<a-descriptions-item label="名称">{{ dataDetail?.name }}</a-descriptions-item>
|
||||
@@ -22,7 +17,13 @@
|
||||
<a-descriptions-item label="修改时间">{{ dataDetail?.updateTime }}</a-descriptions-item>
|
||||
<a-descriptions-item label="描述" :span="2">{{ dataDetail?.description }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<a-descriptions title="功能权限" :column="2" size="large" class="general-description" style="margin-top: 20px; position: relative">
|
||||
<a-descriptions
|
||||
title="功能权限"
|
||||
:column="2"
|
||||
size="large"
|
||||
class="general-description"
|
||||
style="margin-top: 20px; position: relative"
|
||||
>
|
||||
<a-descriptions-item :span="2">
|
||||
<a-tree
|
||||
ref="menuTreeRef"
|
||||
@@ -34,7 +35,14 @@
|
||||
/>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<a-descriptions v-if="dataDetail?.dataScope === 5" title="数据权限" :column="2" size="large" class="general-description" style="margin-top: 20px; position: relative">
|
||||
<a-descriptions
|
||||
v-if="dataDetail?.dataScope === 5"
|
||||
title="数据权限"
|
||||
:column="2"
|
||||
size="large"
|
||||
class="general-description"
|
||||
style="margin-top: 20px; position: relative"
|
||||
>
|
||||
<a-descriptions-item :span="2">
|
||||
<a-tree
|
||||
ref="deptTreeRef"
|
||||
|
@@ -145,7 +145,6 @@ const RoleDetailDrawerRef = ref<InstanceType<typeof RoleDetailDrawer>>()
|
||||
const openDetail = (item: RoleResp) => {
|
||||
RoleDetailDrawerRef.value?.open(item.id)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@@ -85,7 +85,7 @@
|
||||
<script setup lang="ts">
|
||||
import { getStorage, addStorage, updateStorage } from '@/apis'
|
||||
import type { StorageReq } from './type'
|
||||
import { Message, type FormInstance } from "@arco-design/web-vue";
|
||||
import { Message, type FormInstance } from '@arco-design/web-vue'
|
||||
import { useForm } from '@/hooks'
|
||||
import { useDict } from '@/hooks/app'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
|
@@ -100,15 +100,11 @@ const title = computed(() => (isUpdate.value ? '修改用户' : '新增用户'))
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const rules: FormInstance['rules'] = {
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名' },
|
||||
],
|
||||
nickname: [
|
||||
{ required: true, message: '请输入昵称' },
|
||||
],
|
||||
username: [{ required: true, message: '请输入用户名' }],
|
||||
nickname: [{ required: true, message: '请输入昵称' }],
|
||||
password: [{ required: true, message: '请输入密码' }],
|
||||
deptId: [{ required: true, message: '请选择所属部门' }],
|
||||
roleIds: [{ required: true, message: '请选择角色' }],
|
||||
roleIds: [{ required: true, message: '请选择角色' }]
|
||||
}
|
||||
|
||||
const { form, resetForm } = useForm({
|
||||
|
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="visible"
|
||||
title="用户详情"
|
||||
:width="width >= 580 ? 580 : '100%'"
|
||||
:footer="false"
|
||||
>
|
||||
<a-drawer v-model:visible="visible" title="用户详情" :width="width >= 580 ? 580 : '100%'" :footer="false">
|
||||
<a-descriptions :column="2" size="large" class="general-description">
|
||||
<a-descriptions-item label="ID" :span="2">{{ dataDetail?.id }}</a-descriptions-item>
|
||||
<a-descriptions-item label="用户名">{{ dataDetail?.username }}</a-descriptions-item>
|
||||
|
@@ -30,7 +30,7 @@ const options: Options = {
|
||||
}
|
||||
|
||||
const columns: Columns = [
|
||||
{ label: '密码', field: 'newPassword', type: 'input-password', rules: [{ required: true, message: '请输入密码' }] },
|
||||
{ label: '密码', field: 'newPassword', type: 'input-password', rules: [{ required: true, message: '请输入密码' }] }
|
||||
]
|
||||
|
||||
const { form, resetForm } = useForm({
|
||||
@@ -56,7 +56,7 @@ const save = async () => {
|
||||
try {
|
||||
const isInvalid = await formRef.value?.formRef?.validate()
|
||||
if (isInvalid) return false
|
||||
await resetUserPwd({ newPassword: encryptByRsa(form.newPassword) || ''}, dataId.value)
|
||||
await resetUserPwd({ newPassword: encryptByRsa(form.newPassword) || '' }, dataId.value)
|
||||
Message.success('重置成功')
|
||||
emit('save-success')
|
||||
return true
|
||||
|
@@ -6,14 +6,7 @@
|
||||
<a-input v-model="deptName" placeholder="请输入部门名称" allow-clear style="margin-bottom: 10px">
|
||||
<template #prefix><icon-search /></template>
|
||||
</a-input>
|
||||
<a-tree
|
||||
ref="treeRef"
|
||||
:data="deptList"
|
||||
default-expand-all
|
||||
show-line
|
||||
block-node
|
||||
@select="handleSelectDept"
|
||||
>
|
||||
<a-tree ref="treeRef" :data="deptList" default-expand-all show-line block-node @select="handleSelectDept">
|
||||
</a-tree>
|
||||
</a-col>
|
||||
|
||||
@@ -57,7 +50,12 @@
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template #nickname="{ record }">
|
||||
<GiCellAvatar :avatar="getAvatar(record.avatar, record.gender)" :name="record.nickname" is-link @click="openDetail(record)" />
|
||||
<GiCellAvatar
|
||||
:avatar="getAvatar(record.avatar, record.gender)"
|
||||
:name="record.nickname"
|
||||
is-link
|
||||
@click="openDetail(record)"
|
||||
/>
|
||||
</template>
|
||||
<template #gender="{ record }">
|
||||
<GiCellGender :gender="record.gender" />
|
||||
@@ -178,7 +176,7 @@ const onDelete = (item: UserResp) => {
|
||||
}
|
||||
|
||||
// 导出
|
||||
const onExport = ()=>{
|
||||
const onExport = () => {
|
||||
useDownload(() => exportUser(queryForm))
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user