导出表格,升级依赖

This commit is contained in:
xiangheng
2024-02-20 19:33:51 +08:00
parent 65f1f09b70
commit ef9199c2cb
26 changed files with 302 additions and 241 deletions

View File

@@ -1,7 +1,8 @@
{ {
"name": "vue-project", "name": "x_admin",
"version": "0.0.0", "version": "0.0.1",
"license": "MIT", "license": "MIT",
"type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"prod": "vite build", "prod": "vite build",
@@ -13,54 +14,55 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"@highlightjs/vue-plugin": "^2.1.0", "@highlightjs/vue-plugin": "^2.1.0",
"@logicflow/core": "^1.2.18", "@logicflow/core": "^1.2.22",
"@logicflow/extension": "^1.2.19", "@logicflow/extension": "^1.2.22",
"@vue/shared": "^3.4.3", "@vue/shared": "^3.4.19",
"@vueuse/core": "^10.7.1", "@vueuse/core": "^10.7.2",
"@wangeditor/editor": "^5.1.23", "@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.6.3", "axios": "^1.6.7",
"consola": "^3.2.3", "consola": "^3.2.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"css-color-function": "^1.3.3", "css-color-function": "^1.3.3",
"echarts": "^5.4.3", "echarts": "^5.5.0",
"element-plus": "^2.4.4", "element-plus": "^2.5.6",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"query-string": "^8.2.0",
"vform3-builds": "^3.0.10", "vform3-builds": "^3.0.10",
"vue": "^3.4.3", "vue": "^3.4.19",
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.6.8", "vue-echarts": "^6.6.9",
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"vue3-video-play": "^1.3.2", "vue3-video-play": "^1.3.2",
"vuedraggable": "^4.1.0" "vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.6.1", "@rushstack/eslint-patch": "^1.7.2",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^20.10.6", "@types/node": "^20.11.19",
"@types/nprogress": "^0.2.3", "@types/nprogress": "^0.2.3",
"@vitejs/plugin-vue": "^5.0.2", "@vitejs/plugin-vue": "^5.0.4",
"@vitejs/plugin-vue-jsx": "^3.1.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/eslint-config-prettier": "^9.0.0", "@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^12.0.0", "@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.5.1", "@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.17",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-plugin-vue": "^9.19.2", "eslint-plugin-vue": "^9.21.1",
"execa": "^8.0.1", "execa": "^8.0.1",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"postcss": "^8.4.32", "postcss": "^8.4.35",
"prettier": "^3.1.1", "prettier": "^3.2.5",
"rollup-plugin-visualizer": "^5.12.0", "rollup-plugin-visualizer": "^5.12.0",
"sass": "^1.69.6", "sass": "^1.71.0",
"tailwindcss": "^3.4.0", "tailwindcss": "^3.4.1",
"typescript": "~5.3.3", "typescript": "~5.3.3",
"unplugin-auto-import": "^0.17.3", "unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0", "unplugin-vue-components": "^0.26.0",
"vite": "^4.5.0", "vite": "^5.1.3",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-style-import": "^2.0.0", "vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",

View File

@@ -1,5 +1,6 @@
import request from '@/utils/request' import request from '@/utils/request'
import queryString from 'query-string'
import { getToken } from '@/utils/auth'
// 管理员列表 // 管理员列表
export function adminLists(params: any) { export function adminLists(params: any) {
return request.get({ url: '/system/admin/list', params }) return request.get({ url: '/system/admin/list', params })
@@ -34,3 +35,10 @@ export function adminStatus(params: any) {
export function adminListByDeptId(params: any) { export function adminListByDeptId(params: any) {
return request.get({ url: '/system/admin/ListByDeptId', params }) return request.get({ url: '/system/admin/ListByDeptId', params })
} }
// 导出
export function adminExportFile(params: any) {
// return request.get({ url: '/system/admin/ExportFile', params })
return (window.location.href =
`/api/admin/system/admin/ExportFile?token=${getToken()}&` + queryString.stringify(params))
}

View File

@@ -8,37 +8,49 @@
start-placeholder="开始时间" start-placeholder="开始时间"
end-placeholder="结束时间" end-placeholder="结束时间"
clearable clearable
@change="changeDate"
></el-date-picker> ></el-date-picker>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { withDefaults, computed } from 'vue'
/* Props S */ /* Props S */
const props = withDefaults( const props = defineProps({
defineProps<{ startTime: {
startTime?: string type: String,
endTime?: string default: ''
}>(),
{
startTime: '',
endTime: ''
}
)
const emit = defineEmits(['update:startTime', 'update:endTime'])
const content = computed<any>({
get: () => {
return [props.startTime, props.endTime]
}, },
set: (value: Event | any) => { endTime: {
if (value === null) { type: String,
emit('update:startTime', '') default: ''
emit('update:endTime', '')
} else {
emit('update:startTime', value[0])
emit('update:endTime', value[1])
}
} }
}) })
const emit = defineEmits(['update:startTime', 'update:endTime'])
const content = ref<[string, string]>([props.startTime, props.endTime])
function changeDate(value: any) {
console.log('change', value)
if (value === null) {
emit('update:startTime', '')
emit('update:endTime', '')
} else {
emit('update:startTime', value[0])
emit('update:endTime', value[1])
}
}
// const content = computed<any>({
// get: () => {
// return [props.startTime, props.endTime]
// },
// set: (value: Event | any) => {
// console.log('change', value)
// if (value === null) {
// emit('update:startTime', '')
// emit('update:endTime', '')
// } else {
// emit('update:startTime', value[0])
// emit('update:endTime', value[1])
// }
// }
// })
</script> </script>

View File

@@ -2,6 +2,7 @@
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
append-to-body append-to-body
:mask="false"
:show-close="false" :show-close="false"
:fullscreen="true" :fullscreen="true"
:close-on-click-modal="false" :close-on-click-modal="false"
@@ -216,6 +217,9 @@ export default {
} }
</script> </script>
<style> <style>
.flow-config-dialog {
padding: 0;
}
.flow-config-dialog .el-dialog__header { .flow-config-dialog .el-dialog__header {
font-size: var(--el-font-size-large); font-size: var(--el-font-size-large);
padding: 0; padding: 0;

View File

@@ -2,11 +2,13 @@ import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import install from './install' import install from './install'
import './permission' import './permission'
import 'element-plus/dist/index.css'
import './styles/index.scss' import './styles/index.scss'
import 'virtual:svg-icons-register' import 'virtual:svg-icons-register'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import VForm3 from 'vform3-builds' //引入VForm3库 import VForm3 from 'vform3-builds' //引入VForm3库
const app = createApp(App) const app = createApp(App)

View File

@@ -23,7 +23,7 @@
<el-table-column label="通知类型" prop="type" min-width="160" /> <el-table-column label="通知类型" prop="type" min-width="160" />
<el-table-column label="短信通知" min-width="80"> <el-table-column label="短信通知" min-width="80">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.smsStatus == 1">开启</el-tag> <el-tag type="primary" v-if="row.smsStatus == 1">开启</el-tag>
<el-tag type="danger" v-else>关闭</el-tag> <el-tag type="danger" v-else>关闭</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -5,7 +5,7 @@
<el-table-column label="短信渠道" prop="name" min-width="120" /> <el-table-column label="短信渠道" prop="name" min-width="120" />
<el-table-column label="状态" min-width="120"> <el-table-column label="状态" min-width="120">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.status == 1">开启</el-tag> <el-tag type="primary" v-if="row.status == 1">开启</el-tag>
<el-tag type="danger" v-else>关闭</el-tag> <el-tag type="danger" v-else>关闭</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -76,7 +76,7 @@
<el-table-column label="颜色" prop="color" min-width="120" /> <el-table-column label="颜色" prop="color" min-width="120" />
<el-table-column label="状态"> <el-table-column label="状态">
<template v-slot="{ row }"> <template v-slot="{ row }">
<el-tag v-if="row.status == 1">正常</el-tag> <el-tag v-if="row.status == 1" type="primary">正常</el-tag>
<el-tag v-else type="danger">停用</el-tag> <el-tag v-else type="danger">停用</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -68,7 +68,7 @@
<el-table-column label="字典类型" prop="dictType" min-width="120" /> <el-table-column label="字典类型" prop="dictType" min-width="120" />
<el-table-column label="状态"> <el-table-column label="状态">
<template v-slot="{ row }"> <template v-slot="{ row }">
<el-tag v-if="row.dictStatus == 1">正常</el-tag> <el-tag v-if="row.dictStatus == 1" type="primary">正常</el-tag>
<el-tag v-else type="danger">停用</el-tag> <el-tag v-else type="danger">停用</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -52,7 +52,7 @@
<el-table-column label="部门状态" prop="isStop" min-width="100"> <el-table-column label="部门状态" prop="isStop" min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag class="ml-2" :type="row.isStop ? 'danger' : ''"> <el-tag class="ml-2" :type="row.isStop ? 'danger' : 'primary'">
{{ row.isStop ? '停用' : '正常' }} {{ row.isStop ? '停用' : '正常' }}
</el-tag> </el-tag>
</template> </template>

View File

@@ -53,7 +53,7 @@
<el-table-column label="添加时间" prop="createTime" min-width="180" /> <el-table-column label="添加时间" prop="createTime" min-width="180" />
<el-table-column label="岗位状态" prop="isStop" min-width="100"> <el-table-column label="岗位状态" prop="isStop" min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag class="ml-2" :type="row.isStop ? 'danger' : ''"> <el-tag class="ml-2" :type="row.isStop ? 'danger' : 'primary'">
{{ row.isStop ? '停用' : '正常' }} {{ row.isStop ? '停用' : '正常' }}
</el-tag> </el-tag>
</template> </template>

View File

@@ -3,23 +3,13 @@
<el-card class="!border-none" shadow="never"> <el-card class="!border-none" shadow="never">
<el-form class="mb-[-16px]" :model="formData" inline> <el-form class="mb-[-16px]" :model="formData" inline>
<el-form-item label="管理员账号"> <el-form-item label="管理员账号">
<el-input <el-input v-model="formData.username" clearable @keyup.enter="resetPage" />
v-model="formData.username"
class="w-[280px]"
clearable
@keyup.enter="resetPage"
/>
</el-form-item> </el-form-item>
<el-form-item label="管理员名称"> <el-form-item label="管理员名称">
<el-input <el-input v-model="formData.nickname" clearable @keyup.enter="resetPage" />
v-model="formData.nickname"
class="w-[280px]"
clearable
@keyup.enter="resetPage"
/>
</el-form-item> </el-form-item>
<el-form-item label="管理员角色"> <el-form-item label="管理员角色">
<el-select class="w-[280px]" v-model="formData.role"> <el-select v-model="formData.role">
<el-option label="全部" value="" /> <el-option label="全部" value="" />
<el-option <el-option
v-for="(item, index) in optionsData.role" v-for="(item, index) in optionsData.role"
@@ -42,6 +32,13 @@
</template> </template>
新增 新增
</el-button> </el-button>
<el-button type="primary" @click="exportFile">
<template #icon>
<icon name="el-icon-Download" />
</template>
导出
</el-button>
<div class="mt-4"> <div class="mt-4">
<el-table :data="pager.lists" size="large"> <el-table :data="pager.lists" size="large">
<el-table-column label="ID" prop="id" min-width="60" /> <el-table-column label="ID" prop="id" min-width="60" />
@@ -101,7 +98,7 @@
</template> </template>
<script lang="ts" setup name="admin"> <script lang="ts" setup name="admin">
import { adminLists, adminDelete, adminStatus } from '@/api/perms/admin' import { adminLists, adminDelete, adminStatus, adminExportFile } from '@/api/perms/admin'
import { roleAll } from '@/api/perms/role' import { roleAll } from '@/api/perms/role'
import { useDictOptions } from '@/hooks/useDictOptions' import { useDictOptions } from '@/hooks/useDictOptions'
import { usePaging } from '@/hooks/usePaging' import { usePaging } from '@/hooks/usePaging'
@@ -135,7 +132,10 @@ const handleAdd = async () => {
await nextTick() await nextTick()
editRef.value?.open('add') editRef.value?.open('add')
} }
const exportFile = async () => {
await feedback.confirm('确定要导出?')
await adminExportFile(formData)
}
const handleEdit = async (data: any) => { const handleEdit = async (data: any) => {
showEdit.value = true showEdit.value = true
await nextTick() await nextTick()

View File

@@ -52,7 +52,7 @@
</el-table-column> </el-table-column>
<el-table-column label="状态" prop="isDisable" min-width="100"> <el-table-column label="状态" prop="isDisable" min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.isDisable == 0">正常</el-tag> <el-tag v-if="row.isDisable == 0" type="primary">正常</el-tag>
<el-tag v-else type="danger">停用</el-tag> <el-tag v-else type="danger">停用</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -14,7 +14,7 @@
<el-table-column label="储存位置" prop="describe" min-width="160" /> <el-table-column label="储存位置" prop="describe" min-width="160" />
<el-table-column label="状态" min-width="80"> <el-table-column label="状态" min-width="80">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.status == 1">开启</el-tag> <el-tag v-if="row.status == 1" type="primary">开启</el-tag>
<el-tag type="danger" v-else>关闭</el-tag> <el-tag type="danger" v-else>关闭</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -1,128 +1,118 @@
<!-- 系统日志 --> <!-- 系统日志 -->
<template> <template>
<div class="journal"> <div class="journal">
<el-card class="!border-none" shadow="never"> {{ formData }}
<el-form class="ls-form" :model="formData" inline> <el-card class="!border-none" shadow="never">
<el-form-item label="管理员"> <el-form class="ls-form" :model="formData" inline>
<el-input <el-form-item label="管理员" class="w-[360px]">
class="w-[280px]" <el-input
placeholder="请输入" placeholder="请输入"
v-model="formData.username" v-model="formData.username"
clearable clearable
@keyup.enter="resetPage" @keyup.enter="resetPage"
/> />
</el-form-item> </el-form-item>
<el-form-item label="访问方式"> <el-form-item label="访问方式" class="w-[360px]">
<el-select <el-select v-model="formData.type" placeholder="请选择">
class="w-[280px]" <el-option
v-model="formData.type" v-for="(item, index) in visitType"
placeholder="请选择" :key="index"
> :label="item.label"
<el-option :value="item.value"
v-for="(item, index) in visitType" />
:key="index" </el-select>
:label="item.label" </el-form-item>
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="来源IP"> <el-form-item label="来源IP" class="w-[360px]">
<el-input <el-input
class="w-[280px]" placeholder="请输入"
placeholder="请输入" v-model="formData.ip"
v-model="formData.ip" clearable
clearable @keyup.enter="resetPage"
@keyup.enter="resetPage" />
/> </el-form-item>
</el-form-item>
<el-form-item label="访问时间"> <el-form-item label="访问时间" class="w-[360px]">
<daterange-picker <daterange-picker
v-model:startTime="formData.startTime" v-model:startTime="formData.startTime"
v-model:endTime="formData.endTime" v-model:endTime="formData.endTime"
/> />
</el-form-item> </el-form-item>
<el-form-item label="访问链接"> <el-form-item label="访问链接" class="w-[360px]">
<el-input <el-input
class="w-[280px]" placeholder="请输入"
placeholder="请输入" v-model="formData.url"
v-model="formData.url" clearable
clearable @keyup.enter="resetPage"
@keyup.enter="resetPage" />
/> </el-form-item>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button> <el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button> <el-button @click="resetParams">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card class="!border-none mt-4" shadow="never" v-loading="pager.loading"> <el-card class="!border-none mt-4" shadow="never" v-loading="pager.loading">
<div> <div>
<el-table :data="pager.lists" size="large"> <el-table :data="pager.lists" size="large">
<el-table-column label="记录ID" prop="id" /> <el-table-column label="记录ID" prop="id" />
<el-table-column label="操作" prop="title" min-width="120" /> <el-table-column label="操作" prop="title" min-width="120" />
<el-table-column label="管理员" prop="username" min-width="120" /> <el-table-column label="管理员" prop="username" min-width="120" />
<el-table-column label="访问链接" prop="url" min-width="160" /> <el-table-column label="访问链接" prop="url" min-width="160" />
<el-table-column label="访问方式" prop="type" min-width="100" /> <el-table-column label="访问方式" prop="type" min-width="100" />
<el-table-column label="来源IP" prop="ip" min-width="160" /> <el-table-column label="来源IP" prop="ip" min-width="160" />
<el-table-column label="错误信息" prop="error" min-width="160" /> <el-table-column label="错误信息" prop="error" min-width="160" />
<el-table-column <el-table-column label="执行耗时(毫秒)" prop="taskTime" min-width="100" />
label="执行耗时(毫秒)" <el-table-column label="日志时间" prop="createTime" min-width="180" />
prop="taskTime" </el-table>
min-width="100" </div>
/> <div class="flex mt-4 justify-end">
<el-table-column label="日志时间" prop="createTime" min-width="180" /> <pagination v-model="pager" @change="getLists" />
</el-table> </div>
</div> </el-card>
<div class="flex mt-4 justify-end"> </div>
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
</div>
</template> </template>
<script setup lang="ts" name="journal"> <script setup lang="ts" name="journal">
import { systemLogLists } from "@/api/setting/system"; import { systemLogLists } from '@/api/setting/system'
import { usePaging } from "@/hooks/usePaging"; import { usePaging } from '@/hooks/usePaging'
// 查询表单 // 查询表单
const formData = ref({ const formData = ref({
username: "", username: '',
url: "", url: '',
ip: "", ip: '',
type: "", type: '',
startTime: "", startTime: '',
endTime: "", endTime: ''
}); })
// 访问方式 // 访问方式
const visitType = ref<Array<any>>([ const visitType = ref<Array<any>>([
{ {
label: "全部", label: '全部',
value: "", value: ''
}, },
{ {
label: "get", label: 'get',
value: "GET", value: 'GET'
}, },
{ {
label: "post", label: 'post',
value: "POST", value: 'POST'
}, }
]); ])
const { pager, getLists, resetParams, resetPage } = usePaging({ const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: systemLogLists, fetchFun: systemLogLists,
params: formData.value, params: formData.value
}); })
getLists(); getLists()
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@@ -7,14 +7,17 @@
"auto-imports.d.ts", "auto-imports.d.ts",
"typings/**/*.d.ts" "typings/**/*.d.ts"
], ],
"exclude": ["dist"],
"compilerOptions": { "compilerOptions": {
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"allowJs": true, "allowJs": true,
"outDir": "./dist",
"isolatedModules": true, "isolatedModules": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} },
"types": ["element-plus/global"]
} }
} }

