refactor: 更换 ESLint 配置为 @antfu/eslint-config

This commit is contained in:
2024-05-10 22:29:45 +08:00
parent 5101dd12d9
commit bfc8e42bad
148 changed files with 7314 additions and 5046 deletions

View File

@@ -85,7 +85,7 @@
v-model.trim="form.site_copyright"
placeholder="请输入版权信息"
:auto-size="{
minRows: 3
minRows: 3,
}"
show-word-limit
/>
@@ -130,8 +130,8 @@
</template>
<script lang="ts" setup>
import { listOption, updateOption, resetOptionValue, uploadFile, type OptionResp } from '@/apis'
import { Message, Modal, type FileItem, type FormInstance, type RequestOption } from '@arco-design/web-vue'
import { type FileItem, type FormInstance, Message, Modal, type RequestOption } from '@arco-design/web-vue'
import { type OptionResp, listOption, resetOptionValue, updateOption, uploadFile } from '@/apis'
import { useAppStore } from '@/stores'
import { useForm } from '@/hooks'

View File

@@ -1,5 +1,5 @@
<template>
<a-form style="margin-top: 20px" ref="formRef" :model="form" size="small" label-align="left" :disabled="!isUpdate">
<a-form ref="formRef" style="margin-top: 20px" :model="form" size="small" label-align="left" :disabled="!isUpdate">
<a-list size="small" :bordered="false">
<a-list-item style="border: none">
<a-form-item
@@ -7,43 +7,43 @@
:label="form.password_expiration_days.name"
field="password_expiration_days"
>
<a-input-number class="input-width" :min="0" :max="999" v-model="form.password_expiration_days.value">
<a-input-number v-model="form.password_expiration_days.value" class="input-width" :min="0" :max="999">
<template #append></template>
</a-input-number>
</a-form-item>
</a-list-item>
<a-list-item style="border: none">
<a-form-item :help="form.password_min_length.description" :label="form.password_min_length.name">
<a-input-number class="input-width" :min="8" :max="32" v-model="form.password_min_length.value" />
<a-input-number v-model="form.password_min_length.value" class="input-width" :min="8" :max="32" />
</a-form-item>
</a-list-item>
<a-list-item style="border: none">
<a-form-item :help="form.password_update_interval.description" :label="form.password_update_interval.name">
<a-input-number class="input-width" :min="0" :max="9999" v-model="form.password_update_interval.value">
<a-input-number v-model="form.password_update_interval.value" class="input-width" :min="0" :max="9999">
<template #append>分钟</template>
</a-input-number>
</a-form-item>
</a-list-item>
<a-list-item style="border: none">
<a-form-item :help="form.password_error_count.description" :label="form.password_error_count.name">
<a-input-number class="input-width" :min="0" :max="9999" v-model="form.password_error_count.value" />
<a-input-number v-model="form.password_error_count.value" class="input-width" :min="0" :max="9999" />
</a-form-item>
</a-list-item>
<a-list-item style="border: none">
<a-form-item :help="form.password_lock_minutes.description" :label="form.password_lock_minutes.name">
<a-input-number class="input-width" :min="0" :max="9999" v-model="form.password_lock_minutes.value">
<a-input-number v-model="form.password_lock_minutes.value" class="input-width" :min="0" :max="9999">
<template #append>分钟</template>
</a-input-number>
</a-form-item>
</a-list-item>
<a-list-item style="border: none">
<a-form-item :help="form.password_special_char.description" :label="form.password_special_char.name">
<a-switch type="round" :checked-value="1" :unchecked-value="0" v-model="form.password_special_char.value" />
<a-switch v-model="form.password_special_char.value" type="round" :checked-value="1" :unchecked-value="0" />
</a-form-item>
</a-list-item>
<a-list-item style="border: none">
<a-form-item :help="form.password_contain_name.description" :label="form.password_contain_name.name">
<a-switch type="round" :checked-value="1" :unchecked-value="0" v-model="form.password_contain_name.value" />
<a-switch v-model="form.password_contain_name.value" type="round" :checked-value="1" :unchecked-value="0" />
</a-form-item>
</a-list-item>
<a-list-item style="padding-top: 13px; border: none">
@@ -85,8 +85,8 @@
</template>
<script setup lang="ts">
import { listOption, updateOption, resetOptionValue, type SecurityConfigResp, type OptionResp } from '@/apis'
import { Message, Modal, type FormInstance } from '@arco-design/web-vue'
import { type FormInstance, Message, Modal } from '@arco-design/web-vue'
import { type OptionResp, type SecurityConfigResp, listOption, resetOptionValue, updateOption } from '@/apis'
const formRef = ref<FormInstance>()
@@ -100,23 +100,12 @@ const form = ref<SecurityConfigResp>({
password_update_interval: {}
})
// 重置
const reset = () => {
getDataList()
}
const isUpdate = ref(false)
// 修改
const onUpdate = () => {
isUpdate.value = true
}
// 取消
const handleCancel = () => {
reset()
isUpdate.value = false
}
const queryForm = {
code: Object.keys(form.value)
}
@@ -124,11 +113,22 @@ const queryForm = {
const getDataList = async () => {
const { data } = await listOption(queryForm)
form.value = data.reduce((obj: SecurityConfigResp, option: OptionResp) => {
obj[option.code] = { ...option, value: parseInt(option.value) }
obj[option.code] = { ...option, value: Number.parseInt(option.value) }
return obj
}, {})
}
// 重置
const reset = () => {
getDataList()
}
// 取消
const handleCancel = () => {
reset()
isUpdate.value = false
}
// 保存
const handleSave = async () => {
await updateOption(

View File

@@ -14,13 +14,17 @@
</template>
<script setup lang="ts">
import { getDept, addDept, updateDept } from '@/apis'
import type { DeptReq } from './type'
import { Message } from '@arco-design/web-vue'
import { GiForm, type Columns } from '@/components/GiForm'
import type { DeptReq } from './type'
import { addDept, getDept, updateDept } from '@/apis'
import { type Columns, GiForm } from '@/components/GiForm'
import { useForm } from '@/hooks'
import { useDept } from '@/hooks/app'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { deptList, getDeptList } = useDept()
const dataId = ref('')
@@ -49,7 +53,7 @@ const columns: Columns = [
fallbackOption: false,
filterTreeNode(searchKey, nodeData) {
if (nodeData.title) {
return nodeData.title.toLowerCase().indexOf(searchKey.toLowerCase()) > -1
return nodeData.title.toLowerCase().includes(searchKey.toLowerCase())
}
return false
}
@@ -147,9 +151,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -9,8 +9,8 @@
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
:pagination="false"
:disabledTools="['size']"
:disabledColumnKeys="['name']"
:disabled-tools="['size']"
:disabled-column-keys="['name']"
@refresh="search"
>
<template #expand-icon="{ expanded }">
@@ -80,9 +80,9 @@
</template>
<script setup lang="ts">
import { listDept, deleteDept, exportDept, type DeptResp, type DeptQuery } from '@/apis'
import DeptAddModal from './DeptAddModal.vue'
import { Message } from '@arco-design/web-vue'
import DeptAddModal from './DeptAddModal.vue'
import { type DeptQuery, type DeptResp, deleteDept, exportDept, listDept } from '@/apis'
import type GiTable from '@/components/GiTable/index.vue'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useDownload } from '@/hooks'

View File

@@ -14,11 +14,14 @@
</template>
<script setup lang="ts">
import { getDict, addDict, updateDict } from '@/apis'
import { Message } from '@arco-design/web-vue'
import { GiForm, type Columns } from '@/components/GiForm'
import { addDict, getDict, updateDict } from '@/apis'
import { type Columns, GiForm } from '@/components/GiForm'
import { useForm } from '@/hooks'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const dataId = ref('')
const isUpdate = computed(() => !!dataId.value)
const title = computed(() => (isUpdate.value ? '修改字典' : '新增字典'))
@@ -91,9 +94,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -8,8 +8,8 @@
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
:pagination="pagination"
:disabledTools="['size']"
:disabledColumnKeys="['name']"
:disabled-tools="['size']"
:disabled-column-keys="['name']"
@refresh="search"
>
<template #custom-left>
@@ -52,8 +52,8 @@
</template>
<script setup lang="ts">
import { listDict, deleteDict, type DictResp, type DictQuery } from '@/apis'
import DictAddModal from './DictAddModal.vue'
import { type DictQuery, type DictResp, deleteDict, listDict } from '@/apis'
import DictItemModal from '@/views/system/dict/item/index.vue'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useTable } from '@/hooks'
@@ -62,6 +62,24 @@ import has from '@/utils/has'
defineOptions({ name: 'SystemDict' })
const queryForm = reactive<DictQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listDict({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.description = undefined
search()
}
const columns: TableInstanceColumns[] = [
{
title: '序号',
@@ -87,24 +105,6 @@ const columns: TableInstanceColumns[] = [
}
]
const queryForm = reactive<DictQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listDict({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.description = undefined
search()
}
// 删除
const onDelete = (item: DictResp) => {
return handleDelete(() => deleteDict(item.id), { content: `是否确定删除字典 [${item.name}]`, showModal: true })

View File

@@ -22,11 +22,14 @@
</template>
<script setup lang="ts">
import { getDictItem, addDictItem, updateDictItem } from '@/apis'
import { Message } from '@arco-design/web-vue'
import { GiForm, type Columns } from '@/components/GiForm'
import { addDictItem, getDictItem, updateDictItem } from '@/apis'
import { type Columns, GiForm } from '@/components/GiForm'
import { useForm } from '@/hooks'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const dictId = ref('')
const dataId = ref('')
const isUpdate = computed(() => !!dataId.value)
@@ -126,9 +129,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -1,7 +1,7 @@
<template>
<a-modal
v-model:visible="visible"
:title="'字典项管理(' + dictCode + ')'"
:title="`字典项管理(${dictCode})`"
title-align="start"
:mask-closable="false"
:esc-to-close="false"
@@ -11,15 +11,14 @@
hide-cancel
>
<GiTable
ref="tableRef"
row-key="id"
:data="dataList"
:columns="columns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 800 }"
:pagination="pagination"
:disabledTools="['size']"
:disabledColumnKeys="['label']"
:disabled-tools="['size']"
:disabled-column-keys="['label']"
@refresh="search"
>
<template #custom-left>
@@ -63,14 +62,38 @@
</template>
<script lang="ts" setup>
import { listDictItem, deleteDictItem, type DictItemResp, type DictItemQuery } from '@/apis'
import { useWindowSize } from '@vueuse/core'
import DictItemAddModal from './DictItemAddModal.vue'
import { type DictItemQuery, type DictItemResp, deleteDictItem, listDictItem } from '@/apis'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useTable } from '@/hooks'
import { isMobile } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const dictId = ref('')
const queryForm = reactive<DictItemQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listDictItem({ ...queryForm, dictId: dictId.value, page: p.page, size: p.size }), {
immediate: true
})
// 重置
const reset = () => {
queryForm.description = undefined
queryForm.status = undefined
search()
}
const columns: TableInstanceColumns[] = [
{
title: '序号',
@@ -99,11 +122,6 @@ const columns: TableInstanceColumns[] = [
{ title: '操作', slotName: 'action', width: 130, align: 'center', fixed: !isMobile() ? 'right' : undefined }
]
const queryForm = reactive<DictItemQuery>({
sort: ['createTime,desc']
})
const dictId = ref('')
const dictCode = ref('')
const visible = ref(false)
// 打开
@@ -116,23 +134,6 @@ const open = (id: string, code: string) => {
}
defineExpose({ open })
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listDictItem({ ...queryForm, dictId: dictId.value, page: p.page, size: p.size }), {
immediate: true
})
// 重置
const reset = () => {
queryForm.description = undefined
queryForm.status = undefined
search()
}
// 删除
const onDelete = (item: DictItemResp) => {
return handleDelete(() => deleteDictItem(item.id), { content: `是否确定删除 [${item.label}]`, showModal: false })

View File

@@ -20,7 +20,7 @@
</template>
<script setup lang="ts">
import { useDraggable, useWindowSize, useElementSize } from '@vueuse/core'
import { useDraggable, useElementSize, useWindowSize } from '@vueuse/core'
import type { FileItem } from '@/apis'
interface Props {
@@ -71,8 +71,8 @@ const audioStyle = computed(() => {
}
sessionStorage.setItem('AudioDialogXY', JSON.stringify({ top, left }))
return {
left: left + 'px',
top: top + 'px'
left: `${left}px`,
top: `${top}px`
}
})

View File

@@ -2,9 +2,8 @@ import type { Component } from 'vue'
import { createApp } from 'vue'
import ArcoVueIcon from '@arco-design/web-vue/es/icon'
import ArcoVue from '@arco-design/web-vue'
import type { FileItem } from '@/apis'
import ModalContent from './ModalContent.vue'
import type { FileItem } from '@/apis'
function createModal<T extends { callback?: () => void }>(component: Component, options?: T) {
// 创建一个挂载容器
@@ -28,7 +27,7 @@ function createModal<T extends { callback?: () => void }>(component: Component,
instance.use(ArcoVueIcon)
instance.mount(el)
}
type TFileOptions = { data: FileItem; callback?: () => void }
type TFileOptions = { data: FileItem, callback?: () => void }
/** 预览 音频文件 弹窗 */
let fileAudioId = ''
@@ -36,7 +35,7 @@ export function previewFileAudioModal(data: FileItem) {
if (fileAudioId) return // 防止重复打开
fileAudioId = data.id
return createModal<TFileOptions>(ModalContent, {
data: data,
data,
// 关闭的回调
callback: () => {
fileAudioId = ''

View File

@@ -14,8 +14,8 @@
</template>
<script setup lang="ts">
import type { FileItem } from '@/apis'
import FileImage from '../../main/FileMain/FileImage.vue'
import type { FileItem } from '@/apis'
import { formatFileSize } from '@/utils'
interface Props {

View File

@@ -1,7 +1,7 @@
import type { FileItem } from '@/apis'
import { h } from 'vue'
import { Modal } from '@arco-design/web-vue'
import ModalContent from './ModalContent.vue'
import type { FileItem } from '@/apis'
/** 打开 详情 弹窗 */
export function openFileDetailModal(fileItem: FileItem) {

View File

@@ -14,8 +14,8 @@
</template>
<script lang="ts" setup>
import type { FileItem } from '@/apis'
import type { FormInstance } from '@arco-design/web-vue'
import type { FileItem } from '@/apis'
interface Props {
data: FileItem

View File

@@ -1,7 +1,7 @@
import { updateFile, type FileItem } from '@/apis'
import { ref, h } from 'vue'
import { Modal, Message } from '@arco-design/web-vue'
import { h, ref } from 'vue'
import { Message, Modal } from '@arco-design/web-vue'
import ModalContent from './ModalContent.vue'
import { type FileItem, updateFile } from '@/apis'
export function openFileRenameModal(data: FileItem, callback?: () => void) {
const ModalContentRef = ref<InstanceType<typeof ModalContent>>()

View File

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

View File

@@ -15,21 +15,21 @@
</template>
<script setup lang="ts">
import { getFileStatistics, type FileStatisticsResp } from '@/apis'
import { useChart } from '@/hooks'
import { FileTypeList } from '@/constant/file'
import VCharts from 'vue-echarts'
import { use } from 'echarts/core'
import { PieChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { LegendComponent, TitleComponent, TooltipComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
import { FileTypeList } from '@/constant/file'
import { useChart } from '@/hooks'
import { type FileStatisticsResp, getFileStatistics } from '@/apis'
import { formatFileSize } from '@/utils'
use([TitleComponent, TooltipComponent, LegendComponent, PieChart, CanvasRenderer])
const totalData = ref<FileStatisticsResp>({})
const chartData = ref<Array<FileStatisticsResp>>([])
const statisticValueStyle = { color: '#5856D6', 'font-size': '18px' }
const statisticValueStyle = { 'color': '#5856D6', 'font-size': '18px' }
const { option } = useChart(() => {
return {
grid: {
@@ -50,7 +50,7 @@ const { option } = useChart(() => {
},
tooltip: {
show: true,
formatter: function (params) {
formatter(params) {
return `总计:${params.value}<br>${params.data.size}`
}
},
@@ -78,12 +78,12 @@ const getStatisticsData = async () => {
const { data: resData } = await getFileStatistics()
const formatSize = formatFileSize(resData.size).split(' ')
totalData.value = {
size: parseFloat(formatSize[0]),
size: Number.parseFloat(formatSize[0]),
number: resData.number,
unit: formatSize[1]
}
resData.data.forEach((fs: FileStatisticsResp) => {
const matchedItem = FileTypeList.find((item) => item.value == fs.type)
const matchedItem = FileTypeList.find((item) => item.value === fs.type)
chartData.value.unshift({
name: matchedItem ? matchedItem.name : '',
value: fs.number,

View File

@@ -46,7 +46,7 @@
<a-table-column title="修改时间" data-index="updateTime" :width="200"></a-table-column>
<a-table-column title="操作" :width="120" align="center">
<template #cell="{ record }">
<a-popover trigger="click" position="bottom" :content-style="{ padding: 0, 'margin-top': 0 }">
<a-popover trigger="click" position="bottom" :content-style="{ 'padding': 0, 'margin-top': 0 }">
<a-button type="text" @click.stop><icon-more :size="16" /></a-button>
<template #content>
<FileRightMenu
@@ -64,10 +64,10 @@
</template>
<script setup lang="ts">
import type { FileItem } from '@/apis'
import type { TableRowSelection, TableInstance } from '@arco-design/web-vue'
import type { TableInstance, TableRowSelection } from '@arco-design/web-vue'
import FileImage from './FileImage.vue'
import FileRightMenu from './FileRightMenu.vue'
import type { FileItem } from '@/apis'
import { formatFileSize } from '@/utils'
interface Props {
@@ -82,17 +82,17 @@ const props = withDefaults(defineProps<Props>(), {
isBatchMode: false // 是否是批量模式
})
const rowSelection: TableRowSelection = reactive({
type: 'checkbox',
showCheckedAll: true
})
const emit = defineEmits<{
(e: 'click', record: FileItem): void
(e: 'select', record: FileItem): void
(e: 'right-menu-click', mode: string, item: FileItem): void
}>()
const rowSelection: TableRowSelection = reactive({
type: 'checkbox',
showCheckedAll: true
})
// 多选
const select: TableInstance['onSelect'] = (rowKeys, rowKey, record) => {
emit('select', record as unknown as FileItem)

View File

@@ -68,7 +68,7 @@
<!-- 文件列表-宫格模式 -->
<a-spin id="fileMain" class="file-main__list" :loading="loading" @scroll="handleScroll">
<FileGrid
v-show="fileList.length && mode == 'grid'"
v-show="fileList.length && mode === 'grid'"
:data="fileList"
:is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds"
@@ -79,7 +79,7 @@
<!-- 文件列表-列表模式 -->
<FileList
v-show="fileList.length && mode == 'list'"
v-show="fileList.length && mode === 'list'"
:data="fileList"
:is-batch-mode="isBatchMode"
:selected-file-ids="selectedFileIds"
@@ -94,48 +94,22 @@
</template>
<script setup lang="ts">
import { listFile, uploadFile, deleteFile, type FileItem, type FileQuery, type FilePageQuery } from '@/apis'
import { Message, Modal, type RequestOption } from '@arco-design/web-vue'
import FileGrid from './FileGrid.vue'
import { api as viewerApi } from 'v-viewer'
import {
openFileDetailModal,
openFileRenameModal,
previewFileVideoModal,
previewFileAudioModal
previewFileAudioModal,
previewFileVideoModal
} from '../../components/index'
import FileGrid from './FileGrid.vue'
import useFileManage from './useFileManage'
import { type FileItem, type FilePageQuery, type FileQuery, deleteFile, listFile, uploadFile } from '@/apis'
import { ImageTypes } from '@/constant/file'
import { api as viewerApi } from 'v-viewer'
import 'viewerjs/dist/viewer.css'
import { downloadByUrl } from '@/utils/downloadFile'
const FileList = defineAsyncComponent(() => import('./FileList.vue'))
onMounted(() => {
const fileMainDom = document.getElementById('fileMain')
fileMainDom.addEventListener('scrool', handleScroll)
console.table('fileMainDom', fileMainDom)
})
onUnmounted(() => {
// 移除事件监听
const fileMainDom = document.getElementById('fileMain')
fileMainDom.removeEventListener('scroll', handleScroll)
})
const timer = ref<any>()
const handleScroll = (event) => {
const { clientHeight, scrollHeight, scrollTop } = event.target
const scrollLinerHeight = (clientHeight / scrollHeight) * scrollHeight
if (!timer.value) {
timer.value = setTimeout(() => {
if ((scrollTop + scrollLinerHeight) / scrollHeight >= 0.9 && !loading.value) {
++pagination.page
getFileList()
}
timer.value = null
}, 1000)
}
console.log('event', event)
}
const route = useRoute()
const { mode, selectedFileIds, toggleMode, addSelectedFileItem } = useFileManage()
@@ -148,9 +122,11 @@ const pagination = reactive({
page: 1,
size: 30
})
const fileList = ref<FileItem[]>([])
const isBatchMode = ref(false)
const loading = ref(false)
const timer = ref<any>()
// 查询文件列表
const getFileList = async (query: FilePageQuery = { ...queryForm, page: pagination.page, size: pagination.size }) => {
try {
@@ -179,6 +155,12 @@ const getFileList = async (query: FilePageQuery = { ...queryForm, page: paginati
}
}
// 查询
const search = () => {
pagination.page = 1
getFileList()
}
// 点击文件
const handleClickFile = (item: FileItem) => {
if (ImageTypes.includes(item.extension)) {
@@ -222,7 +204,6 @@ const handleRightMenuClick = async (mode: string, fileInfo: FileItem) => {
} else if (mode === 'detail') {
openFileDetailModal(fileInfo)
} else if (mode === 'download') {
console.log('fileInfo', fileInfo)
const res = await downloadByUrl({
url: fileInfo.url,
target: '_self',
@@ -276,12 +257,30 @@ const handleUpload = (options: RequestOption) => {
}
}
// 查询
const search = () => {
pagination.page = 1
getFileList()
const handleScroll = (event) => {
const { clientHeight, scrollHeight, scrollTop } = event.target
const scrollLinerHeight = (clientHeight / scrollHeight) * scrollHeight
if (!timer.value) {
timer.value = setTimeout(() => {
if ((scrollTop + scrollLinerHeight) / scrollHeight >= 0.9 && !loading.value) {
++pagination.page
getFileList()
}
timer.value = null
}, 1000)
}
}
onMounted(() => {
const fileMainDom = document.getElementById('fileMain')
fileMainDom.addEventListener('scrool', handleScroll)
})
onUnmounted(() => {
// 移除事件监听
const fileMainDom = document.getElementById('fileMain')
fileMainDom.removeEventListener('scroll', handleScroll)
})
onBeforeRouteUpdate((to) => {
if (!to.query.type) return
queryForm.type = to.query.type?.toString()

View File

@@ -1,4 +1,4 @@
import { ref, computed } from 'vue'
import { computed, ref } from 'vue'
import type { FileItem } from '@/apis'
type Mode = 'grid' | 'list'

View File

@@ -26,10 +26,10 @@
allow-search
:data="(menuSelectTree as any)"
:fallback-option="false"
:fieldNames="{
:field-names="{
key: 'id',
title: 'title',
children: 'children'
children: 'children',
}"
/>
</a-form-item>
@@ -120,12 +120,12 @@
</template>
<script setup lang="ts">
import { getMenu, addMenu, updateMenu, type MenuResp } from '@/apis'
import { type FormInstance, Message } from '@arco-design/web-vue'
import { mapTree } from 'xe-utils'
import type { MenuForm } from './type'
import { Message, type FormInstance } from '@arco-design/web-vue'
import { type MenuResp, addMenu, getMenu, updateMenu } from '@/apis'
import { useForm } from '@/hooks'
import { filterTree, transformPathToName } from '@/utils'
import { mapTree } from 'xe-utils'
interface Props {
menus: MenuResp[]
@@ -134,6 +134,10 @@ const props = withDefaults(defineProps<Props>(), {
menus: () => []
})
const emit = defineEmits<{
(e: 'save-success'): void
}>()
// 转换为菜单树
const menuSelectTree = computed(() => {
const menus = JSON.parse(JSON.stringify(props.menus)) as MenuResp[]
@@ -176,6 +180,7 @@ const { form, resetForm } = useForm<MenuForm>({
status: 1
})
const componentName = computed(() => transformPathToName(form.path))
// eslint-disable-next-line vue/return-in-computed-property
const formRules = computed(() => {
if ([1, 2].includes(form.type)) {
const { title, name, path } = rules
@@ -239,9 +244,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -9,7 +9,7 @@
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1700, maxHeight: '81vh' }"
:pagination="false"
:disabledColumnKeys="['title']"
:disabled-column-keys="['title']"
@refresh="search"
>
<template #expand-icon="{ expanded }">
@@ -92,9 +92,9 @@
</template>
<script setup lang="ts">
import { listMenu, deleteMenu, type MenuResp, type MenuQuery } from '@/apis'
import MenuAddModal from './MenuAddModal.vue'
import { Message } from '@arco-design/web-vue'
import MenuAddModal from './MenuAddModal.vue'
import { type MenuQuery, type MenuResp, deleteMenu, listMenu } from '@/apis'
import type GiTable from '@/components/GiTable/index.vue'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { DisEnableStatusList } from '@/constant/common'

View File

@@ -64,13 +64,16 @@
</template>
<script setup lang="ts">
import { addNotice, updateNotice, getNotice } from '@/apis'
import { Message, type FormInstance } from '@arco-design/web-vue'
import { useForm } from '@/hooks'
import { useDict } from '@/hooks/app'
import { type FormInstance, Message } from '@arco-design/web-vue'
import { MdEditor } from 'md-editor-v3'
import { useWindowSize } from '@vueuse/core'
import { addNotice, getNotice, updateNotice } from '@/apis'
import { useForm } from '@/hooks'
import { useDict } from '@/hooks/app'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const { notice_type } = useDict('notice_type')
@@ -169,10 +172,6 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -23,7 +23,7 @@
</a-typography-paragraph>
</a-typography>
<a-divider />
<MdPreview :editorId="dataDetail?.id" :modelValue="dataDetail?.content" />
<MdPreview :editor-id="dataDetail?.id" :model-value="dataDetail?.content" />
<a-divider />
<div v-if="dataDetail?.updateTime" class="update-time-row">
<span>
@@ -36,9 +36,9 @@
</template>
<script setup lang="ts">
import { getNotice, type NoticeResp } from '@/apis'
import { MdPreview } from 'md-editor-v3'
import { useWindowSize } from '@vueuse/core'
import { type NoticeResp, getNotice } from '@/apis'
const { width } = useWindowSize()
const dataDetail = ref<NoticeResp>()

View File

@@ -9,8 +9,8 @@
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
:pagination="pagination"
:disabledTools="['size']"
:disabledColumnKeys="['title']"
:disabled-tools="['size']"
:disabled-column-keys="['title']"
@refresh="search"
>
<template #custom-left>
@@ -58,9 +58,9 @@
</template>
<script lang="ts" setup>
import { listNotice, deleteNotice, type NoticeResp, type NoticeQuery } from '@/apis'
import NoticeAddModal from './NoticeAddModal.vue'
import NoticeDetailModal from './NoticeDetailModal.vue'
import { type NoticeQuery, type NoticeResp, deleteNotice, listNotice } from '@/apis'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useTable } from '@/hooks'
import { useDict } from '@/hooks/app'
@@ -71,6 +71,25 @@ defineOptions({ name: 'SystemNotice' })
const { notice_type, notice_status_enum } = useDict('notice_type', 'notice_status_enum')
const queryForm = reactive<NoticeQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listNotice({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.title = undefined
queryForm.type = undefined
search()
}
const columns: TableInstanceColumns[] = [
{
title: '序号',
@@ -95,25 +114,6 @@ const columns: TableInstanceColumns[] = [
}
]
const queryForm = reactive<NoticeQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listNotice({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.title = undefined
queryForm.type = undefined
search()
}
// 删除
const onDelete = (item: NoticeResp) => {
return handleDelete(() => deleteNotice(item.id), {

View File

@@ -86,12 +86,15 @@
</template>
<script setup lang="ts">
import { getRole, addRole, updateRole } from '@/apis'
import { Message, type FormInstance, type TreeNodeData } from '@arco-design/web-vue'
import { useForm } from '@/hooks'
import { useDict, useMenu, useDept } from '@/hooks/app'
import { type FormInstance, Message, type TreeNodeData } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { addRole, getRole, updateRole } from '@/apis'
import { useForm } from '@/hooks'
import { useDept, useDict, useMenu } from '@/hooks/app'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const { data_scope_enum } = useDict('data_scope_enum')
const { deptList, getDeptList } = useDept()
@@ -239,10 +242,6 @@ const onCheckAll = (type: string) => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -22,7 +22,6 @@
>
<a-descriptions-item :span="2">
<a-tree
ref="menuTreeRef"
:checked-keys="dataDetail?.menuIds"
:data="menuList"
default-expand-all
@@ -41,7 +40,6 @@
>
<a-descriptions-item :span="2">
<a-tree
ref="deptTreeRef"
:checked-keys="dataDetail?.deptIds"
:data="deptList"
default-expand-all
@@ -54,9 +52,9 @@
</template>
<script lang="ts" setup>
import { getRole, type RoleDetailResp } from '@/apis'
import { useDict, useMenu, useDept } from '@/hooks/app'
import { useWindowSize } from '@vueuse/core'
import { type RoleDetailResp, getRole } from '@/apis'
import { useDept, useDict, useMenu } from '@/hooks/app'
const { width } = useWindowSize()
const { data_scope_enum } = useDict('data_scope_enum')

View File

@@ -8,8 +8,8 @@
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
:pagination="pagination"
:disabledTools="['size']"
:disabledColumnKeys="['name']"
:disabled-tools="['size']"
:disabled-column-keys="['name']"
@refresh="search"
>
<template #custom-left>
@@ -57,9 +57,9 @@
</template>
<script setup lang="ts">
import { listRole, deleteRole, type RoleResp, type RoleQuery } from '@/apis'
import RoleAddModal from './RoleAddModal.vue'
import RoleDetailDrawer from './RoleDetailDrawer.vue'
import { type RoleQuery, type RoleResp, deleteRole, listRole } from '@/apis'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useTable } from '@/hooks'
import { useDict } from '@/hooks/app'
@@ -70,6 +70,24 @@ defineOptions({ name: 'SystemRole' })
const { data_scope_enum } = useDict('data_scope_enum')
const queryForm = reactive<RoleQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listRole({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.description = undefined
search()
}
const columns: TableInstanceColumns[] = [
{
title: '序号',
@@ -97,24 +115,6 @@ const columns: TableInstanceColumns[] = [
}
]
const queryForm = reactive<RoleQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listRole({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.description = undefined
search()
}
// 删除
const onDelete = (item: RoleResp) => {
return handleDelete(() => deleteRole(item.id), { content: `是否确定删除角色 [${item.name}]`, showModal: true })

View File

@@ -45,8 +45,8 @@
:rules="[
{
required: true,
message: '请输入域名'
}
message: '请输入域名',
},
]"
>
<a-input v-model.trim="form.domain" placeholder="请输入域名" />
@@ -88,14 +88,17 @@
</template>
<script setup lang="ts">
import { getStorage, addStorage, updateStorage } from '@/apis'
import { type FormInstance, Message } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import type { StorageReq } from './type'
import { Message, type FormInstance } from '@arco-design/web-vue'
import { addStorage, getStorage, updateStorage } from '@/apis'
import { useForm } from '@/hooks'
import { useDict } from '@/hooks/app'
import { useWindowSize } from '@vueuse/core'
import { encryptByRsa } from '@/utils/encrypt'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const { storage_type_enum } = useDict('storage_type_enum')
@@ -175,9 +178,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -8,8 +8,8 @@
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1300 }"
:pagination="pagination"
:disabledTools="['size']"
:disabledColumnKeys="['name']"
:disabled-tools="['size']"
:disabled-column-keys="['name']"
@refresh="search"
>
<template #custom-left>
@@ -68,8 +68,8 @@
</template>
<script setup lang="ts">
import { listStorage, deleteStorage, type StorageResp, type StorageQuery } from '@/apis'
import StorageAddModal from './StorageAddModal.vue'
import { type StorageQuery, type StorageResp, deleteStorage, listStorage } from '@/apis'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useTable } from '@/hooks'
import { useDict } from '@/hooks/app'
@@ -81,6 +81,25 @@ 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((p) => listStorage({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.description = undefined
queryForm.status = undefined
search()
}
const columns: TableInstanceColumns[] = [
{
title: '序号',
@@ -111,25 +130,6 @@ const columns: TableInstanceColumns[] = [
}
]
const queryForm = reactive<StorageQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listStorage({ ...queryForm, page: p.page, size: p.size }), { immediate: true })
// 重置
const reset = () => {
queryForm.description = undefined
queryForm.status = undefined
search()
}
// 删除
const onDelete = (item: StorageResp) => {
return handleDelete(() => deleteStorage(item.id), { content: `是否确定删除存储 [${item.name}]`, showModal: true })

View File

@@ -76,21 +76,24 @@
</template>
<script setup lang="ts">
import { getUser, addUser, updateUser } from '@/apis'
import { type FormInstance, Message, type TreeNodeData } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { addUser, getUser, updateUser } from '@/apis'
import type { Gender, Status } from '@/types/global'
import { Message, type FormInstance, type TreeNodeData } from '@arco-design/web-vue'
import { useForm } from '@/hooks'
import { useDept, useRole } from '@/hooks/app'
import { useWindowSize } from '@vueuse/core'
import { encryptByRsa } from '@/utils/encrypt'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const { roleList, getRoleList } = useRole()
const { deptList, getDeptList } = useDept()
// 过滤部门
const filterDeptOptions = (searchKey: string, nodeData: TreeNodeData) => {
if (nodeData.title) {
return nodeData.title.toLowerCase().indexOf(searchKey.toLowerCase()) > -1
return nodeData.title.toLowerCase().includes(searchKey.toLowerCase())
}
return false
}
@@ -182,9 +185,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onAdd, onUpdate })
</script>

View File

@@ -27,8 +27,8 @@
</template>
<script lang="ts" setup>
import { getUser, type UserDetailResp } from '@/apis'
import { useWindowSize } from '@vueuse/core'
import { type UserDetailResp, getUser } from '@/apis'
const { width } = useWindowSize()

View File

@@ -14,12 +14,15 @@
</template>
<script setup lang="ts">
import { resetUserPwd } from '@/apis'
import { Message } from '@arco-design/web-vue'
import { GiForm, type Columns } from '@/components/GiForm'
import { resetUserPwd } from '@/apis'
import { type Columns, GiForm } from '@/components/GiForm'
import { useForm } from '@/hooks'
import { encryptByRsa } from '@/utils/encrypt'
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const dataId = ref('')
const formRef = ref<InstanceType<typeof GiForm>>()
@@ -65,9 +68,5 @@ const save = async () => {
}
}
const emit = defineEmits<{
(e: 'save-success'): void
}>()
defineExpose({ onReset })
</script>

View File

@@ -19,15 +19,14 @@
</a-col>
<a-col :xs="24" :md="20" :lg="20" :xl="20" :xxl="20">
<GiTable
ref="tableRef"
row-key="id"
:data="dataList"
:columns="columns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1500 }"
:pagination="pagination"
:disabledTools="['size']"
:disabledColumnKeys="['username']"
:disabled-tools="['size']"
:disabled-column-keys="['username']"
@refresh="search"
>
<template #custom-left>
@@ -107,13 +106,13 @@
</template>
<script setup lang="ts">
import { listUser, deleteUser, exportUser, type UserResp, type UserQuery } from '@/apis'
import type { TreeInstance } from '@arco-design/web-vue'
import UserAddModal from './UserAddModal.vue'
import UserDetailDrawer from './UserDetailDrawer.vue'
import UserResetPwdModal from './UserResetPwdModal.vue'
import type { TreeInstance } from '@arco-design/web-vue'
import { type UserQuery, type UserResp, deleteUser, exportUser, listUser } from '@/apis'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useTable, useDownload } from '@/hooks'
import { useDownload, useTable } from '@/hooks'
import { useDept } from '@/hooks/app'
import { isMobile } from '@/utils'
import getAvatar from '@/utils/avatar'
@@ -122,6 +121,25 @@ import { DisEnableStatusList } from '@/constant/common'
defineOptions({ name: 'SystemUser' })
const queryForm = reactive<UserQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listUser({ ...queryForm, page: p.page, size: p.size }), { immediate: false })
// 重置
const reset = () => {
queryForm.description = undefined
queryForm.status = undefined
search()
}
const columns: TableInstanceColumns[] = [
{
title: '序号',
@@ -160,25 +178,6 @@ const columns: TableInstanceColumns[] = [
}
]
const queryForm = reactive<UserQuery>({
sort: ['createTime,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((p) => listUser({ ...queryForm, page: p.page, size: p.size }), { immediate: false })
// 重置
const reset = () => {
queryForm.description = undefined
queryForm.status = undefined
search()
}
// 删除
const onDelete = (item: UserResp) => {
return handleDelete(() => deleteUser(item.id), {