refactor: 调整 eslint.config.js,优化代码格式

This commit is contained in:
2024-10-28 21:20:08 +08:00
parent 0e8fe5ff1f
commit 9e5dff144b
176 changed files with 5956 additions and 5624 deletions

View File

@@ -6,11 +6,15 @@
<template #extra>
{{ siteConfig.SITE_LOGO.description }}
<br />
<a-upload :file-list="logoFile ? [logoFile] : []" accept="image/*" :show-file-list="false"
:custom-request="handleUploadLogo" @change="handleChangeLogo">
<a-upload
:file-list="logoFile ? [logoFile] : []" accept="image/*" :show-file-list="false"
:custom-request="handleUploadLogo" @change="handleChangeLogo"
>
<template #upload-button>
<div :class="`arco-upload-list-item${logoFile && logoFile.status === 'error' ? ' arco-upload-list-item-error' : ''
}`">
<div
: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" />
<div v-if="isUpdate" class="arco-upload-list-picture-mask logo">
@@ -32,13 +36,19 @@
<template #extra>
{{ siteConfig.SITE_FAVICON.description }}
<br />
<a-upload :file-list="faviconFile ? [faviconFile] : []" accept="image/*" :show-file-list="false"
:custom-request="handleUploadFavicon" @change="handleChangeFavicon">
<a-upload
:file-list="faviconFile ? [faviconFile] : []" accept="image/*" :show-file-list="false"
:custom-request="handleUploadFavicon" @change="handleChangeFavicon"
>
<template #upload-button>
<div :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">
<div
: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"
>
<img :src="faviconFile.url" alt="favicon" />
<div v-if="isUpdate" class="arco-upload-list-picture-mask favicon">
<IconEdit />
@@ -110,7 +120,7 @@ import {
type SiteConfig,
listOption,
resetOptionValue,
updateOption
updateOption,
} from '@/apis/system'
import { useAppStore } from '@/stores'
import { useForm } from '@/hooks'
@@ -124,12 +134,12 @@ const { form } = useForm({
SITE_FAVICON: '',
SITE_LOGO: '',
SITE_TITLE: '',
SITE_COPYRIGHT: ''
SITE_COPYRIGHT: '',
})
const rules: FormInstance['rules'] = {
SITE_TITLE: [{ required: true, message: '请输入系统标题' }],
SITE_DESCRIPTION: [{ required: true, message: '请输入系统描述' }],
SITE_COPYRIGHT: [{ required: true, message: '请输入版权信息' }]
SITE_COPYRIGHT: [{ required: true, message: '请输入版权信息' }],
}
const siteConfig = ref<SiteConfig>({
@@ -138,7 +148,7 @@ const siteConfig = ref<SiteConfig>({
SITE_TITLE: {},
SITE_DESCRIPTION: {},
SITE_COPYRIGHT: {},
SITE_BEIAN: {}
SITE_BEIAN: {},
})
const faviconFile = ref<FileItem>({ uid: '-1' })
const logoFile = ref<FileItem>({ uid: '-2' })
@@ -168,7 +178,7 @@ const handleCancel = () => {
}
const queryForm = reactive({
category: 'SITE'
category: 'SITE',
})
// 查询列表数据
const getDataList = async () => {
@@ -190,7 +200,7 @@ const handleSave = async () => {
await updateOption(
Object.entries(form).map(([key, value]) => {
return { id: siteConfig.value[key].id, code: key, value }
})
}),
)
appStore.setSiteConfig(form)
await getDataList()
@@ -210,7 +220,7 @@ const onResetValue = () => {
content: '确认恢复基础配置为默认值吗?',
hideCancel: false,
maskClosable: false,
onOk: handleResetValue
onOk: handleResetValue,
})
}
@@ -236,12 +246,12 @@ const handleUploadFavicon = (options: RequestOption) => {
return {
abort() {
controller.abort()
}
},
}
}
const handleChangeFavicon = (_: any, currentFile: any) => {
faviconFile.value = {
...currentFile
...currentFile,
}
}
@@ -267,12 +277,12 @@ const handleUploadLogo = (options: RequestOption) => {
return {
abort() {
controller.abort()
}
},
}
}
const handleChangeLogo = (_: any, currentFile: any) => {
logoFile.value = {
...currentFile
...currentFile,
}
}

View File

@@ -1,7 +1,9 @@
<template>
<a-space wrap :size="30">
<a-form ref="formRef" :model="form" :rules="rules" auto-label-width label-align="left"
:layout="width >= 500 ? 'horizontal' : 'vertical'" :disabled="!isUpdate" scroll-to-first-error>
<a-form
ref="formRef" :model="form" :rules="rules" auto-label-width label-align="left"
:layout="width >= 500 ? 'horizontal' : 'vertical'" :disabled="!isUpdate" scroll-to-first-error
>
<a-list :bordered="false" :loading="loading">
<a-form-item field="MAIL_PROTOCOL" :label="mailConfig.MAIL_PROTOCOL.name" hide-asterisk>
<a-select v-model.trim="form.MAIL_PROTOCOL">
@@ -26,8 +28,10 @@
<a-radio value="0">禁用</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item v-if="form.MAIL_SSL_ENABLED === '1'" field="MAIL_SSL_PORT" :label="mailConfig.MAIL_SSL_PORT.name"
hide-asterisk>
<a-form-item
v-if="form.MAIL_SSL_ENABLED === '1'" field="MAIL_SSL_PORT" :label="mailConfig.MAIL_SSL_PORT.name"
hide-asterisk
>
<a-input-number v-model="form.MAIL_SSL_PORT" :min="0" />
</a-form-item>
<a-space>
@@ -60,7 +64,7 @@ import {
type OptionResp,
listOption,
resetOptionValue,
updateOption
updateOption,
} from '@/apis/system'
import { useForm } from '@/hooks'
@@ -75,14 +79,14 @@ const { form } = useForm({
MAIL_USERNAME: '',
MAIL_PASSWORD: '',
MAIL_SSL_ENABLED: '',
MAIL_SSL_PORT: 0
MAIL_SSL_PORT: 0,
})
const rules: FormInstance['rules'] = {
MAIL_HOST: [{ required: true, message: '请输入值' }],
MAIL_PORT: [{ required: true, message: '请输入值' }],
MAIL_USERNAME: [{ required: true, message: '请输入值' }],
MAIL_PASSWORD: [{ required: true, message: '请输入值' }],
MAIL_SSL_PORT: [{ required: true, message: '请输入值' }]
MAIL_SSL_PORT: [{ required: true, message: '请输入值' }],
}
const mailConfig = ref<MailConfig>({
@@ -92,7 +96,7 @@ const mailConfig = ref<MailConfig>({
MAIL_USERNAME: {},
MAIL_PASSWORD: {},
MAIL_SSL_ENABLED: {},
MAIL_SSL_PORT: {}
MAIL_SSL_PORT: {},
})
// 重置
@@ -120,7 +124,7 @@ const handleCancel = () => {
}
const queryForm = {
category: 'MAIL'
category: 'MAIL',
}
// 查询列表数据
const getDataList = async () => {
@@ -141,7 +145,7 @@ const handleSave = async () => {
await updateOption(
Object.entries(form).map(([key, value]) => {
return { id: mailConfig.value[key].id, code: key, value }
})
}),
)
await getDataList()
Message.success('保存成功')
@@ -159,7 +163,7 @@ const onResetValue = () => {
content: '确认恢复邮件配置为默认值吗?',
hideCancel: false,
maskClosable: false,
onOk: handleResetValue
onOk: handleResetValue,
})
}

View File

@@ -1,50 +1,76 @@
<template>
<a-space wrap :size="30">
<a-form ref="formRef" :model="form" :rules="rules" auto-label-width label-align="left"
:layout="width >= 500 ? 'horizontal' : 'vertical'" :disabled="!isUpdate" scroll-to-first-error>
<a-form
ref="formRef" :model="form" :rules="rules" auto-label-width label-align="left"
:layout="width >= 500 ? 'horizontal' : 'vertical'" :disabled="!isUpdate" scroll-to-first-error
>
<a-list :bordered="false" :loading="loading">
<a-form-item field="PASSWORD_ERROR_LOCK_COUNT" :label="securityConfig.PASSWORD_ERROR_LOCK_COUNT.name"
:help="securityConfig.PASSWORD_ERROR_LOCK_COUNT.description" hide-asterisk>
<a-input-number v-model="form.PASSWORD_ERROR_LOCK_COUNT" class="input-width" :default-value="0" :precision="0"
:min="0" :max="10">
<a-form-item
field="PASSWORD_ERROR_LOCK_COUNT" :label="securityConfig.PASSWORD_ERROR_LOCK_COUNT.name"
:help="securityConfig.PASSWORD_ERROR_LOCK_COUNT.description" hide-asterisk
>
<a-input-number
v-model="form.PASSWORD_ERROR_LOCK_COUNT" class="input-width" :default-value="0" :precision="0"
:min="0" :max="10"
>
<template #append></template>
</a-input-number>
</a-form-item>
<a-form-item field="PASSWORD_ERROR_LOCK_MINUTES" :label="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.name"
:help="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.description" hide-asterisk>
<a-input-number v-model="form.PASSWORD_ERROR_LOCK_MINUTES" class="input-width" :precision="0" :min="1"
:max="1440">
<a-form-item
field="PASSWORD_ERROR_LOCK_MINUTES" :label="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.name"
:help="securityConfig.PASSWORD_ERROR_LOCK_MINUTES.description" hide-asterisk
>
<a-input-number
v-model="form.PASSWORD_ERROR_LOCK_MINUTES" class="input-width" :precision="0" :min="1"
:max="1440"
>
<template #append>分钟</template>
</a-input-number>
</a-form-item>
<a-form-item field="PASSWORD_EXPIRATION_DAYS" :label="securityConfig.PASSWORD_EXPIRATION_DAYS.name"
:help="securityConfig.PASSWORD_EXPIRATION_DAYS.description" hide-asterisk>
<a-input-number v-model="form.PASSWORD_EXPIRATION_DAYS" class="input-width" :precision="0" :min="0"
:max="999">
<a-form-item
field="PASSWORD_EXPIRATION_DAYS" :label="securityConfig.PASSWORD_EXPIRATION_DAYS.name"
:help="securityConfig.PASSWORD_EXPIRATION_DAYS.description" hide-asterisk
>
<a-input-number
v-model="form.PASSWORD_EXPIRATION_DAYS" class="input-width" :precision="0" :min="0"
:max="999"
>
<template #append></template>
</a-input-number>
</a-form-item>
<a-form-item :label="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.name"
<a-form-item
:label="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.name"
field="PASSWORD_EXPIRATION_WARNING_DAYS" :help="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.description"
hide-asterisk>
<a-input-number v-model="form.PASSWORD_EXPIRATION_WARNING_DAYS" class="input-width" :precision="0" :min="0"
:max="998">
hide-asterisk
>
<a-input-number
v-model="form.PASSWORD_EXPIRATION_WARNING_DAYS" class="input-width" :precision="0" :min="0"
:max="998"
>
<template #append></template>
</a-input-number>
</a-form-item>
<a-form-item field="PASSWORD_REPETITION_TIMES" :label="securityConfig.PASSWORD_REPETITION_TIMES.name"
:help="securityConfig.PASSWORD_REPETITION_TIMES.description" hide-asterisk>
<a-input-number v-model="form.PASSWORD_REPETITION_TIMES" class="input-width" :precision="0" :min="3"
:max="32">
<a-form-item
field="PASSWORD_REPETITION_TIMES" :label="securityConfig.PASSWORD_REPETITION_TIMES.name"
:help="securityConfig.PASSWORD_REPETITION_TIMES.description" hide-asterisk
>
<a-input-number
v-model="form.PASSWORD_REPETITION_TIMES" class="input-width" :precision="0" :min="3"
:max="32"
>
<template #append></template>
</a-input-number>
</a-form-item>
<a-form-item field="PASSWORD_MIN_LENGTH" :label="securityConfig.PASSWORD_MIN_LENGTH.name"
:help="securityConfig.PASSWORD_MIN_LENGTH.description" hide-asterisk>
<a-form-item
field="PASSWORD_MIN_LENGTH" :label="securityConfig.PASSWORD_MIN_LENGTH.name"
:help="securityConfig.PASSWORD_MIN_LENGTH.description" hide-asterisk
>
<a-input-number v-model="form.PASSWORD_MIN_LENGTH" class="input-width" :precision="0" :min="8" :max="32" />
</a-form-item>
<a-form-item field="PASSWORD_ALLOW_CONTAIN_USERNAME"
:label="securityConfig.PASSWORD_ALLOW_CONTAIN_USERNAME.name">
<a-form-item
field="PASSWORD_ALLOW_CONTAIN_USERNAME"
:label="securityConfig.PASSWORD_ALLOW_CONTAIN_USERNAME.name"
>
<a-switch v-model="form.PASSWORD_ALLOW_CONTAIN_USERNAME" type="round" :checked-value="1" :unchecked-value="0">
<template #checked></template>
<template #unchecked></template>
@@ -97,7 +123,7 @@ const { form } = useForm({
PASSWORD_REPETITION_TIMES: 0,
PASSWORD_MIN_LENGTH: 0,
PASSWORD_ALLOW_CONTAIN_USERNAME: 0,
PASSWORD_REQUIRE_SYMBOLS: 0
PASSWORD_REQUIRE_SYMBOLS: 0,
})
const rules: FormInstance['rules'] = {
PASSWORD_ERROR_LOCK_COUNT: [{ required: true, message: '请输入值' }],
@@ -112,11 +138,11 @@ const rules: FormInstance['rules'] = {
} else {
callback()
}
}
}
},
},
],
PASSWORD_REPETITION_TIMES: [{ required: true, message: '请输入值' }],
PASSWORD_MIN_LENGTH: [{ required: true, message: '请输入值' }]
PASSWORD_MIN_LENGTH: [{ required: true, message: '请输入值' }],
}
const securityConfig = ref<SecurityConfig>({
@@ -127,7 +153,7 @@ const securityConfig = ref<SecurityConfig>({
PASSWORD_REPETITION_TIMES: {},
PASSWORD_MIN_LENGTH: {},
PASSWORD_ALLOW_CONTAIN_USERNAME: {},
PASSWORD_REQUIRE_SYMBOLS: {}
PASSWORD_REQUIRE_SYMBOLS: {},
})
// 重置
const reset = () => {
@@ -155,7 +181,7 @@ const handleCancel = () => {
}
const queryForm = {
category: 'PASSWORD'
category: 'PASSWORD',
}
// 查询列表数据
const getDataList = async () => {
@@ -176,7 +202,7 @@ const handleSave = async () => {
await updateOption(
Object.entries(form).map(([key, value]) => {
return { id: securityConfig.value[key].id, code: key, value }
})
}),
)
await getDataList()
Message.success('保存成功')
@@ -194,7 +220,7 @@ const onResetValue = () => {
content: '确认恢复安全配置为默认值吗?',
hideCancel: false,
maskClosable: false,
onOk: handleResetValue
onOk: handleResetValue,
})
}

View File

@@ -41,7 +41,7 @@ watch(
activeKey.value = String(route.query.tabKey)
}
},
{ immediate: true }
{ immediate: true },
)
const change = (key: string | number) => {
activeKey.value = key as string

View File

@@ -34,7 +34,7 @@ const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = {
form: { size: 'large' },
btns: { hide: true }
btns: { hide: true },
}
const columns: Columns = reactive([
@@ -55,9 +55,9 @@ const columns: Columns = reactive([
return nodeData.title.toLowerCase().includes(searchKey.toLowerCase())
}
return false
}
},
},
rules: [{ required: true, message: '请选择上级部门' }]
rules: [{ required: true, message: '请选择上级部门' }],
},
{
label: '名称',
@@ -65,8 +65,8 @@ const columns: Columns = reactive([
type: 'input',
rules: [{ required: true, message: '请输入名称' }],
props: {
maxLength: 30
}
maxLength: 30,
},
},
{
label: '排序',
@@ -74,8 +74,8 @@ const columns: Columns = reactive([
type: 'input-number',
props: {
min: 1,
mode: 'button'
}
mode: 'button',
},
},
{
label: '描述',
@@ -83,8 +83,8 @@ const columns: Columns = reactive([
type: 'textarea',
props: {
maxLength: 200,
autoSize: { minRows: 3, maxRows: 5 }
}
autoSize: { minRows: 3, maxRows: 5 },
},
},
{
label: '状态',
@@ -95,14 +95,14 @@ const columns: Columns = reactive([
checkedValue: 1,
uncheckedValue: 2,
checkedText: '启用',
uncheckedText: '禁用'
}
}
uncheckedText: '禁用',
},
},
])
const { form, resetForm } = useForm({
sort: 999,
status: 1
status: 1,
})
// 重置

View File

@@ -81,14 +81,14 @@ const {
tableData,
loading,
search,
handleDelete
handleDelete,
} = useTable(() => listDept(queryForm), {
immediate: true,
onSuccess: () => {
nextTick(() => {
tableRef.value?.tableRef?.expandAll(true)
})
}
},
})
// 过滤树
@@ -104,7 +104,7 @@ const searchData = (name: string) => {
if (filterData.length) {
result.push({
...item,
children: filterData
children: filterData,
})
}
}
@@ -135,8 +135,8 @@ const columns: TableInstanceColumns[] = [
width: 180,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:dept:update', 'system:dept:delete', 'system:dept:add'])
}
show: has.hasPermOr(['system:dept:update', 'system:dept:delete', 'system:dept:add']),
},
]
// 重置
@@ -148,7 +148,7 @@ const reset = () => {
const onDelete = (record: DeptResp) => {
return handleDelete(() => deleteDept(record.id), {
content: `是否确定删除 [${record.name}]`,
showModal: true
showModal: true,
})
}

View File

@@ -39,7 +39,7 @@ const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = {
form: { size: 'large' },
btns: { hide: true }
btns: { hide: true },
}
const columns: Columns = reactive([
@@ -52,8 +52,8 @@ const columns: Columns = reactive([
type: 'input-number',
props: {
min: 1,
mode: 'button'
}
mode: 'button',
},
},
{
label: '描述',
@@ -61,8 +61,8 @@ const columns: Columns = reactive([
type: 'textarea',
props: {
maxLength: 200,
autoSize: { minRows: 3, maxRows: 5 }
}
autoSize: { minRows: 3, maxRows: 5 },
},
},
{
label: '状态',
@@ -73,15 +73,15 @@ const columns: Columns = reactive([
checkedValue: 1,
uncheckedValue: 2,
checkedText: '启用',
uncheckedText: '禁用'
}
}
uncheckedText: '禁用',
},
},
])
const { form, resetForm } = useForm({
color: 'blue',
sort: 999,
status: 1
status: 1,
})
// 重置

View File

@@ -46,9 +46,9 @@
<a-space>
<a-link v-permission="['system:dict:item:update']" @click="onUpdate(record)">修改</a-link>
<a-link
v-permission="['system:dict:item:delete']"
status="danger"
@click="onDelete(record)"
v-permission="['system:dict:item:delete']"
status="danger"
@click="onDelete(record)"
>
删除
</a-link>
@@ -75,7 +75,7 @@ defineOptions({ name: 'SystemDict' })
const queryForm = reactive<DictItemQuery>({
dictId: '',
sort: ['createTime,desc']
sort: ['createTime,desc'],
})
const {
@@ -83,7 +83,7 @@ const {
loading,
pagination,
search,
handleDelete
handleDelete,
} = useTable((page) => listDictItem({ ...queryForm, ...page }), { immediate: false })
const columns: TableInstanceColumns[] = [
@@ -91,7 +91,7 @@ const columns: TableInstanceColumns[] = [
title: '序号',
width: 66,
align: 'center',
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize)
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
},
{ title: '标签', dataIndex: 'label', slotName: 'label', width: 100, align: 'center' },
{ title: '值', dataIndex: 'value', width: 100, align: 'center', ellipsis: true, tooltip: true },
@@ -102,8 +102,8 @@ const columns: TableInstanceColumns[] = [
width: 90,
align: 'center',
sortable: {
sortDirections: ['ascend', 'descend']
}
sortDirections: ['ascend', 'descend'],
},
},
{ title: '描述', dataIndex: 'description', width: 130, ellipsis: true, tooltip: true },
{ title: '创建人', dataIndex: 'createUserString', width: 140, ellipsis: true, tooltip: true, show: false },
@@ -116,8 +116,8 @@ const columns: TableInstanceColumns[] = [
width: 130,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:dict:item:update', 'system:dict:item:delete'])
}
show: has.hasPermOr(['system:dict:item:update', 'system:dict:item:delete']),
},
]
// 重置

View File

@@ -30,7 +30,7 @@ const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = {
form: { size: 'large' },
btns: { hide: true }
btns: { hide: true },
}
const columns: Columns = reactive([
@@ -42,9 +42,9 @@ const columns: Columns = reactive([
type: 'textarea',
props: {
maxLength: 200,
autoSize: { minRows: 3, maxRows: 5 }
}
}
autoSize: { minRows: 3, maxRows: 5 },
},
},
])
const { form, resetForm } = useForm({})

View File

@@ -57,7 +57,7 @@ interface Props {
placeholder?: string
}
const props = withDefaults(defineProps<Props>(), {
placeholder: '请输入关键词'
placeholder: '请输入关键词',
})
const emit = defineEmits<{
(e: 'node-click', keys: Array<any>): void
@@ -74,7 +74,7 @@ const select = (keys: Array<any>) => {
}
const queryForm = reactive<DictQuery>({
sort: ['createTime,asc']
sort: ['createTime,asc'],
})
interface TreeItem extends DictResp {
@@ -92,7 +92,7 @@ const getTreeData = async (query: DictQuery = { ...queryForm }) => {
popupVisible: false,
icon: () => {
return null
}
},
}))
await nextTick(() => {
select([treeData.value[0]?.id])
@@ -136,7 +136,7 @@ const onMenuItemClick = (mode: string, node: DictResp) => {
} catch (error) {
return false
}
}
},
})
}
}

View File

@@ -51,7 +51,7 @@ if (obj && obj.top && obj.left) {
axis.value.left = obj.left
}
const { x, y } = useDraggable(audioRef, {
initialValue: { x: axis.value.left - boxWidth.value, y: axis.value.top }
initialValue: { x: axis.value.left - boxWidth.value, y: axis.value.top },
})
const audioStyle = computed(() => {
@@ -72,7 +72,7 @@ const audioStyle = computed(() => {
sessionStorage.setItem('AudioDialogXY', JSON.stringify({ top, left }))
return {
left: `${left}px`,
top: `${top}px`
top: `${top}px`,
}
})

View File

@@ -20,14 +20,14 @@ function createModal<T extends { callback?: () => void }>(component: Component,
document.body.removeChild(el)
options?.callback && options?.callback()
}, 350)
}
},
})
instance.use(ArcoVue)
instance.use(ArcoVueIcon)
instance.mount(el)
}
type TFileOptions = { data: FileItem, callback?: () => void }
interface TFileOptions { data: FileItem, callback?: () => void }
/** 预览 音频文件 弹窗 */
let fileAudioId = ''
@@ -39,6 +39,6 @@ export function previewFileAudioModal(data: FileItem) {
// 关闭的回调
callback: () => {
fileAudioId = ''
}
},
})
}

View File

@@ -12,6 +12,6 @@ export function openFileDetailModal(fileItem: FileItem) {
modalStyle: { maxWidth: '320px' },
width: '90%',
footer: false,
content: () => h(ModalContent, { data: fileItem })
content: () => h(ModalContent, { data: fileItem }),
})
}

View File

@@ -24,7 +24,7 @@ const props = withDefaults(defineProps<Props>(), {})
const formRef = ref<FormInstance>()
const form = reactive({
name: props.data?.name || ''
name: props.data?.name || '',
})
defineExpose({ formRef })

View File

@@ -15,7 +15,7 @@ export function openFileRenameModal(data: FileItem, callback?: () => void) {
data,
ref: (e) => {
ModalContentRef.value = e as any
}
},
}),
onBeforeOk: async () => {
const isInvalid = await ModalContentRef.value?.formRef?.validate()
@@ -27,6 +27,6 @@ export function openFileRenameModal(data: FileItem, callback?: () => void) {
callback()
}
return true
}
},
})
}

View File

@@ -18,7 +18,7 @@ onMounted(() => {
lang: 'zh-cn',
autoplay: true,
closeVideoClick: true,
videoInit: true
videoInit: true,
})
})
</script>

View File

@@ -8,6 +8,6 @@ export function previewFileVideoModal(data: FileItem) {
title: '视频播放',
width: 'auto',
modalStyle: {},
content: () => h(ModalContent, { data })
content: () => h(ModalContent, { data }),
})
}

View File

@@ -36,8 +36,8 @@ watch(
selectedKey.value = route.query.type as string || '0'
},
{
immediate: true
}
immediate: true,
},
)
// 点击事件

View File

@@ -34,7 +34,7 @@ const totalData = ref<FileStatisticsResp>({
size: 0,
number: 0,
unit: '',
data: []
data: [],
})
const chartData = ref<Array<{ name: string, value: number, size: string }>>([])
const statisticValueStyle = { 'color': '#5856D6', 'font-size': '18px' }
@@ -44,7 +44,7 @@ const { option } = useChart(() => {
left: 0,
right: 0,
top: 0,
bottom: 0
bottom: 0,
},
legend: {
show: true,
@@ -53,14 +53,14 @@ const { option } = useChart(() => {
itemWidth: 6,
itemHeight: 6,
textStyle: {
color: '#4E5969'
}
color: '#4E5969',
},
},
tooltip: {
show: true,
formatter(params) {
return `总计:${params.value}<br>${params.data.size}`
}
},
},
series: [
{
@@ -69,11 +69,11 @@ const { option } = useChart(() => {
avoidLabelOverlap: true,
label: {
show: false,
position: 'center'
position: 'center',
},
data: chartData.value
}
]
data: chartData.value,
},
],
}
})
@@ -89,14 +89,14 @@ const getStatisticsData = async () => {
size: Number.parseFloat(formatSize[0]),
number: resData.number ?? 0,
unit: formatSize[1],
data: []
data: [],
}
resData.data?.forEach((fs: FileStatisticsResp) => {
const matchedItem = FileTypeList.find((item) => item.value === fs.type)
chartData.value.unshift({
name: matchedItem ? matchedItem.name : '',
value: fs.number,
size: formatFileSize(fs.size)
size: formatFileSize(fs.size),
})
})
} finally {

View File

@@ -53,7 +53,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
data: () => [], // 文件数据
selectedFileIds: () => [], // 批量模式下选中的文件id数组
isBatchMode: false // 是否是批量模式
isBatchMode: false, // 是否是批量模式
})
const emit = defineEmits<{

View File

@@ -26,7 +26,7 @@ const getFileImg = computed<string>(() => {
return props.data.url || ''
}
if (!Object.keys(FileIcon).includes(extension)) {
return FileIcon['other']
return FileIcon.other
}
return FileIcon[extension]
})

View File

@@ -79,7 +79,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
data: () => [], // 文件数据
selectedFileIds: () => [],
isBatchMode: false // 是否是批量模式
isBatchMode: false, // 是否是批量模式
})
const emit = defineEmits<{
@@ -95,7 +95,7 @@ const getFileName = (item: FileItem) => {
const rowSelection: TableRowSelection = reactive({
type: 'checkbox',
showCheckedAll: true
showCheckedAll: true,
})
// 多选

View File

@@ -18,7 +18,7 @@ interface Props {
}
const props = withDefaults(defineProps<Props>(), {
shadow: true
shadow: true,
})
const emit = defineEmits<{

View File

@@ -17,8 +17,10 @@
</a-dropdown>
<a-input-group>
<a-input v-model="queryForm.name" placeholder="请输入文件名" allow-clear style="width: 200px"
@change="search" />
<a-input
v-model="queryForm.name" placeholder="请输入文件名" allow-clear style="width: 200px"
@change="search"
/>
<a-button type="primary" @click="search">
<template #icon>
<icon-search />
@@ -30,8 +32,10 @@
<!-- 右侧区域 -->
<a-space wrap>
<a-button v-if="isBatchMode" :disabled="!selectedFileIds.length" type="primary" status="danger"
@click="handleMulDelete">
<a-button
v-if="isBatchMode" :disabled="!selectedFileIds.length" type="primary" status="danger"
@click="handleMulDelete"
>
<template #icon>
<icon-delete />
</template>
@@ -57,14 +61,18 @@
<!-- 文件列表-宫格模式 -->
<a-spin id="fileMain" class="file-main__list" :loading="loading">
<FileGrid v-show="fileList.length && mode === 'grid'" :data="fileList" :is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
@right-menu-click="handleRightMenuClick"></FileGrid>
<FileGrid
v-show="fileList.length && mode === 'grid'" :data="fileList" :is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
@right-menu-click="handleRightMenuClick"
></FileGrid>
<!-- 文件列表-列表模式 -->
<FileList v-show="fileList.length && mode === 'list'" :data="fileList" :is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
@right-menu-click="handleRightMenuClick"></FileList>
<FileList
v-show="fileList.length && mode === 'list'" :data="fileList" :is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds" @click="handleClickFile" @select="handleSelectFile"
@right-menu-click="handleRightMenuClick"
></FileList>
<a-empty v-if="!fileList.length" />
</a-spin>
@@ -82,7 +90,7 @@ import {
openFileDetailModal,
openFileRenameModal,
previewFileAudioModal,
previewFileVideoModal
previewFileVideoModal,
} from '../../components/index'
import FileGrid from './FileGrid.vue'
import useFileManage from './useFileManage'
@@ -101,18 +109,18 @@ const { mode, selectedFileIds, toggleMode, addSelectedFileItem } = useFileManage
const queryForm = reactive<FileQuery>({
name: undefined,
type: route.query.type?.toString() !== '0' ? route.query.type?.toString() : undefined,
sort: ['updateTime,desc']
sort: ['updateTime,desc'],
})
const paginationOption = reactive({
defaultPageSize: 30,
defaultSizeOptions: [30, 40, 50, 100, 120]
defaultSizeOptions: [30, 40, 50, 100, 120],
})
const isBatchMode = ref(false)
const {
tableData: fileList,
loading,
pagination,
search
search,
} = useTable((page) => listFile({ ...queryForm, ...page }), { immediate: false, paginationOption })
const filePreviewRef = ref()
// 点击文件
@@ -124,9 +132,9 @@ const handleClickFile = (item: FileItem) => {
if (imgList.length) {
viewerApi({
options: {
initialViewIndex: index
initialViewIndex: index,
},
images: imgList
images: imgList,
})
}
}
@@ -143,11 +151,11 @@ const handleClickFile = (item: FileItem) => {
},
transformData: (workbookData) => {
return workbookData
}
},
}
filePreviewRef.value.onPreview({
fileInfo: { data: item.url, fileName: item.name, fileType: item.extension },
excelConfig
excelConfig,
})
}
if (item.extension === 'mp4') {
@@ -162,7 +170,7 @@ const onDownload = async (fileInfo: FileItem) => {
const res = await downloadByUrl({
url: fileInfo.url,
target: '_self',
fileName: `${fileInfo.name}.${fileInfo.extension}`
fileName: `${fileInfo.name}.${fileInfo.extension}`,
})
res ? Message.success('下载成功') : Message.error('下载失败')
search()
@@ -180,7 +188,7 @@ const handleRightMenuClick = async (mode: string, fileInfo: FileItem) => {
await deleteFile(fileInfo.id)
Message.success('删除成功')
search()
}
},
})
} else if (mode === 'rename') {
openFileRenameModal(fileInfo, search)
@@ -206,7 +214,7 @@ const handleMulDelete = () => {
await deleteFile(selectedFileIds.value)
Message.success('删除成功')
search()
}
},
})
}
@@ -230,7 +238,7 @@ const handleUpload = (options: RequestOption) => {
return {
abort() {
controller.abort()
}
},
}
}

View File

@@ -28,6 +28,6 @@ export default function () {
selectedFileList,
selectedFileIds,
toggleMode,
addSelectedFileItem
addSelectedFileItem,
}
}

View File

@@ -127,7 +127,7 @@ interface Props {
menus: MenuResp[]
}
const props = withDefaults(defineProps<Props>(), {
menus: () => []
menus: () => [],
})
const emit = defineEmits<{
@@ -141,7 +141,7 @@ const menuSelectTree = computed(() => {
return mapTree(data, (i) => ({
key: i.id,
title: i.title,
children: i.children
children: i.children,
}))
})
@@ -164,7 +164,7 @@ const rules: FormInstance['rules'] = {
path: [{ required: true, message: '请输入路由地址' }],
name: [{ required: true, message: '请输入组件名称' }],
component: [{ required: true, message: '请输入组件路径' }],
permission: [{ required: true, message: '请输入权限标识' }]
permission: [{ required: true, message: '请输入权限标识' }],
}
const { form, resetForm } = useForm({
@@ -173,7 +173,7 @@ const { form, resetForm } = useForm({
isExternal: false,
isCache: false,
isHidden: false,
status: 1
status: 1,
})
const componentName = computed(() => transformPathToName(form.path))
// eslint-disable-next-line vue/return-in-computed-property

View File

@@ -94,7 +94,7 @@ const {
tableData,
loading,
search,
handleDelete
handleDelete,
} = useTable(() => listMenu(queryForm), { immediate: true })
// 过滤树
@@ -110,7 +110,7 @@ const searchData = (title: string) => {
if (filterData.length) {
result.push({
...item,
children: filterData
children: filterData,
})
}
}
@@ -147,8 +147,8 @@ const columns: TableInstanceColumns[] = [
width: 180,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:menu:update', 'system:menu:delete', 'system:menu:add'])
}
show: has.hasPermOr(['system:menu:update', 'system:menu:delete', 'system:menu:add']),
},
]
// 重置
@@ -160,7 +160,7 @@ const reset = () => {
const onDelete = (record: MenuResp) => {
return handleDelete(() => deleteMenu(record.id), {
content: `是否确定删除 [${record.title}]`,
showModal: true
showModal: true,
})
}

View File

@@ -34,7 +34,7 @@ const editorConfig = reactive<AiEditorOptions>({
theme: appStore.theme,
placeholder: '请输入内容',
content: '',
editable: false
editable: false,
})
const init = () => {
aieditor.value?.destroy()

View File

@@ -1,25 +1,25 @@
<!-- 未完善 -->
<template>
<div ref="divRef" class="container">
<div class="aie-container">
<div class="aie-header-panel">
<div class="aie-container-header"></div>
<div ref="divRef" class="container">
<div class="aie-container">
<div class="aie-header-panel">
<div class="aie-container-header"></div>
</div>
<div class="aie-main">
<div class="aie-directory-content">
<div class="aie-directory">
<h5>目录</h5>
<div id="outline">
</div>
<div class="aie-main">
<div class="aie-directory-content">
<div class="aie-directory">
<h5>目录</h5>
<div id="outline">
</div>
</div>
</div>
<div class="aie-container-panel">
<div class="aie-container-main"></div>
</div>
</div>
<div class="aie-container-footer"></div>
</div>
</div>
<div class="aie-container-panel">
<div class="aie-container-main"></div>
</div>
</div>
<div class="aie-container-footer"></div>
</div>
</div>
</template>
<script setup lang="ts">
@@ -72,7 +72,7 @@ const editorConfig = reactive<AiEditorOptions>({
},
onCreated: (editor: AiEditor) => {
updateOutLine(editor)
}
},
})
watch(() => props.modelValue, (value) => {
if (value !== aieditor.value?.getHtml()) {

View File

@@ -45,7 +45,7 @@
css: true,
}"
>
{{ record.title }}
{{ record.title }}
</a-typography-paragraph>
</a-link>
</template>
@@ -79,7 +79,7 @@ const { notice_type, notice_status_enum } = useDict('notice_type', 'notice_statu
const router = useRouter()
const queryForm = reactive<NoticeQuery>({
sort: ['createTime,desc']
sort: ['createTime,desc'],
})
const {
@@ -87,7 +87,7 @@ const {
loading,
pagination,
search,
handleDelete
handleDelete,
} = useTable((page) => listNotice({ ...queryForm, ...page }), { immediate: true })
const columns: TableInstanceColumns[] = [
@@ -95,7 +95,7 @@ const columns: TableInstanceColumns[] = [
title: '序号',
width: 66,
align: 'center',
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize)
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
},
{ title: '标题', dataIndex: 'title', slotName: 'title', width: 200, ellipsis: true, tooltip: true },
{ title: '类型', slotName: 'type', align: 'center' },
@@ -110,8 +110,8 @@ const columns: TableInstanceColumns[] = [
width: 130,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:notice:update', 'system:notice:delete'])
}
show: has.hasPermOr(['system:notice:update', 'system:notice:delete']),
},
]
// 重置
@@ -125,7 +125,7 @@ const reset = () => {
const onDelete = (record: NoticeResp) => {
return handleDelete(() => deleteNotice(record.id), {
content: `是否确定删除公告 [${record.title}]`,
showModal: true
showModal: true,
})
}

View File

@@ -51,12 +51,12 @@ const { form, resetForm } = useForm({
effectiveTime: '',
terminateTime: '',
content: '',
noticeScope: 1
noticeScope: 1,
})
const options: Options = {
form: { size: 'large' },
grid: { cols: 2 },
btns: { hide: true }
btns: { hide: true },
}
const columns: Columns = reactive([
@@ -66,24 +66,24 @@ const columns: Columns = reactive([
type: 'input',
props: {
maxLength: 150,
showWordLimit: true
showWordLimit: true,
},
rules: [{ required: true, message: '请输入标题' }]
rules: [{ required: true, message: '请输入标题' }],
},
{
label: '类型',
field: 'type',
type: 'select',
options: notice_type,
rules: [{ required: true, message: '请输入类型' }]
rules: [{ required: true, message: '请输入类型' }],
},
{
label: '生效时间',
field: 'effectiveTime',
type: 'date-picker',
props: {
showTime: true
}
showTime: true,
},
},
{
@@ -91,15 +91,15 @@ const columns: Columns = reactive([
field: 'terminateTime',
type: 'date-picker',
props: {
showTime: true
}
showTime: true,
},
},
{
label: '通知范围',
field: 'noticeScope',
type: 'radio-group',
options: [{ label: '所有人', value: 1 }, { label: '指定用户', value: 2 }],
rules: [{ required: true, message: '请选择通知范围' }]
rules: [{ required: true, message: '请选择通知范围' }],
},
{
label: '指定用户',
@@ -108,8 +108,8 @@ const columns: Columns = reactive([
hide: () => {
return form.noticeScope === 1
},
rules: [{ required: true, message: '请选择指定用户' }]
}
rules: [{ required: true, message: '请选择指定用户' }],
},
])
// 修改

View File

@@ -1,40 +1,40 @@
<template>
<div ref="containerRef" class="detail">
<div class="detail_header">
<a-affix :target="(containerRef as HTMLElement)">
<a-page-header title="通知公告" subtitle="查看" @back="onBack">
</a-page-header>
</a-affix>
</div>
<div class="detail_content">
<h1 class="title">{{ form?.title }}</h1>
<div class="info">
<a-space>
<span>
<icon-user class="icon" />
<span class="label">发布人</span>
<span>{{ form?.createUserString }}</span>
</span>
<a-divider direction="vertical" />
<span>
<icon-history class="icon" />
<span class="label">发布时间</span>
<span>{{ form?.effectiveTime ? form?.effectiveTime : form?.createTime
}}</span>
</span>
<a-divider v-if="form?.updateTime" direction="vertical" />
<span v-if="form?.updateTime">
<icon-schedule class="icon" />
<span>更新时间</span>
<span>{{ form?.updateTime }}</span>
</span>
</a-space>
</div>
<div style="flex: 1;">
<AiEditor v-model="form.content" />
</div>
</div>
<div ref="containerRef" class="detail">
<div class="detail_header">
<a-affix :target="(containerRef as HTMLElement)">
<a-page-header title="通知公告" subtitle="查看" @back="onBack">
</a-page-header>
</a-affix>
</div>
<div class="detail_content">
<h1 class="title">{{ form?.title }}</h1>
<div class="info">
<a-space>
<span>
<icon-user class="icon" />
<span class="label">发布人</span>
<span>{{ form?.createUserString }}</span>
</span>
<a-divider direction="vertical" />
<span>
<icon-history class="icon" />
<span class="label">发布时间</span>
<span>{{ form?.effectiveTime ? form?.effectiveTime : form?.createTime
}}</span>
</span>
<a-divider v-if="form?.updateTime" direction="vertical" />
<span v-if="form?.updateTime">
<icon-schedule class="icon" />
<span>更新时间</span>
<span>{{ form?.updateTime }}</span>
</span>
</a-space>
</div>
<div style="flex: 1;">
<AiEditor v-model="form.content" />
</div>
</div>
</div>
</template>
<script setup lang="tsx">
@@ -52,7 +52,7 @@ const { form, resetForm } = useForm({
createUserString: '',
effectiveTime: '',
createTime: '',
content: ''
content: '',
})
// 修改

View File

@@ -1,11 +1,11 @@
<template>
<a-modal
v-model:visible="visible"
:title="title"
:mask-closable="false"
:esc-to-close="true"
:width="width >= 600 ? 600 : '100%'"
@close="reset"
v-model:visible="visible"
:title="title"
:mask-closable="false"
:esc-to-close="true"
:width="width >= 600 ? 600 : '100%'"
@close="reset"
>
<a-steps :current="current" class="mb-15" @change="onChangeCurrent">
<a-step>基础信息</a-step>
@@ -26,11 +26,11 @@
</a-form-item>
<a-form-item label="描述" field="description">
<a-textarea
v-model.trim="form.description"
placeholder="请输入描述"
show-word-limit
:max-length="200"
:auto-size="{ minRows: 3, maxRows: 5 }"
v-model.trim="form.description"
placeholder="请输入描述"
show-word-limit
:max-length="200"
:auto-size="{ minRows: 3, maxRows: 5 }"
/>
</a-form-item>
</fieldset>
@@ -43,14 +43,14 @@
</a-space>
<template #extra>
<a-tree
ref="menuTreeRef"
v-model:checked-keys="form.menuIds"
class="w-full"
:data="menuList"
:default-expand-all="isMenuExpanded"
:check-strictly="!form.menuCheckStrictly"
:virtual-list-props="{ height: 400 }"
checkable
ref="menuTreeRef"
v-model:checked-keys="form.menuIds"
class="w-full"
:data="menuList"
:default-expand-all="isMenuExpanded"
:check-strictly="!form.menuCheckStrictly"
:virtual-list-props="{ height: 400 }"
checkable
/>
</template>
</a-form-item>
@@ -58,10 +58,10 @@
<fieldset v-show="current === 3">
<a-form-item hide-label field="dataScope">
<a-select
v-model.trim="form.dataScope"
:options="data_scope_enum"
placeholder="请选择数据权限"
:disabled="form.isSystem"
v-model.trim="form.dataScope"
:options="data_scope_enum"
placeholder="请选择数据权限"
:disabled="form.isSystem"
/>
</a-form-item>
<a-form-item v-if="form.dataScope === 5" hide-label :disabled="form.isSystem">
@@ -72,14 +72,14 @@
</a-space>
<template #extra>
<a-tree
ref="deptTreeRef"
v-model:checked-keys="form.deptIds"
class="w-full"
:data="deptList"
:default-expand-all="isDeptExpanded"
:check-strictly="!form.deptCheckStrictly"
:virtual-list-props="{ height: 350 }"
checkable
ref="deptTreeRef"
v-model:checked-keys="form.deptIds"
class="w-full"
:data="deptList"
:default-expand-all="isDeptExpanded"
:check-strictly="!form.deptCheckStrictly"
:virtual-list-props="{ height: 350 }"
checkable
/>
</template>
</a-form-item>
@@ -124,14 +124,14 @@ const formRef = ref<FormInstance>()
const rules: FormInstance['rules'] = {
name: [{ required: true, message: '请输入名称' }],
code: [{ required: true, message: '请输入编码' }],
dataScope: [{ required: true, message: '请选择数据权限' }]
dataScope: [{ required: true, message: '请选择数据权限' }],
}
const { form, resetForm } = useForm({
menuCheckStrictly: true,
deptCheckStrictly: true,
sort: 999,
dataScope: 4
dataScope: 4,
})
const menuTreeRef = ref()
@@ -209,7 +209,7 @@ const getMenuAllCheckedKeys = () => {
// 获取半选中的菜单
const halfCheckedNodes = menuTreeRef.value?.getHalfCheckedNodes()
const halfCheckedKeys = halfCheckedNodes.map((item: TreeNodeData) => item.key)
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
checkedKeys.unshift(...halfCheckedKeys)
return checkedKeys
}
@@ -224,8 +224,7 @@ const getDeptAllCheckedKeys = () => {
// 获取半选中的部门
const halfCheckedNodes = deptTreeRef.value?.getHalfCheckedNodes()
const halfCheckedKeys = halfCheckedNodes.map((item: TreeNodeData) => item.key)
// eslint-disable-next-line prefer-spread
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
checkedKeys.unshift(...halfCheckedKeys)
return checkedKeys
}
@@ -253,7 +252,7 @@ const save = async () => {
const handleTreeAction = (type, action) => {
const refMap = {
menu: menuTreeRef,
dept: deptTreeRef
dept: deptTreeRef,
}
const ref = refMap[type]
if (ref && action === 'expand') {

View File

@@ -103,14 +103,14 @@ const formRef = ref<FormInstance>()
const rules: FormInstance['rules'] = {
name: [{ required: true, message: '请输入名称' }],
code: [{ required: true, message: '请输入编码' }],
dataScope: [{ required: true, message: '请选择数据权限' }]
dataScope: [{ required: true, message: '请选择数据权限' }],
}
const { form, resetForm } = useForm({
menuCheckStrictly: true,
deptCheckStrictly: true,
sort: 999,
dataScope: 4
dataScope: 4,
})
const menuTreeRef = ref()
@@ -180,8 +180,7 @@ const getMenuAllCheckedKeys = () => {
// 获取半选中的菜单
const halfCheckedNodes = menuTreeRef.value?.getHalfCheckedNodes()
const halfCheckedKeys = halfCheckedNodes.map((item: TreeNodeData) => item.key)
// eslint-disable-next-line prefer-spread
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
checkedKeys.unshift(...halfCheckedKeys)
return checkedKeys
}
@@ -196,8 +195,7 @@ const getDeptAllCheckedKeys = () => {
// 获取半选中的部门
const halfCheckedNodes = deptTreeRef.value?.getHalfCheckedNodes()
const halfCheckedKeys = halfCheckedNodes.map((item: TreeNodeData) => item.key)
// eslint-disable-next-line prefer-spread
checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
checkedKeys.unshift(...halfCheckedKeys)
return checkedKeys
}

View File

@@ -1,116 +1,113 @@
<template>
<a-modal
v-model:visible="visible"
title="关联用户"
:mask-closable="false"
:esc-to-close="false"
:modal-style="{ maxWidth: '625px' }"
:body-style="{ maxHeight: '70vh' }"
width="90%"
draggable
@before-ok="save"
@close="close"
>
<a-transfer :data="transferData" :model-value="values" :title="['未选择','已选择']" @change="handleChange">
<template #source="{ data, selectedKeys, onSelect }">
<a-tree
size="medium"
:checkable="true"
checked-strategy="child"
:checked-keys="selectedKeys"
:data="getTreeData()"
@check="(keys) => onSelect(keys)"
/>
</template>
</a-transfer>
</a-modal>
</template>
<template>
<a-modal
v-model:visible="visible"
title="关联用户"
:mask-closable="false"
:esc-to-close="false"
:modal-style="{ maxWidth: '625px' }"
:body-style="{ maxHeight: '70vh' }"
width="90%"
draggable
@before-ok="save"
@close="close"
>
<a-transfer :data="transferData" :model-value="values" :title="['未选择', '已选择']" @change="handleChange">
<template #source="{ selectedKeys, onSelect }">
<a-tree
size="medium"
:checkable="true"
checked-strategy="child"
:checked-keys="selectedKeys"
:data="getTreeData()"
@check="(keys) => onSelect(keys)"
/>
</template>
</a-transfer>
</a-modal>
</template>
<script lang="ts" setup>
import { bindUsers, listDeptWithUsersTree, listRoleUsers } from '@/apis';
import { ref } from 'vue';
import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface';
import { Message, type TreeNodeData } from '@arco-design/web-vue';
<script lang="ts" setup>
import { ref } from 'vue'
import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface'
import { Message, type TreeNodeData } from '@arco-design/web-vue'
import { bindUsers, listDeptWithUsersTree, listRoleUsers } from '@/apis'
const visible = ref(false);
const roleId = ref('');
const treeData = ref<TreeNodeData[]>([]);
const transferData = ref<TransferItem[]>([]);
const values = ref<string[]>(['']);
const close = () => {
visible.value = false;
};
const visible = ref(false)
const roleId = ref('')
const treeData = ref<TreeNodeData[]>([])
const transferData = ref<TransferItem[]>([])
const values = ref<string[]>([''])
const close = () => {
visible.value = false
}
const save = async () => {
const newValues = values.value.map((item) => item.replace('user_', ''));
const res = await bindUsers(roleId.value, newValues);
if (res.success) {
Message.success('修改成功')
visible.value = false;
return false;
}else{
Message.error(res.msg)
}
};
const handleChange = (value: string[]) => {
values.value = value
const newValues = values.value.map((item) => item.replace('user_', ''))
const res = await bindUsers(roleId.value, newValues)
if (res.success) {
Message.success('修改成功')
visible.value = false
return false
} else {
Message.error(res.msg)
}
}
const handleChange = (value: string[]) => {
values.value = value
}
const getTransferData = (treeData: TreeNodeData[], transferDataSource: TransferItem[] = []) => {
treeData.forEach((item) => {
if (item["isUser"] === true) {
transferDataSource.push({ label: item.title ?? '', value: String(item.key) ?? '', disabled: false });
}
if (item.children) {
getTransferData(item.children, transferDataSource);
}
});
return transferDataSource;
};
treeData.forEach((item) => {
if (item.isUser === true) {
transferDataSource.push({ label: item.title ?? '', value: String(item.key) ?? '', disabled: false })
}
if (item.children) {
getTransferData(item.children, transferDataSource)
}
})
return transferDataSource
}
const getTreeData = () => {
const travel = (_treeData: TreeNodeData[] = []) => {
const treeDataSource: TreeNodeData[] = [];
_treeData.forEach((item) => {
const disabled = values.value.filter((v) => v === item.key).length > 0;
treeDataSource.push({ title: item.title, key: item.key, children: travel(item.children) , disabled: disabled});
});
return treeDataSource;
};
return travel(treeData.value);
};
const travel = (_treeData: TreeNodeData[] = []) => {
const treeDataSource: TreeNodeData[] = []
_treeData.forEach((item) => {
const disabled = values.value.filter((v) => v === item.key).length > 0
treeDataSource.push({ title: item.title, key: item.key, children: travel(item.children), disabled })
})
return treeDataSource
}
const onAssociation = async (id: string) => {
console.log(1);
visible.value = true;
roleId.value = id;
values.value = []
getDeptList();
listUsers(roleId.value);
};
const getDeptList = async () => {
const res = await listDeptWithUsersTree({ status: 1 });
treeData.value = res.data;
transferData.value = getTransferData(treeData.value);
};
return travel(treeData.value)
}
const listUsers = async (roleId: string) => {
const res = await listRoleUsers(roleId);
res.data.forEach(item => {
values.value.push( "user_" + item)
})
};
const res = await listRoleUsers(roleId)
res.data.forEach((item) => {
values.value.push(`user_${item}`)
})
}
const getDeptList = async () => {
const res = await listDeptWithUsersTree({ status: 1 })
treeData.value = res.data
transferData.value = getTransferData(treeData.value)
}
defineExpose({
onAssociation
});
</script>
const onAssociation = async (id: string) => {
visible.value = true
roleId.value = id
values.value = []
await getDeptList()
await listUsers(roleId.value)
}
<style lang="scss" scoped>
:deep(.arco-transfer-view) {
height: 40vh;
width: 300px;
}
</style>
defineExpose({
onAssociation,
})
</script>
<style lang="scss" scoped>
:deep(.arco-transfer-view) {
height: 40vh;
width: 300px;
}
</style>

View File

@@ -69,7 +69,6 @@
<RoleUpdateDrawer ref="RoleUpdateDrawerRef" @save-success="search" />
<RoleDetailDrawer ref="RoleDetailDrawerRef" />
<RoleUserAssociation ref="RoleUserAssociationRef" />
</div>
</template>
@@ -90,7 +89,7 @@ defineOptions({ name: 'SystemRole' })
const { data_scope_enum } = useDict('data_scope_enum')
const queryForm = reactive<RoleQuery>({
sort: ['createTime,desc']
sort: ['createTime,desc'],
})
const {
@@ -98,7 +97,7 @@ const {
loading,
pagination,
search,
handleDelete
handleDelete,
} = useTable((page) => listRole({ ...queryForm, ...page }), { immediate: true })
const columns: TableInstanceColumns[] = [
@@ -106,7 +105,7 @@ const columns: TableInstanceColumns[] = [
title: '序号',
width: 66,
align: 'center',
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize)
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
},
{ title: '名称', dataIndex: 'name', slotName: 'name', ellipsis: true, tooltip: true },
{ title: '编码', dataIndex: 'code', ellipsis: true, tooltip: true },
@@ -124,8 +123,8 @@ const columns: TableInstanceColumns[] = [
width: 200,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:role:update', 'system:role:delete'])
}
show: has.hasPermOr(['system:role:update', 'system:role:delete']),
},
]
// 重置

View File

@@ -1,12 +1,12 @@
<template>
<a-drawer
v-model:visible="visible"
:title="title"
:mask-closable="false"
:esc-to-close="false"
:width="width >= 600 ? 600 : '100%'"
@before-ok="save"
@close="reset"
v-model:visible="visible"
:title="title"
:mask-closable="false"
:esc-to-close="false"
:width="width >= 600 ? 600 : '100%'"
@before-ok="save"
@close="reset"
>
<a-form ref="formRef" :model="form" :rules="rules" size="large" auto-label-width>
<a-form-item label="名称" field="name">
@@ -23,9 +23,9 @@
</a-form-item>
<a-form-item v-if="form.type === 1" label="私有密钥" field="secretKey">
<a-input
v-model.trim="form.secretKey"
placeholder="请输入私有密钥"
:max-length="255"
v-model.trim="form.secretKey"
placeholder="请输入私有密钥"
:max-length="255"
/>
</a-form-item>
<a-form-item v-if="form.type === 1" label="终端节点" field="endpoint">
@@ -43,10 +43,10 @@
</template>
</a-form-item>
<a-form-item
v-if="form.type === 2"
label="域名"
field="domain"
:rules="[
v-if="form.type === 2"
label="域名"
field="domain"
:rules="[
{
required: true,
message: '请输入域名',
@@ -60,31 +60,31 @@
</a-form-item>
<a-form-item label="描述" field="description">
<a-textarea
v-model.trim="form.description"
placeholder="请输入描述"
show-word-limit
:max-length="200"
:auto-size="{ minRows: 3, maxRows: 5 }"
v-model.trim="form.description"
placeholder="请输入描述"
show-word-limit
:max-length="200"
:auto-size="{ minRows: 3, maxRows: 5 }"
/>
</a-form-item>
<a-form-item label="默认存储" field="isDefault">
<a-switch
v-model="form.isDefault"
type="round"
:checked-value="true"
:unchecked-value="false"
checked-text=""
unchecked-text=""
v-model="form.isDefault"
type="round"
:checked-value="true"
:unchecked-value="false"
checked-text=""
unchecked-text=""
/>
</a-form-item>
<a-form-item label="状态" field="status">
<a-switch
v-model="form.status"
type="round"
:checked-value="1"
:unchecked-value="2"
checked-text="启用"
unchecked-text="禁用"
v-model="form.status"
type="round"
:checked-value="1"
:unchecked-value="2"
checked-text="启用"
unchecked-text="禁用"
/>
</a-form-item>
</a-form>
@@ -118,14 +118,14 @@ const rules: FormInstance['rules'] = {
accessKey: [{ required: true, message: '请输入访问密钥' }],
secretKey: [{ required: true, message: '请输入私有密钥' }],
endpoint: [{ required: true, message: '请输入终端节点' }],
bucketName: [{ required: true, message: '请输入桶名称' }]
bucketName: [{ required: true, message: '请输入桶名称' }],
}
const { form, resetForm } = useForm({
type: 2,
isDefault: false,
sort: 999,
status: 1
status: 1,
})
/** 获取url的protocol和endpoint */
const stripProtocol = (url: string): { endpoint: string, protocol: string } => {
@@ -177,7 +177,7 @@ const save = async () => {
const data = {
...form,
secretKey: form.type === 1 && !form.secretKey.includes('*') ? encryptByRsa(form.secretKey) : null,
domain: form.domain || defaultDomain.value
domain: form.domain || defaultDomain.value,
}
if (isUpdate.value) {
await updateStorage(data, dataId.value)

View File

@@ -84,7 +84,7 @@ defineOptions({ name: 'SystemStorage' })
const { storage_type_enum } = useDict('storage_type_enum')
const queryForm = reactive<StorageQuery>({
sort: ['createTime,desc']
sort: ['createTime,desc'],
})
const {
@@ -92,7 +92,7 @@ const {
loading,
pagination,
search,
handleDelete
handleDelete,
} = useTable((page) => listStorage({ ...queryForm, ...page }), { immediate: true })
const columns: TableInstanceColumns[] = [
@@ -100,7 +100,7 @@ const columns: TableInstanceColumns[] = [
title: '序号',
width: 66,
align: 'center',
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize)
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
},
{ title: '名称', dataIndex: 'name', slotName: 'name', width: 140, ellipsis: true, tooltip: true },
{ title: '编码', dataIndex: 'code', ellipsis: true, tooltip: true },
@@ -121,8 +121,8 @@ const columns: TableInstanceColumns[] = [
width: 130,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:storage:update', 'system:storage:delete'])
}
show: has.hasPermOr(['system:storage:update', 'system:storage:delete']),
},
]
// 重置

View File

@@ -108,12 +108,12 @@ const rules: FormInstance['rules'] = {
nickname: [{ required: true, message: '请输入昵称' }],
password: [{ required: true, message: '请输入密码' }],
deptId: [{ required: true, message: '请选择所属部门' }],
roleIds: [{ required: true, message: '请选择角色' }]
roleIds: [{ required: true, message: '请选择角色' }],
}
const { form, resetForm } = useForm({
gender: 1 as Gender,
status: 1 as Status
status: 1 as Status,
})
// 重置

View File

@@ -1,14 +1,14 @@
<template>
<a-drawer
v-model:visible="visible"
title="导入用户"
:mask-closable="false"
:esc-to-close="false"
:width="width >= 600 ? 600 : '100%'"
ok-text="确认导入"
cancel-text="取消导入"
@before-ok="save"
@close="reset"
v-model:visible="visible"
title="导入用户"
:mask-closable="false"
:esc-to-close="false"
:width="width >= 600 ? 600 : '100%'"
ok-text="确认导入"
cancel-text="取消导入"
@before-ok="save"
@close="reset"
>
<a-form ref="formRef" :model="form" size="large" auto-label-width>
<a-alert v-if="!form.disabled" :show-icon="false" style="margin-bottom: 15px">
@@ -20,13 +20,14 @@
<fieldset>
<legend>1.上传解析文件</legend>
<div class="file-box">
<a-upload draggable
:custom-request="handleUpload"
:limit="1"
:show-retry-butto="false"
:show-cancel-button="false" tip="仅支持xls、xlsx格式"
:file-list="uploadFile"
accept=".xls, .xlsx, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
<a-upload
draggable
:custom-request="handleUpload"
:limit="1"
:show-retry-butto="false"
:show-cancel-button="false" tip="仅支持xls、xlsx格式"
:file-list="uploadFile"
accept=".xls, .xlsx, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
/>
</div>
<div v-if="dataResult.importKey">
@@ -68,12 +69,12 @@
</a-form-item>
<a-form-item label="默认状态" field="defaultStatus">
<a-switch
v-model="form.defaultStatus"
:checked-value="1"
:unchecked-value="2"
checked-text="启用"
unchecked-text="禁用"
type="round"
v-model="form.defaultStatus"
:checked-value="1"
:unchecked-value="2"
checked-text="启用"
unchecked-text="禁用"
type="round"
/>
</a-form-item>
</fieldset>
@@ -100,7 +101,7 @@ const { form, resetForm } = useForm({
duplicateUser: 1,
duplicateEmail: 1,
duplicatePhone: 1,
defaultStatus: 1
defaultStatus: 1,
})
const dataResult = ref<UserImportResp>({
@@ -109,7 +110,7 @@ const dataResult = ref<UserImportResp>({
validRows: 0,
duplicateUserRows: 0,
duplicateEmailRows: 0,
duplicatePhoneRows: 0
duplicatePhoneRows: 0,
})
// 重置
@@ -151,7 +152,7 @@ const handleUpload = (options: RequestOption) => {
return {
abort() {
controller.abort()
}
},
}
}

View File

@@ -29,11 +29,11 @@ const formRef = ref<InstanceType<typeof GiForm>>()
const options: Options = {
form: { size: 'large' },
btns: { hide: true }
btns: { hide: true },
}
const columns: Columns = reactive([
{ label: '密码', field: 'newPassword', type: 'input-password', rules: [{ required: true, message: '请输入密码' }] }
{ label: '密码', field: 'newPassword', type: 'input-password', rules: [{ required: true, message: '请输入密码' }] },
])
const { form, resetForm } = useForm({})

View File

@@ -28,6 +28,7 @@
css: true,
}"
>
<!-- eslint-disable-next-line vue/no-parsing-error -->
<template v-if="index = getMatchIndex(node?.title), index < 0">{{ node?.title }}</template>
<span v-else>{{ node?.title?.substr(0, index) }}
<span style="color: rgb(var(--arcoblue-6));">{{ node?.title?.substr(index, searchKey.length) }}</span>
@@ -50,7 +51,7 @@ interface Props {
placeholder?: string
}
const props = withDefaults(defineProps<Props>(), {
placeholder: '请输入关键词'
placeholder: '请输入关键词',
})
const emit = defineEmits<{
(e: 'node-click', keys: Array<any>): void
@@ -73,7 +74,7 @@ const { deptList, getDeptList } = useDept({
treeRef.value?.expandAll(true)
select([deptList.value[0]?.key])
})
}
},
})
// 过滤树
@@ -89,7 +90,7 @@ const search = (keyword: string) => {
if (filterData.length) {
result.push({
...item,
children: filterData
children: filterData,
})
}
}
@@ -106,8 +107,10 @@ const treeData = computed(() => {
/**
* 获取匹配索引
*
* @param name 名称
*/
// eslint-disable-next-line unused-imports/no-unused-vars
const getMatchIndex = (name: string) => {
if (!searchKey.value) return -1
return name.toLowerCase().indexOf(searchKey.value.toLowerCase())

View File

@@ -109,20 +109,20 @@ import { DisEnableStatusList } from '@/constant/common'
defineOptions({ name: 'SystemUser' })
const queryForm = reactive<UserQuery>({
sort: ['t1.createTime,desc']
sort: ['t1.createTime,desc'],
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
handleDelete,
} = useTable((page) => listUser({ ...queryForm, ...page }), { immediate: false })
const options: Options = reactive({
form: { layout: 'inline' },
grid: { cols: { xs: 1, sm: 1, md: 2, lg: 3, xl: 3, xxl: 3 } },
fold: { enable: true, index: 1, defaultCollapsed: true }
fold: { enable: true, index: 1, defaultCollapsed: true },
})
const queryFormColumns: Columns = reactive([
@@ -130,31 +130,31 @@ const queryFormColumns: Columns = reactive([
type: 'input',
field: 'description',
formItemProps: {
hideLabel: true
hideLabel: true,
},
props: {
placeholder: '用户名/昵称/描述'
}
placeholder: '用户名/昵称/描述',
},
},
{
type: 'select',
field: 'status',
options: DisEnableStatusList,
formItemProps: {
hideLabel: true
hideLabel: true,
},
props: {
placeholder: '请选择状态'
}
placeholder: '请选择状态',
},
},
{
type: 'range-picker',
field: 'createTime',
span: { lg: 2, xl: 2, xxl: 1 },
formItemProps: {
hideLabel: true
}
}
hideLabel: true,
},
},
])
const columns: TableInstanceColumns[] = [
@@ -163,7 +163,7 @@ const columns: TableInstanceColumns[] = [
width: 66,
align: 'center',
render: ({ rowIndex }) => h('span', {}, rowIndex + 1 + (pagination.current - 1) * pagination.pageSize),
fixed: !isMobile() ? 'left' : undefined
fixed: !isMobile() ? 'left' : undefined,
},
{
title: '昵称',
@@ -172,7 +172,7 @@ const columns: TableInstanceColumns[] = [
minWidth: 140,
ellipsis: true,
tooltip: true,
fixed: !isMobile() ? 'left' : undefined
fixed: !isMobile() ? 'left' : undefined,
},
{ title: '用户名', dataIndex: 'username', slotName: 'username', minWidth: 140, ellipsis: true, tooltip: true },
{ title: '状态', slotName: 'status', align: 'center', width: 80 },
@@ -193,8 +193,8 @@ const columns: TableInstanceColumns[] = [
width: 190,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['system:user:update', 'system:user:delete', 'system:user:resetPwd'])
}
show: has.hasPermOr(['system:user:update', 'system:user:delete', 'system:user:resetPwd']),
},
]
// 重置
@@ -209,7 +209,7 @@ const reset = () => {
const onDelete = (record: UserResp) => {
return handleDelete(() => deleteUser(record.id), {
content: `是否确定删除 [${record.nickname}(${record.username})]`,
showModal: true
showModal: true,
})
}