View File

@@ -41,8 +41,8 @@ export default ({ mode }) => {
} }
}), }),
Components({ Components({
directoryAsNamespace: true directoryAsNamespace: true,
// resolvers: [ElementPlusResolver()] resolvers: [ElementPlusResolver()]
}), }),
// createStyleImportPlugin({ // createStyleImportPlugin({
// resolves: [ElementPlusResolve()] // resolves: [ElementPlusResolve()]

View File

@@ -5,6 +5,7 @@ import (
"x_admin/config" "x_admin/config"
"x_admin/core/request" "x_admin/core/request"
"x_admin/core/response" "x_admin/core/response"
"x_admin/util/excel"
"x_admin/util" "x_admin/util"
@@ -44,6 +45,28 @@ func (ah AdminHandler) Self(c *gin.Context) {
response.CheckAndRespWithData(c, res, err) response.CheckAndRespWithData(c, res, err)
} }
func (ah AdminHandler) ExportFile(c *gin.Context) {
var listReq SystemAuthAdminListReq
if response.IsFailWithResp(c, util.VerifyUtil.VerifyQuery(c, &listReq)) {
return
}
res, err := Service.ExportFile(listReq)
if err != nil {
response.FailWithMsg(c, response.SystemError, "查询导出失败")
return
}
f, err := excel.NormalDynamicExport(res, "Sheet1", "用户信息", "", true, false, nil)
if err != nil {
response.FailWithMsg(c, response.SystemError, "导出失败")
return
}
excel.DownLoadExcel("用户信息", c.Writer, f)
// c.Header("Content-Type", "application/octet-stream")
// c.Header("Content-Disposition", "attachment; filename="+"用户信息.xlsx")
// c.Header("Content-Transfer-Encoding", "binary")
// f.Write(c.Writer)
}
// list 管理员列表 // list 管理员列表
func (ah AdminHandler) List(c *gin.Context) { func (ah AdminHandler) List(c *gin.Context) {
var page request.PageReq var page request.PageReq
@@ -114,12 +137,12 @@ func (ah AdminHandler) Disable(c *gin.Context) {
response.CheckAndResp(c, Service.Disable(c, disableReq.ID)) response.CheckAndResp(c, Service.Disable(c, disableReq.ID))
} }
// @Summary 获取部门的用户 // @Summary 获取部门的用户
// @Description 获取部门的用户 // @Description 获取部门的用户
// @Tags 管理员 // @Tags 管理员
// @Param deptId path int true "部门id" // @Param deptId path int true "部门id"
// @Success 200 {object} response.Response "{"code": 200, "data": []}" // @Success 200 {object} response.Response "{"code": 200, "data": []}"
// @Router /system/admin/ListByDeptId/{deptId} [get] // @Router /system/admin/ListByDeptId/{deptId} [get]
func (ah AdminHandler) ListByDeptId(c *gin.Context) { func (ah AdminHandler) ListByDeptId(c *gin.Context) {
deptIdStr, bool := c.GetQuery("deptId") deptIdStr, bool := c.GetQuery("deptId")
if bool == false { if bool == false {

View File

@@ -63,20 +63,20 @@ type SystemAuthAdminDisableReq struct {
//SystemAuthAdminResp 管理员返回信息 //SystemAuthAdminResp 管理员返回信息
type SystemAuthAdminResp struct { type SystemAuthAdminResp struct {
ID uint `json:"id" structs:"id"` // 主键 ID uint `json:"id" structs:"id"` // 主键
Username string `json:"username" structs:"username"` // 账号 Username string `json:"username" structs:"username" excel:"name:账号;"` // 账号
Nickname string `json:"nickname" structs:"nickname"` // 昵称 Nickname string `json:"nickname" structs:"nickname" excel:"name:昵称;"` // 昵称
Avatar string `json:"avatar" structs:"avatar"` // 头像 Avatar string `json:"avatar" structs:"avatar" excel:"name:头像;"` // 头像
Role string `json:"role" structs:"role"` // 角色 Role string `json:"role" structs:"role" excel:"name:角色;"` // 角色
DeptId uint `json:"deptId" structs:"deptId"` // 部门ID DeptId uint `json:"deptId" structs:"deptId" excel:"name:部门ID;"` // 部门ID
PostId uint `json:"postId" structs:"postId"` // 岗位ID PostId uint `json:"postId" structs:"postId" excel:"name:岗位ID;"` // 岗位ID
Dept string `json:"dept" structs:"dept"` // 部门 Dept string `json:"dept" structs:"dept" excel:"name:部门;"` // 部门
IsMultipoint uint8 `json:"isMultipoint" structs:"isMultipoint"` // 多端登录: [0=否, 1=是] IsMultipoint uint8 `json:"isMultipoint" structs:"isMultipoint" excel:"name:多端登录;"` // 多端登录: [0=否, 1=是]
IsDisable uint8 `json:"isDisable" structs:"isDisable"` // 是否禁用: [0=否, 1=是] IsDisable uint8 `json:"isDisable" structs:"isDisable" excel:"name:是否禁用;"` // 是否禁用: [0=否, 1=是]
LastLoginIp string `json:"lastLoginIp" structs:"lastLoginIp"` // 最后登录IP LastLoginIp string `json:"lastLoginIp" structs:"lastLoginIp" excel:"name:最后登录IP;"` // 最后登录IP
LastLoginTime core.TsTime `json:"lastLoginTime" structs:"lastLoginTime"` // 最后登录时间 LastLoginTime core.TsTime `json:"lastLoginTime" structs:"lastLoginTime" excel:"name:最后登录时间;"` // 最后登录时间
CreateTime core.TsTime `json:"createTime" structs:"createTime"` // 创建时间 CreateTime core.TsTime `json:"createTime" structs:"createTime" excel:"name:创建时间;"` // 创建时间
UpdateTime core.TsTime `json:"updateTime" structs:"updateTime"` // 更新时间 UpdateTime core.TsTime `json:"updateTime" structs:"updateTime" excel:"name:更新时间;"` // 更新时间
} }
//SystemAuthAdminSelfOneResp 当前管理员返回部分信息 //SystemAuthAdminSelfOneResp 当前管理员返回部分信息

View File

@@ -122,6 +122,39 @@ func (adminSrv systemAuthAdminService) ListByUserIdOrDeptIdPostId(userId, deptId
} }
return adminResp, nil return adminResp, nil
} }
func (adminSrv systemAuthAdminService) ExportFile(listReq SystemAuthAdminListReq) (res []SystemAuthAdminResp, e error) {
// 查询
adminTbName := core.DBTableName(&system_model.SystemAuthAdmin{})
roleTbName := core.DBTableName(&system_model.SystemAuthRole{})
deptTbName := core.DBTableName(&system_model.SystemAuthDept{})
adminModel := adminSrv.db.Table(adminTbName+" AS admin").Where("admin.is_delete = ?", 0).Joins(
fmt.Sprintf("LEFT JOIN %s ON admin.role = %s.id", roleTbName, roleTbName)).Joins(
fmt.Sprintf("LEFT JOIN %s ON admin.dept_id = %s.id", deptTbName, deptTbName)).Select(
fmt.Sprintf("admin.*, %s.name as dept, %s.name as role", deptTbName, roleTbName))
// 条件
if listReq.Username != "" {
adminModel = adminModel.Where("username like ?", "%"+listReq.Username+"%")
}
if listReq.Nickname != "" {
adminModel = adminModel.Where("nickname like ?", "%"+listReq.Nickname+"%")
}
if listReq.Role >= 0 {
adminModel = adminModel.Where("role = ?", listReq.Role)
}
// 数据
var adminResp []SystemAuthAdminResp
err := adminModel.Order("id desc, sort desc").Find(&adminResp).Error
if e = response.CheckErr(err, "List Find err"); e != nil {
return
}
for i := 0; i < len(adminResp); i++ {
adminResp[i].Avatar = util.UrlUtil.ToAbsoluteUrl(adminResp[i].Avatar)
if adminResp[i].ID == 1 {
adminResp[i].Role = "系统管理员"
}
}
return adminResp, nil
}
// List 管理员列表 // List 管理员列表
func (adminSrv systemAuthAdminService) List(page request.PageReq, listReq SystemAuthAdminListReq) (res response.PageResp, e error) { func (adminSrv systemAuthAdminService) List(page request.PageReq, listReq SystemAuthAdminListReq) (res response.PageResp, e error) {

View File

@@ -30,6 +30,8 @@ func AdminRoute(rg *gin.RouterGroup) {
rg.POST("/admin/del", middleware.RecordLog("管理员删除"), handle.Del) rg.POST("/admin/del", middleware.RecordLog("管理员删除"), handle.Del)
rg.POST("/admin/disable", middleware.RecordLog("管理员状态切换"), handle.Disable) rg.POST("/admin/disable", middleware.RecordLog("管理员状态切换"), handle.Disable)
rg.GET("/admin/ExportFile", middleware.RecordLog("管理员导出"), handle.ExportFile)
} }
func RoleRoute(rg *gin.RouterGroup) { func RoleRoute(rg *gin.RouterGroup) {
// db := core.GetDB() // db := core.GetDB()

View File

@@ -16,13 +16,25 @@ import (
func GetExcelColumnName(columnNumber int) string { func GetExcelColumnName(columnNumber int) string {
columnName := "" columnName := ""
for columnNumber > 0 { for columnNumber > 0 {
columnNumber-- remainder := (columnNumber - 1) % 26
columnName = fmt.Sprint('A'+columnNumber%26) + columnName columnName = string('A'+remainder) + columnName
columnNumber /= 26 columnNumber = (columnNumber - 1) / 26
} }
return columnName return columnName
} }
// NormalDynamicExport 导出excel
// ** 需要在传入的结构体中的字段加上tagexcelize:"title:列头名称;index:列下标(从0开始);"
// list 需要导出的对象数组、sheet sheet名称、title 标题、isGhbj 是否设置隔行背景色
func NormalDynamicExport(list interface{}, sheet, title, fields string, isGhbj, isIgnore bool, changeHead map[string]string) (file *excelize.File, err error) {
e := ExcelInit()
err = ExportExcel(sheet, title, fields, isGhbj, isIgnore, list, changeHead, e)
if err != nil {
return
}
return e.F, err
}
// ExportExcel excel导出 // ExportExcel excel导出
func ExportExcel(sheet, title, fields string, isGhbj, isIgnore bool, list interface{}, changeHead map[string]string, e *Excel) (err error) { func ExportExcel(sheet, title, fields string, isGhbj, isIgnore bool, list interface{}, changeHead map[string]string, e *Excel) (err error) {
index, _ := e.F.GetSheetIndex(sheet) index, _ := e.F.GetSheetIndex(sheet)
@@ -47,44 +59,6 @@ func ExportExcel(sheet, title, fields string, isGhbj, isIgnore bool, list interf
return return
} }
// ================================= 普通导出 =================================
// NormalDownLoad 导出excel并下载单个sheet
func NormalDownLoad(fileName, sheet, title string, isGhbj bool, list interface{}, res http.ResponseWriter) error {
f, err := NormalDynamicExport(list, sheet, title, "", isGhbj, false, nil)
if err != nil {
return err
}
DownLoadExcel(fileName, res, f)
return nil
}
// NormalDynamicDownLoad 动态导出excel并下载单个sheet
// isIgnore 是否忽略指定字段true 要忽略的字段 false 要导出的字段)
// fields 选择的字段多个字段用逗号隔开最后一个字段后面也要加逗号字段1,字段2,字段3,
// changeHead 要改变表头的字段,格式是{"字段1":"更改的表头1","字段2":"更改的表头2"}
func NormalDynamicDownLoad(fileName, sheet, title, fields string, isGhbj, isIgnore bool,
list interface{}, changeHead map[string]string, res http.ResponseWriter) error {
f, err := NormalDynamicExport(list, sheet, title, fields, isGhbj, isIgnore, changeHead)
if err != nil {
return err
}
DownLoadExcel(fileName, res, f)
return nil
}
// NormalDynamicExport 导出excel
// ** 需要在传入的结构体中的字段加上tagexcelize:"title:列头名称;index:列下标(从0开始);"
// list 需要导出的对象数组、sheet sheet名称、title 标题、isGhbj 是否设置隔行背景色
func NormalDynamicExport(list interface{}, sheet, title, fields string, isGhbj, isIgnore bool, changeHead map[string]string) (file *excelize.File, err error) {
e := ExcelInit()
err = ExportExcel(sheet, title, fields, isGhbj, isIgnore, list, changeHead, e)
if err != nil {
return
}
return e.F, err
}
// 构造表头endColName 最后一列的列名 dataRow 数据行开始的行号) // 构造表头endColName 最后一列的列名 dataRow 数据行开始的行号)
func normalBuildTitle(e *Excel, sheet, title, fields string, isIgnore bool, changeHead map[string]string, dataValue reflect.Value) (endColName string, dataRow int, err error) { func normalBuildTitle(e *Excel, sheet, title, fields string, isIgnore bool, changeHead map[string]string, dataValue reflect.Value) (endColName string, dataRow int, err error) {
dataType := dataValue.Type().Elem() // 获取导入目标对象的类型信息 dataType := dataValue.Type().Elem() // 获取导入目标对象的类型信息

View File

@@ -66,3 +66,11 @@ func TestImports(t *testing.T) {
fmt.Println(t) fmt.Println(t)
} }
} }
func TestGetExcelColumnName(t *testing.T) {
for i := 0; i < 100; i++ {
var col = GetExcelColumnName(i)
fmt.Println("col:", col)
}
}

Binary file not shown.