mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-09 20:57:17 +08:00
feat(system/config): 新增存储配置
This commit is contained in:
@@ -5,7 +5,6 @@ export * from './dept'
|
||||
export * from './notice'
|
||||
export * from './dict'
|
||||
export * from './file'
|
||||
export * from './storage'
|
||||
export * from './option'
|
||||
export * from './user-center'
|
||||
export * from './message'
|
||||
|
@@ -1,31 +0,0 @@
|
||||
import type * as T from './type'
|
||||
import http from '@/utils/http'
|
||||
|
||||
export type * from './type'
|
||||
|
||||
const BASE_URL = '/system/storage'
|
||||
|
||||
/** @desc 查询存储列表 */
|
||||
export function listStorage(query: T.StoragePageQuery) {
|
||||
return http.get<PageRes<T.StorageResp[]>>(`${BASE_URL}`, query)
|
||||
}
|
||||
|
||||
/** @desc 查询存储详情 */
|
||||
export function getStorage(id: string) {
|
||||
return http.get<T.StorageResp>(`${BASE_URL}/${id}`)
|
||||
}
|
||||
|
||||
/** @desc 新增存储 */
|
||||
export function addStorage(data: any) {
|
||||
return http.post(`${BASE_URL}`, data)
|
||||
}
|
||||
|
||||
/** @desc 修改存储 */
|
||||
export function updateStorage(data: any, id: string) {
|
||||
return http.put(`${BASE_URL}/${id}`, data)
|
||||
}
|
||||
|
||||
/** @desc 删除存储 */
|
||||
export function deleteStorage(id: string) {
|
||||
return http.del(`${BASE_URL}/${id}`)
|
||||
}
|
@@ -231,34 +231,6 @@ export interface FileQuery {
|
||||
export interface FilePageQuery extends FileQuery, PageQuery {
|
||||
}
|
||||
|
||||
/** 存储类型 */
|
||||
export interface StorageResp {
|
||||
id: string
|
||||
name: string
|
||||
code: string
|
||||
type: number
|
||||
accessKey: string
|
||||
secretKey: string
|
||||
endpoint: string
|
||||
bucketName: string
|
||||
domain: string
|
||||
description: string
|
||||
isDefault: boolean
|
||||
sort: number
|
||||
status: number
|
||||
createUserString: string
|
||||
createTime: string
|
||||
updateUserString: string
|
||||
updateTime: string
|
||||
}
|
||||
export interface StorageQuery {
|
||||
description?: string
|
||||
status?: number
|
||||
sort: Array<string>
|
||||
}
|
||||
export interface StoragePageQuery extends StorageQuery, PageQuery {
|
||||
}
|
||||
|
||||
/** 客户端类型 */
|
||||
export interface ClientResp {
|
||||
id: string
|
||||
@@ -334,6 +306,7 @@ export interface SiteConfig {
|
||||
SITE_TITLE: OptionResp
|
||||
SITE_DESCRIPTION: OptionResp
|
||||
SITE_COPYRIGHT: OptionResp
|
||||
SITE_DOMAIN: OptionResp
|
||||
SITE_BEIAN: OptionResp
|
||||
}
|
||||
|
||||
@@ -360,6 +333,18 @@ export interface MailConfig {
|
||||
MAIL_SSL_PORT: OptionResp
|
||||
}
|
||||
|
||||
/** 存储配置类型 */
|
||||
export interface StorageConfig {
|
||||
STORAGE_DEFAULT: OptionResp
|
||||
STORAGE_LOCAL_BUCKET: OptionResp
|
||||
STORAGE_LOCAL_ENDPOINT: OptionResp
|
||||
STORAGE_OSS_ACCESS_KEY: OptionResp
|
||||
STORAGE_OSS_SECRET_KEY: OptionResp
|
||||
STORAGE_OSS_BUCKET: OptionResp
|
||||
STORAGE_OSS_ENDPOINT: OptionResp
|
||||
STORAGE_OSS_REGION: OptionResp
|
||||
}
|
||||
|
||||
/** 登录配置类型 */
|
||||
export interface LoginConfig {
|
||||
LOGIN_CAPTCHA_ENABLED: OptionResp
|
||||
|
@@ -9,25 +9,56 @@
|
||||
:layout="width >= 500 ? 'horizontal' : 'vertical'"
|
||||
:disabled="!isUpdate"
|
||||
scroll-to-first-error
|
||||
class="form"
|
||||
>
|
||||
<a-form-item field="MAIL_PROTOCOL" :label="mailConfig.MAIL_PROTOCOL.name" hide-asterisk>
|
||||
<a-form-item
|
||||
field="MAIL_PROTOCOL"
|
||||
:label="mailConfig.MAIL_PROTOCOL.name"
|
||||
:help="mailConfig.MAIL_PROTOCOL.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-select v-model.trim="form.MAIL_PROTOCOL">
|
||||
<a-option label="SMTP" value="smtp" />
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="MAIL_HOST" :label="mailConfig.MAIL_HOST.name" hide-asterisk>
|
||||
<a-input v-model.trim="form.MAIL_HOST" class="input-width" />
|
||||
<a-form-item
|
||||
field="MAIL_HOST"
|
||||
:label="mailConfig.MAIL_HOST.name"
|
||||
:help="mailConfig.MAIL_HOST.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model.trim="form.MAIL_HOST" />
|
||||
</a-form-item>
|
||||
<a-form-item field="MAIL_PORT" :label="mailConfig.MAIL_PORT.name" hide-asterisk>
|
||||
<a-input-number v-model="form.MAIL_PORT" class="input-width" :min="0" />
|
||||
<a-form-item
|
||||
field="MAIL_PORT"
|
||||
:label="mailConfig.MAIL_PORT.name"
|
||||
:help="mailConfig.MAIL_PORT.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input-number v-model="form.MAIL_PORT" :min="0" />
|
||||
</a-form-item>
|
||||
<a-form-item field="MAIL_USERNAME" :label="mailConfig.MAIL_USERNAME.name" hide-asterisk>
|
||||
<a-input v-model.trim="form.MAIL_USERNAME" class="input-width" />
|
||||
<a-form-item
|
||||
field="MAIL_USERNAME"
|
||||
:label="mailConfig.MAIL_USERNAME.name"
|
||||
:help="mailConfig.MAIL_USERNAME.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model.trim="form.MAIL_USERNAME" />
|
||||
</a-form-item>
|
||||
<a-form-item field="MAIL_PASSWORD" :label="mailConfig.MAIL_PASSWORD?.name" hide-asterisk>
|
||||
<a-input-password v-model.trim="form.MAIL_PASSWORD" class="input-width" />
|
||||
<a-form-item
|
||||
field="MAIL_PASSWORD"
|
||||
:label="mailConfig.MAIL_PASSWORD?.name"
|
||||
:help="mailConfig.MAIL_PASSWORD.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input-password v-model.trim="form.MAIL_PASSWORD" />
|
||||
</a-form-item>
|
||||
<a-form-item field="MAIL_SSL_ENABLED" :label="mailConfig.MAIL_SSL_ENABLED?.name" hide-asterisk>
|
||||
<a-form-item
|
||||
field="MAIL_SSL_ENABLED"
|
||||
:label="mailConfig.MAIL_SSL_ENABLED?.name"
|
||||
:help="mailConfig.MAIL_SSL_ENABLED.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-switch
|
||||
v-model="form.MAIL_SSL_ENABLED"
|
||||
type="round"
|
||||
@@ -39,10 +70,13 @@
|
||||
</a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="form.MAIL_SSL_ENABLED === '1'" field="MAIL_SSL_PORT" :label="mailConfig.MAIL_SSL_PORT.name"
|
||||
v-if="form.MAIL_SSL_ENABLED === '1'"
|
||||
field="MAIL_SSL_PORT"
|
||||
:label="mailConfig.MAIL_SSL_PORT.name"
|
||||
:help="mailConfig.MAIL_SSL_PORT.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input-number v-model="form.MAIL_SSL_PORT" class="input-width" :min="0" />
|
||||
<a-input-number v-model="form.MAIL_SSL_PORT" :min="0" />
|
||||
</a-form-item>
|
||||
<a-space style="margin-bottom: 16px">
|
||||
<a-button v-if="!isUpdate" v-permission="['system:config:update']" type="primary" @click="onUpdate">
|
||||
@@ -186,7 +220,8 @@ onMounted(() => {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.input-width, :deep(.arco-select-view-single) {
|
||||
:deep(.form .arco-input-wrapper),
|
||||
:deep(.arco-select-view-single) {
|
||||
width: 220px;
|
||||
}
|
||||
</style>
|
||||
|
@@ -9,35 +9,49 @@
|
||||
:layout="width >= 500 ? 'horizontal' : 'vertical'"
|
||||
:disabled="!isUpdate"
|
||||
scroll-to-first-error
|
||||
class="form"
|
||||
>
|
||||
<a-form-item
|
||||
field="PASSWORD_ERROR_LOCK_COUNT" :label="securityConfig.PASSWORD_ERROR_LOCK_COUNT.name"
|
||||
:help="securityConfig.PASSWORD_ERROR_LOCK_COUNT.description" hide-asterisk
|
||||
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"
|
||||
v-model="form.PASSWORD_ERROR_LOCK_COUNT"
|
||||
: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
|
||||
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"
|
||||
v-model="form.PASSWORD_ERROR_LOCK_MINUTES"
|
||||
: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
|
||||
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"
|
||||
v-model="form.PASSWORD_EXPIRATION_DAYS"
|
||||
:precision="0"
|
||||
:min="0"
|
||||
:max="999"
|
||||
>
|
||||
<template #append>天</template>
|
||||
@@ -45,43 +59,62 @@
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:label="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.name"
|
||||
field="PASSWORD_EXPIRATION_WARNING_DAYS" :help="securityConfig.PASSWORD_EXPIRATION_WARNING_DAYS.description"
|
||||
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"
|
||||
v-model="form.PASSWORD_EXPIRATION_WARNING_DAYS"
|
||||
: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
|
||||
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"
|
||||
v-model="form.PASSWORD_REPETITION_TIMES"
|
||||
: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
|
||||
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-input-number
|
||||
v-model="form.PASSWORD_MIN_LENGTH"
|
||||
:precision="0"
|
||||
:min="8"
|
||||
:max="32"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="PASSWORD_ALLOW_CONTAIN_USERNAME"
|
||||
:label="securityConfig.PASSWORD_ALLOW_CONTAIN_USERNAME.name"
|
||||
:help="securityConfig.PASSWORD_ALLOW_CONTAIN_USERNAME.description"
|
||||
>
|
||||
<a-switch v-model="form.PASSWORD_ALLOW_CONTAIN_USERNAME" type="round" :checked-value="1" :unchecked-value="0">
|
||||
<template #checked>是</template>
|
||||
<template #unchecked>否</template>
|
||||
</a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item field="PASSWORD_REQUIRE_SYMBOLS" :label="securityConfig.PASSWORD_REQUIRE_SYMBOLS.name">
|
||||
<a-form-item
|
||||
field="PASSWORD_REQUIRE_SYMBOLS"
|
||||
:label="securityConfig.PASSWORD_REQUIRE_SYMBOLS.name"
|
||||
:help="securityConfig.PASSWORD_REQUIRE_SYMBOLS.description"
|
||||
>
|
||||
<a-switch v-model="form.PASSWORD_REQUIRE_SYMBOLS" type="round" :checked-value="1" :unchecked-value="0">
|
||||
<template #checked>是</template>
|
||||
<template #unchecked>否</template>
|
||||
@@ -138,7 +171,7 @@ const rules: FormInstance['rules'] = {
|
||||
{
|
||||
validator: (value, callback) => {
|
||||
if (form.PASSWORD_EXPIRATION_DAYS > 0 && value >= form.PASSWORD_EXPIRATION_DAYS) {
|
||||
callback('密码到期前的提示时间应小于密码有效期')
|
||||
callback('密码到期提醒时间应小于密码有效期')
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
@@ -238,7 +271,7 @@ onMounted(() => {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.input-width {
|
||||
:deep(.form .arco-input-wrapper) {
|
||||
width: 200px;
|
||||
}
|
||||
</style>
|
||||
|
@@ -72,24 +72,26 @@
|
||||
</a-upload>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item class="input-item" field="SITE_TITLE" :label="siteConfig.SITE_TITLE.name">
|
||||
<a-input v-model.trim="form.SITE_TITLE" class="input-width" placeholder="请输入系统标题" :max-length="18" show-word-limit />
|
||||
<a-form-item class="input-item" field="SITE_TITLE" :label="siteConfig.SITE_TITLE.name" :help="siteConfig.SITE_TITLE.description">
|
||||
<a-input v-model.trim="form.SITE_TITLE" placeholder="请输入网站名称" :max-length="18" show-word-limit />
|
||||
</a-form-item>
|
||||
<a-form-item class="input-item" field="SITE_DESCRIPTION" :label="siteConfig.SITE_DESCRIPTION.name">
|
||||
<a-form-item class="input-item" field="SITE_DESCRIPTION" :label="siteConfig.SITE_DESCRIPTION.name" :help="siteConfig.SITE_DESCRIPTION.description">
|
||||
<a-textarea
|
||||
v-model.trim="form.SITE_DESCRIPTION"
|
||||
class="input-width"
|
||||
placeholder="请输入系统描述"
|
||||
placeholder="请输入网站描述"
|
||||
:auto-size="{ minRows: 1, maxRows: 3 }"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="input-item" field="SITE_COPYRIGHT" :label="siteConfig.SITE_COPYRIGHT.name">
|
||||
<a-input v-model.trim="form.SITE_COPYRIGHT" class="input-width" placeholder="请输入版权信息" />
|
||||
<a-form-item class="input-item" field="SITE_COPYRIGHT" :label="siteConfig.SITE_COPYRIGHT.name" :help="siteConfig.SITE_COPYRIGHT.description">
|
||||
<a-input v-model.trim="form.SITE_COPYRIGHT" placeholder="请输入版权声明" />
|
||||
</a-form-item>
|
||||
<a-form-item field="SITE_BEIAN" :label="siteConfig.SITE_BEIAN.name">
|
||||
<a-input v-model.trim="form.SITE_BEIAN" class="input-width" placeholder="请输入备案号" :max-length="30" show-word-limit />
|
||||
<a-form-item class="input-item" field="SITE_DOMAIN" :label="siteConfig.SITE_DOMAIN.name" :help="siteConfig.SITE_DOMAIN.description">
|
||||
<a-input v-model.trim="form.SITE_DOMAIN" placeholder="请输入网站域名" />
|
||||
</a-form-item>
|
||||
<a-space style="margin-bottom: 16px">
|
||||
<a-form-item field="SITE_BEIAN" :label="siteConfig.SITE_BEIAN.name" :help="siteConfig.SITE_BEIAN.description">
|
||||
<a-input v-model.trim="form.SITE_BEIAN" placeholder="请输入网站备案号" :max-length="30" show-word-limit />
|
||||
</a-form-item>
|
||||
<a-space style="margin-top: 16px">
|
||||
<a-button v-if="!isUpdate" v-permission="['system:config:update']" type="primary" @click="onUpdate">
|
||||
<template #icon>
|
||||
<icon-edit />
|
||||
@@ -144,9 +146,9 @@ const [form] = useResetReactive({
|
||||
SITE_COPYRIGHT: '',
|
||||
})
|
||||
const rules: FormInstance['rules'] = {
|
||||
SITE_TITLE: [{ required: true, message: '请输入系统标题' }],
|
||||
SITE_DESCRIPTION: [{ required: true, message: '请输入系统描述' }],
|
||||
SITE_COPYRIGHT: [{ required: true, message: '请输入版权信息' }],
|
||||
SITE_TITLE: [{ required: true, message: '请输入网站名称' }],
|
||||
SITE_DESCRIPTION: [{ required: true, message: '请输入网站描述' }],
|
||||
SITE_COPYRIGHT: [{ required: true, message: '请输入版权声明' }],
|
||||
}
|
||||
|
||||
const siteConfig = ref<SiteConfig>({
|
||||
@@ -155,6 +157,7 @@ const siteConfig = ref<SiteConfig>({
|
||||
SITE_TITLE: {},
|
||||
SITE_DESCRIPTION: {},
|
||||
SITE_COPYRIGHT: {},
|
||||
SITE_DOMAIN: {},
|
||||
SITE_BEIAN: {},
|
||||
})
|
||||
const faviconFile = ref<FileItem>({ uid: '-1' })
|
||||
@@ -166,6 +169,7 @@ const reset = () => {
|
||||
form.SITE_LOGO = siteConfig.value.SITE_LOGO.value || ''
|
||||
form.SITE_TITLE = siteConfig.value.SITE_TITLE.value || ''
|
||||
form.SITE_DESCRIPTION = siteConfig.value.SITE_DESCRIPTION.value || ''
|
||||
form.SITE_DOMAIN = siteConfig.value.SITE_DOMAIN.value || ''
|
||||
form.SITE_COPYRIGHT = siteConfig.value.SITE_COPYRIGHT.value || ''
|
||||
form.SITE_BEIAN = siteConfig.value.SITE_BEIAN.value || ''
|
||||
faviconFile.value.url = siteConfig.value.SITE_FAVICON.value
|
||||
@@ -313,7 +317,8 @@ onMounted(() => {
|
||||
line-height: 46px;
|
||||
}
|
||||
|
||||
.input-width {
|
||||
:deep(.form .arco-input-wrapper),
|
||||
:deep(.form .arco-textarea-wrapper) {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
@@ -327,9 +332,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
// responsive
|
||||
.mobile {
|
||||
.input-width {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.mobile .form .arco-input-wrapper),
|
||||
:deep(.mobile .form .arco-textarea-wrapper) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
261
src/views/system/config/components/StorageSetting.vue
Normal file
261
src/views/system/config/components/StorageSetting.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<a-spin :loading="loading">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="form.STORAGE_DEFAULT === 'LOCAL' ? localRules : ossRules"
|
||||
auto-label-width
|
||||
label-align="left"
|
||||
:layout="width >= 500 ? 'horizontal' : 'vertical'"
|
||||
:disabled="!isUpdate"
|
||||
scroll-to-first-error
|
||||
class="form"
|
||||
>
|
||||
<!-- 默认存储 -->
|
||||
<a-form-item
|
||||
field="STORAGE_DEFAULT"
|
||||
:label="storageConfig.STORAGE_DEFAULT.name"
|
||||
>
|
||||
<a-radio-group v-model="form.STORAGE_DEFAULT">
|
||||
<a-radio value="LOCAL">本地存储</a-radio>
|
||||
<a-radio value="OSS">对象存储</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<fieldset>
|
||||
<legend>本地存储配置</legend>
|
||||
<a-form-item
|
||||
field="STORAGE_LOCAL_BUCKET"
|
||||
:label="storageConfig.STORAGE_LOCAL_BUCKET.name"
|
||||
:help="storageConfig.STORAGE_LOCAL_BUCKET.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model="form.STORAGE_LOCAL_BUCKET" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="STORAGE_LOCAL_ENDPOINT"
|
||||
:label="storageConfig.STORAGE_LOCAL_ENDPOINT.name"
|
||||
:help="storageConfig.STORAGE_LOCAL_ENDPOINT.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model="form.STORAGE_LOCAL_ENDPOINT" />
|
||||
</a-form-item>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>对象存储配置</legend>
|
||||
<a-form-item
|
||||
field="STORAGE_OSS_ACCESS_KEY"
|
||||
:label="storageConfig.STORAGE_OSS_ACCESS_KEY.name"
|
||||
:help="storageConfig.STORAGE_OSS_ACCESS_KEY.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model="form.STORAGE_OSS_ACCESS_KEY" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="STORAGE_OSS_SECRET_KEY"
|
||||
:label="storageConfig.STORAGE_OSS_SECRET_KEY.name"
|
||||
:help="storageConfig.STORAGE_OSS_SECRET_KEY.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input-password v-model="form.STORAGE_OSS_SECRET_KEY" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="STORAGE_OSS_BUCKET"
|
||||
:label="storageConfig.STORAGE_OSS_BUCKET.name"
|
||||
:help="storageConfig.STORAGE_OSS_BUCKET.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model="form.STORAGE_OSS_BUCKET" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="STORAGE_OSS_ENDPOINT"
|
||||
:label="storageConfig.STORAGE_OSS_ENDPOINT.name"
|
||||
:help="storageConfig.STORAGE_OSS_ENDPOINT.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model="form.STORAGE_OSS_ENDPOINT" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="STORAGE_OSS_REGION"
|
||||
:label="storageConfig.STORAGE_OSS_REGION.name"
|
||||
:help="storageConfig.STORAGE_OSS_REGION.description"
|
||||
hide-asterisk
|
||||
>
|
||||
<a-input v-model="form.STORAGE_OSS_REGION" />
|
||||
</a-form-item>
|
||||
</fieldset>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<a-space style="margin-bottom: 16px">
|
||||
<a-button v-if="!isUpdate" v-permission="['system:config:update']" type="primary" @click="onUpdate">
|
||||
<template #icon>
|
||||
<icon-edit />
|
||||
</template>
|
||||
修改
|
||||
</a-button>
|
||||
<a-button v-if="!isUpdate" v-permission="['system:config:reset']" @click="onResetValue">
|
||||
<template #icon>
|
||||
<icon-undo />
|
||||
</template>
|
||||
恢复默认
|
||||
</a-button>
|
||||
<a-button v-if="isUpdate" type="primary" @click="handleSave">
|
||||
<template #icon>
|
||||
<icon-save />
|
||||
</template>
|
||||
保存
|
||||
</a-button>
|
||||
<a-button v-if="isUpdate" @click="reset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
<a-button v-if="isUpdate" @click="handleCancel">
|
||||
<template #icon>
|
||||
<icon-undo />
|
||||
</template>
|
||||
取消
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import { type FormInstance, Message, Modal } from '@arco-design/web-vue'
|
||||
import {
|
||||
type OptionResp,
|
||||
type SecurityConfig,
|
||||
type StorageConfig,
|
||||
listOption,
|
||||
resetOptionValue,
|
||||
updateOption,
|
||||
} from '@/apis/system'
|
||||
import { useResetReactive } from '@/hooks'
|
||||
|
||||
defineOptions({ name: 'StorageSetting' })
|
||||
const { width } = useWindowSize()
|
||||
|
||||
const loading = ref<boolean>(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const [form] = useResetReactive({
|
||||
STORAGE_DEFAULT: 'LOCAL', // 默认选中本地存储
|
||||
STORAGE_LOCAL_BUCKET: '',
|
||||
STORAGE_LOCAL_ENDPOINT: '',
|
||||
STORAGE_OSS_ACCESS_KEY: '',
|
||||
STORAGE_OSS_SECRET_KEY: '',
|
||||
STORAGE_OSS_BUCKET: '',
|
||||
STORAGE_OSS_ENDPOINT: '',
|
||||
STORAGE_OSS_REGION: '',
|
||||
})
|
||||
|
||||
const localRules: FormInstance['rules'] = {
|
||||
STORAGE_LOCAL_BUCKET: [{ required: true, message: '请输入本地存储路径' }],
|
||||
STORAGE_LOCAL_ENDPOINT: [{ required: true, message: '请输入本地资源访问地址' }],
|
||||
}
|
||||
|
||||
const ossRules: FormInstance['rules'] = {
|
||||
STORAGE_OSS_ACCESS_KEY: [{ required: true, message: '请输入Access Key' }],
|
||||
STORAGE_OSS_SECRET_KEY: [{ required: true, message: '请输入Secret Key' }],
|
||||
STORAGE_OSS_BUCKET: [{ required: true, message: '请输入对象存储桶名称' }],
|
||||
STORAGE_OSS_ENDPOINT: [{ required: true, message: '请输入对象存储终端节点' }],
|
||||
}
|
||||
|
||||
const storageConfig = ref<StorageConfig>({
|
||||
STORAGE_DEFAULT: {},
|
||||
STORAGE_LOCAL_BUCKET: {},
|
||||
STORAGE_LOCAL_ENDPOINT: {},
|
||||
STORAGE_OSS_ACCESS_KEY: {},
|
||||
STORAGE_OSS_SECRET_KEY: {},
|
||||
STORAGE_OSS_BUCKET: {},
|
||||
STORAGE_OSS_ENDPOINT: {},
|
||||
STORAGE_OSS_REGION: {},
|
||||
})
|
||||
|
||||
const reset = () => {
|
||||
formRef.value?.resetFields()
|
||||
Object.keys(form).forEach((key) => {
|
||||
form[key] = storageConfig.value[key]?.value || form[key] // 兜底设置默认值
|
||||
})
|
||||
}
|
||||
|
||||
const isUpdate = ref(false)
|
||||
|
||||
const onUpdate = () => {
|
||||
isUpdate.value = true
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
reset()
|
||||
isUpdate.value = false
|
||||
}
|
||||
|
||||
const queryForm = { category: 'STORAGE' }
|
||||
|
||||
const getDataList = async () => {
|
||||
loading.value = true
|
||||
const { data } = await listOption(queryForm)
|
||||
storageConfig.value = data.reduce((obj: SecurityConfig, option: OptionResp) => {
|
||||
obj[option.code] = { ...option, value: option.value }
|
||||
return obj
|
||||
}, {})
|
||||
handleCancel()
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
const isInvalid = await formRef.value?.validate()
|
||||
if (isInvalid) return
|
||||
await updateOption(
|
||||
Object.entries(form).map(([key, value]) => ({ id: storageConfig.value[key].id, code: key, value })),
|
||||
)
|
||||
await getDataList()
|
||||
Message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleResetValue = async () => {
|
||||
await resetOptionValue(queryForm)
|
||||
Message.success('恢复成功')
|
||||
await getDataList()
|
||||
}
|
||||
|
||||
const onResetValue = () => {
|
||||
Modal.warning({
|
||||
title: '警告',
|
||||
content: '确认恢复存储配置为默认值吗?',
|
||||
hideCancel: false,
|
||||
maskClosable: false,
|
||||
onOk: handleResetValue,
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDataList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.form .arco-input-wrapper) {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
min-width: 0;
|
||||
padding: 15px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid var(--color-neutral-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
fieldset legend {
|
||||
color: rgb(var(--gray-10));
|
||||
padding: 2px 5px 2px 5px;
|
||||
border: 1px solid var(--color-neutral-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
@@ -6,16 +6,19 @@
|
||||
</a-space>
|
||||
</a-row> -->
|
||||
<a-tabs v-model:active-key="activeKey" type="card-gutter" size="large" @change="change">
|
||||
<a-tab-pane key="1">
|
||||
<template #title><icon-settings /> 基础配置</template>
|
||||
<a-tab-pane key="site">
|
||||
<template #title><icon-apps /> 网站配置</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2">
|
||||
<a-tab-pane key="security">
|
||||
<template #title><icon-safe /> 安全配置</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3">
|
||||
<a-tab-pane key="mail">
|
||||
<template #title><icon-email /> 邮件配置</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="4">
|
||||
<a-tab-pane key="storage">
|
||||
<template #title><icon-storage /> 存储配置</template>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="login">
|
||||
<template #title><icon-lock /> 登录配置</template>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
@@ -27,35 +30,37 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import BasicSetting from './components/BasicSetting.vue'
|
||||
import SiteSetting from './components/SiteSetting.vue'
|
||||
import SecuritySetting from './components/SecuritySetting.vue'
|
||||
import MailSetting from './components/MailSetting.vue'
|
||||
import LoginSetting from './components/LoginSetting.vue'
|
||||
import StorageSetting from './components/StorageSetting.vue'
|
||||
|
||||
defineOptions({ name: 'SystemConfig' })
|
||||
|
||||
const PanMap: Record<string, Component> = {
|
||||
1: BasicSetting,
|
||||
2: SecuritySetting,
|
||||
3: MailSetting,
|
||||
4: LoginSetting,
|
||||
site: SiteSetting,
|
||||
security: SecuritySetting,
|
||||
mail: MailSetting,
|
||||
storage: StorageSetting,
|
||||
login: LoginSetting,
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const activeKey = ref('1')
|
||||
const activeKey = ref('site')
|
||||
watch(
|
||||
() => route.query,
|
||||
() => {
|
||||
if (route.query.tabKey) {
|
||||
activeKey.value = String(route.query.tabKey)
|
||||
if (route.query.tab) {
|
||||
activeKey.value = String(route.query.tab)
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
const change = (key: string | number) => {
|
||||
activeKey.value = key as string
|
||||
router.replace({ path: route.path, query: { tabKey: key } })
|
||||
router.replace({ path: route.path, query: { tab: key } })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -1,198 +0,0 @@
|
||||
<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"
|
||||
>
|
||||
<a-form ref="formRef" :model="form" :rules="rules" size="large" auto-label-width>
|
||||
<a-form-item label="名称" field="name">
|
||||
<a-input v-model.trim="form.name" placeholder="请输入名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="编码" field="code">
|
||||
<a-input v-model.trim="form.code" placeholder="请输入编码" :disabled="isUpdate" />
|
||||
</a-form-item>
|
||||
<a-form-item label="类型" field="type">
|
||||
<a-select v-model.trim="form.type" :options="storage_type_enum" placeholder="请选择类型" :disabled="isUpdate" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="form.type === 1" label="访问密钥" field="accessKey">
|
||||
<a-input v-model.trim="form.accessKey" placeholder="请输入访问密钥" :max-length="255" />
|
||||
</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"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="form.type === 1" label="终端节点" field="endpoint">
|
||||
<a-input v-model.trim="form.endpoint" placeholder="请输入终端节点" />
|
||||
</a-form-item>
|
||||
<a-form-item label="桶名称" field="bucketName">
|
||||
<a-input v-model.trim="form.bucketName" placeholder="请输入桶名称" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="form.type === 1" label="域名" field="domain">
|
||||
<a-input v-model.trim="form.domain" placeholder="请输入域名" />
|
||||
<template #extra>
|
||||
<div v-if="defaultDomain">
|
||||
<span>留空默认域名:{{ defaultDomain }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="form.type === 2"
|
||||
label="域名"
|
||||
field="domain"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入域名',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input v-model.trim="form.domain" placeholder="请输入域名" />
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" field="sort">
|
||||
<a-input-number v-model="form.sort" placeholder="请输入排序" :min="1" mode="button" />
|
||||
</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 }"
|
||||
/>
|
||||
</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="否"
|
||||
/>
|
||||
</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="禁用"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type FormInstance, Message } from '@arco-design/web-vue'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import { addStorage, getStorage, updateStorage } from '@/apis/system/storage'
|
||||
import { useResetReactive } from '@/hooks'
|
||||
import { useDict } from '@/hooks/app'
|
||||
import { encryptByRsa } from '@/utils/encrypt'
|
||||
import { isIPv4 } from '@/utils/validate'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'save-success'): void
|
||||
}>()
|
||||
|
||||
const { width } = useWindowSize()
|
||||
|
||||
const dataId = ref('')
|
||||
const visible = ref(false)
|
||||
const isUpdate = computed(() => !!dataId.value)
|
||||
const title = computed(() => (isUpdate.value ? '修改存储' : '新增存储'))
|
||||
const formRef = ref<FormInstance>()
|
||||
const { storage_type_enum } = useDict('storage_type_enum')
|
||||
|
||||
const rules: FormInstance['rules'] = {
|
||||
name: [{ required: true, message: '请输入名称' }],
|
||||
code: [{ required: true, message: '请输入编码' }],
|
||||
type: [{ required: true, message: '请选择类型' }],
|
||||
accessKey: [{ required: true, message: '请输入访问密钥' }],
|
||||
secretKey: [{ required: true, message: '请输入私有密钥' }],
|
||||
endpoint: [{ required: true, message: '请输入终端节点' }],
|
||||
bucketName: [{ required: true, message: '请输入桶名称' }],
|
||||
}
|
||||
|
||||
const [form, resetForm] = useResetReactive({
|
||||
type: 2,
|
||||
isDefault: false,
|
||||
sort: 999,
|
||||
status: 1,
|
||||
})
|
||||
/** 获取url的protocol和endpoint */
|
||||
const stripProtocol = (url: string): { endpoint: string, protocol: string } => {
|
||||
if (url.startsWith('http://')) {
|
||||
return { endpoint: url.substring(7), protocol: 'http://' }
|
||||
} else if (url.startsWith('https://')) {
|
||||
return { endpoint: url.substring(8), protocol: 'https://' }
|
||||
}
|
||||
return { endpoint: url, protocol: 'http://' }
|
||||
}
|
||||
/** 按规则拼接当前默认domain */
|
||||
const defaultDomain = computed(() => {
|
||||
const { endpoint: initialEndpoint, bucketName, domain, type } = form
|
||||
if (domain || type !== 1 || !initialEndpoint || !bucketName) {
|
||||
return
|
||||
}
|
||||
const { endpoint, protocol } = stripProtocol(initialEndpoint)
|
||||
return isIPv4(endpoint) ? `${protocol}${endpoint}/${bucketName}/` : `${protocol}${bucketName}.${endpoint}/`
|
||||
})
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formRef.value?.resetFields()
|
||||
resetForm()
|
||||
}
|
||||
|
||||
// 保存
|
||||
const save = async () => {
|
||||
try {
|
||||
const isInvalid = await formRef.value?.validate()
|
||||
if (isInvalid) return false
|
||||
const data = {
|
||||
...form,
|
||||
secretKey: form.type === 1 && !form.secretKey.includes('*') ? encryptByRsa(form.secretKey) : null,
|
||||
domain: form.domain || defaultDomain.value,
|
||||
}
|
||||
if (isUpdate.value) {
|
||||
await updateStorage(data, dataId.value)
|
||||
Message.success('修改成功')
|
||||
} else {
|
||||
await addStorage(data)
|
||||
Message.success('新增成功')
|
||||
}
|
||||
emit('save-success')
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
reset()
|
||||
dataId.value = ''
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = async (id: string) => {
|
||||
reset()
|
||||
dataId.value = id
|
||||
const { data } = await getStorage(id)
|
||||
Object.assign(form, data)
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
defineExpose({ onAdd, onUpdate })
|
||||
</script>
|
@@ -1,153 +0,0 @@
|
||||
<template>
|
||||
<div class="gi_table_page">
|
||||
<GiTable
|
||||
title=""
|
||||
row-key="id"
|
||||
:data="dataList"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1300 }"
|
||||
:pagination="pagination"
|
||||
:disabled-tools="['size']"
|
||||
:disabled-column-keys="['name']"
|
||||
@refresh="search"
|
||||
>
|
||||
<template #toolbar-left>
|
||||
<a-input-search v-model="queryForm.description" placeholder="搜索名称/编码/描述" allow-clear @search="search" />
|
||||
<a-select
|
||||
v-model="queryForm.status"
|
||||
:options="DisEnableStatusList"
|
||||
placeholder="请选择状态"
|
||||
allow-clear
|
||||
style="width: 150px"
|
||||
@change="search"
|
||||
/>
|
||||
<a-button @click="reset">
|
||||
<template #icon><icon-refresh /></template>
|
||||
<template #default>重置</template>
|
||||
</a-button>
|
||||
</template>
|
||||
<template #toolbar-right>
|
||||
<a-button v-permission="['system:storage:add']" type="primary" @click="onAdd">
|
||||
<template #icon><icon-plus /></template>
|
||||
<template #default>新增</template>
|
||||
</a-button>
|
||||
</template>
|
||||
<template #name="{ record }">
|
||||
<a-space fill>
|
||||
<span>{{ record.name }}</span>
|
||||
<a-tag v-if="record.isDefault" color="arcoblue" size="small" class="gi_round">
|
||||
<template #default>默认</template>
|
||||
</a-tag>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #type="{ record }">
|
||||
<GiCellTag :value="record.type" :dict="storage_type_enum" />
|
||||
</template>
|
||||
<template #status="{ record }">
|
||||
<GiCellStatus :status="record.status" />
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<a-space>
|
||||
<a-link v-permission="['system:storage:update']" title="修改" @click="onUpdate(record)">修改</a-link>
|
||||
<a-link
|
||||
v-permission="['system:storage:delete']"
|
||||
status="danger"
|
||||
:disabled="record.isDefault"
|
||||
:title="record.isDefault ? '默认存储不能删除' : '删除'"
|
||||
@click="onDelete(record)"
|
||||
>
|
||||
删除
|
||||
</a-link>
|
||||
</a-space>
|
||||
</template>
|
||||
</GiTable>
|
||||
|
||||
<StorageAddDrawer ref="StorageAddDrawerRef" @save-success="search" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import StorageAddDrawer from './StorageAddDrawer.vue'
|
||||
import { type StorageQuery, type StorageResp, deleteStorage, listStorage } from '@/apis/system/storage'
|
||||
import type { TableInstanceColumns } from '@/components/GiTable/type'
|
||||
import { DisEnableStatusList } from '@/constant/common'
|
||||
import { useTable } from '@/hooks'
|
||||
import { useDict } from '@/hooks/app'
|
||||
import { isMobile } from '@/utils'
|
||||
import has from '@/utils/has'
|
||||
|
||||
defineOptions({ name: 'SystemStorage' })
|
||||
|
||||
const { storage_type_enum } = useDict('storage_type_enum')
|
||||
|
||||
const queryForm = reactive<StorageQuery>({
|
||||
sort: ['createTime,desc'],
|
||||
})
|
||||
|
||||
const {
|
||||
tableData: dataList,
|
||||
loading,
|
||||
pagination,
|
||||
search,
|
||||
handleDelete,
|
||||
} = useTable((page) => listStorage({ ...queryForm, ...page }), { immediate: true })
|
||||
const columns: TableInstanceColumns[] = [
|
||||
{
|
||||
title: '序号',
|
||||
width: 66,
|
||||
align: 'center',
|
||||
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 },
|
||||
{ title: '状态', dataIndex: 'status', slotName: 'status', align: 'center' },
|
||||
{ title: '类型', dataIndex: 'type', slotName: 'type', align: 'center', ellipsis: true, tooltip: true },
|
||||
{ title: '访问密钥', dataIndex: 'accessKey', ellipsis: true, tooltip: true },
|
||||
{ title: '终端节点', dataIndex: 'endpoint', ellipsis: true, tooltip: true },
|
||||
{ title: '桶名称', dataIndex: 'bucketName', ellipsis: true, tooltip: true },
|
||||
{ title: '域名', dataIndex: 'domain', ellipsis: true, tooltip: true },
|
||||
{ title: '描述', dataIndex: 'description', ellipsis: true, tooltip: true },
|
||||
{ title: '创建人', dataIndex: 'createUserString', ellipsis: true, tooltip: true, show: false },
|
||||
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
|
||||
{ title: '修改人', dataIndex: 'updateUserString', ellipsis: true, tooltip: true, show: false },
|
||||
{ title: '修改时间', dataIndex: 'updateTime', width: 180, show: false },
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
slotName: 'action',
|
||||
width: 130,
|
||||
align: 'center',
|
||||
fixed: !isMobile() ? 'right' : undefined,
|
||||
show: has.hasPermOr(['system:storage:update', 'system:storage:delete']),
|
||||
},
|
||||
]
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
queryForm.description = undefined
|
||||
queryForm.status = undefined
|
||||
search()
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onDelete = (record: StorageResp) => {
|
||||
return handleDelete(() => deleteStorage(record.id), {
|
||||
content: `是否确定删除存储「${record.name}」?`,
|
||||
showModal: true,
|
||||
})
|
||||
}
|
||||
|
||||
const StorageAddDrawerRef = ref<InstanceType<typeof StorageAddDrawer>>()
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
StorageAddDrawerRef.value?.onAdd()
|
||||
}
|
||||
|
||||
// 修改
|
||||
const onUpdate = (record: StorageResp) => {
|
||||
StorageAddDrawerRef.value?.onUpdate(record.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@@ -1,14 +0,0 @@
|
||||
export interface StorageReq {
|
||||
name: string
|
||||
code: string
|
||||
type: number
|
||||
accessKey: string
|
||||
secretKey: string
|
||||
endpoint: string
|
||||
bucketName: string
|
||||
domain: string
|
||||
sort: number
|
||||
description: string
|
||||
isDefault: boolean
|
||||
status: 1 | 2
|
||||
}
|
Reference in New Issue
Block a user