mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-11-14 03:01:37 +08:00
refactor: 调整 eslint.config.js,优化代码格式
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
// 重置
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
// 重置
|
||||
|
||||
@@ -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']),
|
||||
},
|
||||
]
|
||||
|
||||
// 重置
|
||||
|
||||
@@ -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({})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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`,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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 = ''
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 }),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
|
||||
@@ -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
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ onMounted(() => {
|
||||
lang: 'zh-cn',
|
||||
autoplay: true,
|
||||
closeVideoClick: true,
|
||||
videoInit: true
|
||||
videoInit: true,
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,6 @@ export function previewFileVideoModal(data: FileItem) {
|
||||
title: '视频播放',
|
||||
width: 'auto',
|
||||
modalStyle: {},
|
||||
content: () => h(ModalContent, { data })
|
||||
content: () => h(ModalContent, { data }),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ watch(
|
||||
selectedKey.value = route.query.type as string || '0'
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
immediate: true,
|
||||
},
|
||||
)
|
||||
|
||||
// 点击事件
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -53,7 +53,7 @@ interface Props {
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
data: () => [], // 文件数据
|
||||
selectedFileIds: () => [], // 批量模式下选中的文件id数组
|
||||
isBatchMode: false // 是否是批量模式
|
||||
isBatchMode: false, // 是否是批量模式
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -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]
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
// 多选
|
||||
|
||||
@@ -18,7 +18,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
shadow: true
|
||||
shadow: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,6 @@ export default function () {
|
||||
selectedFileList,
|
||||
selectedFileIds,
|
||||
toggleMode,
|
||||
addSelectedFileItem
|
||||
addSelectedFileItem,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ const editorConfig = reactive<AiEditorOptions>({
|
||||
theme: appStore.theme,
|
||||
placeholder: '请输入内容',
|
||||
content: '',
|
||||
editable: false
|
||||
editable: false,
|
||||
})
|
||||
const init = () => {
|
||||
aieditor.value?.destroy()
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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: '请选择指定用户' }],
|
||||
},
|
||||
|
||||
])
|
||||
// 修改
|
||||
|
||||
@@ -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: '',
|
||||
})
|
||||
|
||||
// 修改
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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']),
|
||||
},
|
||||
]
|
||||
|
||||
// 重置
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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']),
|
||||
},
|
||||
]
|
||||
|
||||
// 重置
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
// 重置
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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({})
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user