This commit is contained in:
Double-_-Z 2025-07-07 09:52:27 +08:00
parent 3dc1faf896
commit cd31ed4420
4 changed files with 1208 additions and 124 deletions

View File

@ -404,6 +404,21 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
icon: 'iconfont icon-shuju', icon: 'iconfont icon-shuju',
}, },
}, },
{
path: '/statistics',
name: 'statistics',
component: () => import('/@/views/statistics/index.vue'),
meta: {
title: 'message.router.statistics',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'user'],
icon: 'iconfont icon-ico_shuju',
},
},
{ {
path: '/video', path: '/video',
name: 'video', name: 'video',

View File

@ -15,12 +15,12 @@
</el-icon> </el-icon>
重置 重置
</el-button> </el-button>
<el-button @click="pushMessages" size="default" type="primary" class="ml10" :disabled="btnDisabled"> <!-- <el-button @click="pushMessages" size="default" type="primary" class="ml10" :disabled="btnDisabled">
<el-icon> <el-icon>
<ele-FolderAdd /> <ele-FolderAdd />
</el-icon> </el-icon>
消息推送 消息推送
</el-button> </el-button> -->
</div> </div>
<el-table <el-table
:data="state.tableData.data" :data="state.tableData.data"
@ -28,17 +28,19 @@
style="width: 100%" style="width: 100%"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
> >
<el-table-column type="selection" :selectable="selectable" width="100" /> <!-- <el-table-column type="selection" :selectable="selectable" width="100" /> -->
<el-table-column prop="username" label="账户" show-overflow-tooltipalign="center"></el-table-column> <el-table-column prop="realName" label="姓名" show-overflow-tooltip align="center"></el-table-column>
<el-table-column prop="nickName" label="昵称" show-overflow-tooltip align="center"></el-table-column> <el-table-column prop="gender" label="性别" show-overflow-tooltip align="center"></el-table-column>
<el-table-column prop="phone" label="手机号" show-overflow-tooltip align="center"></el-table-column> <el-table-column prop="username" label="手机号" show-overflow-tooltipalign="center"></el-table-column>
<el-table-column prop="mail" label="邮箱" show-overflow-tooltip align="center"></el-table-column> <!-- <el-table-column prop="phone" label="手机号" show-overflow-tooltip align="center"></el-table-column> -->
<el-table-column prop="registerTime" label="注册时间" :formatter="dateFormatter" show-overflow-tooltip align="center"></el-table-column> <el-table-column prop="usertypeName" label="用户类型" show-overflow-tooltipalign="center"></el-table-column>
<el-table-column prop="registerTime" label="创建时间" :formatter="dateFormatter" show-overflow-tooltip align="center"></el-table-column>
<el-table-column prop="gender" label="用户状态" show-overflow-tooltip align="center"></el-table-column>
<!-- <el-table-column prop="state" label="状态" show-overflow-tooltip width="255px" align="center"></el-table-column> --> <!-- <el-table-column prop="state" label="状态" show-overflow-tooltip width="255px" align="center"></el-table-column> -->
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template #default="scope"> <template #default="scope">
<el-button size="small" text type="primary" :disabled="scope.row.enable?true:false" @click="scope.row.enable=!scope.row.enable">启用</el-button> <el-button size="small" text type="primary" :disabled="scope.row.enable?true:false" @click="handleEnable(scope)">启用</el-button>
<el-button size="small" text type="primary" :disabled="scope.row.enable?false:true" @click="scope.row.enable=!scope.row.enable"></el-button> <el-button size="small" text type="primary" :disabled="scope.row.enable?false:true" @click="handleEnable(scope)"></el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -191,9 +193,9 @@ const getTableData = async() => {
state.tableData.data = res.data.records.map((item:any) => { state.tableData.data = res.data.records.map((item:any) => {
return { return {
...item, ...item,
nickName:item.nickName || '暂无', realName:item.realName || '暂无',
phone: item.phone || '暂无', gender:item.gender || '未知',
mail: item.mail || '暂无', usertypeName:item.usertypeName || '暂无',
} }
}); });
state.tableData.total = res.data.total; state.tableData.total = res.data.total;
@ -246,6 +248,11 @@ const dateFormatter = (row: any, column: TableColumnCtx<String>) => {
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`; return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
} }
// /
const handleEnable = (scope: any) => {
scope.row.enable=!scope.row.enable;
}
// //
const onHandleSizeChange = (val: number) => { const onHandleSizeChange = (val: number) => {
state.tableData.param.size = val; state.tableData.param.size = val;

File diff suppressed because one or more lines are too long

View File

@ -1,82 +1,95 @@
<template> <template>
<div class="system-user-dialog-container"> <div class="system-user-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px"> <el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" width="769px">
<el-form ref="userDialogFormRef" :model="state.ruleForm" :rules="state.rules" size="default" label-width="90px"> <el-form ref="userDialogFormRef" :model="state.ruleForm" :rules="state.rules" size="default"
label-width="90px" v-loading="state.ruleForm.loading">
<el-row :gutter="35"> <el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户名称" prop="username"> <el-form-item label="姓名" prop="userNickname">
<el-input v-model="state.ruleForm.username" placeholder="请输入账户名称" clearable></el-input> <el-input v-model="state.ruleForm.userNickname" placeholder="请输入姓名" clearable></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="用户昵称">
<el-input v-model="state.ruleForm.userNickname" placeholder="请输入用户昵称" clearable></el-input>
</el-form-item>
</el-col> -->
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="关联角色" prop="acgroup"> <el-form-item label="账户" prop="username">
<el-select v-model="state.ruleForm.acgroup" placeholder="请选择" clearable class="w100"> <el-input v-model="state.ruleForm.username" placeholder="请输入账户" clearable></el-input>
<!-- <el-option label="管理员" value="admin"></el-option>
<el-option label="普通用户" value="common"></el-option> -->
<el-option :data-op="item.id" v-for="(item,index) in roleList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="部门">
<el-cascader
:options="state.deptData"
:props="{ checkStrictly: true, value: 'deptName', label: 'deptName' }"
placeholder="请选择部门"
clearable
class="w100"
v-model="state.ruleForm.department"
>
<template #default="{ node, data }">
<span>{{ data.deptName }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col> -->
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="手机号" > <el-form-item label="密码" prop="password">
<el-input v-model="state.ruleForm.password" placeholder="请输入密码" type="password"
clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="手机号" prop="phone">
<el-input v-model="state.ruleForm.phone" placeholder="请输入手机号" clearable></el-input> <el-input v-model="state.ruleForm.phone" placeholder="请输入手机号" clearable></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="邮箱" > <el-form-item label="角色" prop="acgroup">
<el-input v-model="state.ruleForm.mail" placeholder="请输入" clearable></el-input> <el-select v-model="state.ruleForm.acgroup" placeholder="请选择角色" clearable class="w100">
</el-form-item> <el-option :data-op="item.id" v-for="(item, index) in roleList" :key="index"
</el-col> :label="item.name" :value="item.id"></el-option>
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> -->
<!-- <el-form-item label="性别">
<el-select v-model="state.ruleForm.gender" placeholder="请选择" clearable class="w100">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select> </el-select>
</el-form-item> --> </el-form-item>
<!-- </el-col> --> </el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户密码" prop="password"> <el-form-item label="区域" prop="area">
<el-input v-model="state.ruleForm.password" placeholder="请输入" type="password" clearable></el-input> <el-select v-model="state.ruleForm.area" placeholder="请选择区域" clearable class="w100">
<el-option :data-op="item.id" v-for="(item, index) in roleList" :key="index"
:label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="账户过期"> <el-form-item label="景区" prop="spot">
<el-date-picker v-model="state.ruleForm.overdueTime" type="date" placeholder="请选择" class="w100"> </el-date-picker> <el-select v-model="state.ruleForm.spot" placeholder="请选择景区" clearable class="w100">
</el-form-item> <el-option :data-op="item.id" v-for="(item, index) in roleList" :key="index"
</el-col> --> :label="item.name" :value="item.id"></el-option>
<!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> </el-select>
<el-form-item label="用户状态">
<el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="用户描述"> <el-form-item label="飞行资质" prop="intelligence">
<el-input v-model="state.ruleForm.describe" type="textarea" placeholder="请输入用户描述" maxlength="150"></el-input> <el-select v-model="state.ruleForm.intelligence" placeholder="请选择飞行资质" clearable
class="w100">
<el-option :data-op="item.id" v-for="(item, index) in roleList" :key="index"
:label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> --> </el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="飞行资质附件" prop="intelligenceFile" label-width="100px">
<el-upload ref="uploadRef" action="#" list-type="picture-card"
:class="{ disabled: uploadDisabled }" :limit="1" :file-list="state.ruleForm.fileList"
:on-change="handleChange" :auto-upload="false">
<div style="display: flex;flex-direction: column;align-items: center;">
<el-icon style="font-size: 30px;"><Plus /></el-icon>
<div style="margin: 5px 0 -20px;">上传</div>
</div>
<template #file="{ file }">
<div>
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)">
<el-icon><zoom-in /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete"
@click="handleRemove(file)">
<el-icon>
<Delete />
</el-icon>
</span>
</span>
</div>
</template>
</el-upload>
<el-dialog v-model="dialogVisible">
<img :src="dialogImageUrl" style="width: 100%" alt="Preview Image" />
</el-dialog>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
<template #footer> <template #footer>
@ -92,9 +105,11 @@
<script setup lang="ts" name="systemUserDialog"> <script setup lang="ts" name="systemUserDialog">
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { roleApi } from '/@/api/role'; import { roleApi } from '/@/api/role';
import { ElMessage } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { userApi } from '/@/api/user'; import { userApi } from '/@/api/user';
import { photosApi } from '/@/api/photos';
import { Delete, Plus, ZoomIn } from '@element-plus/icons-vue'
import type { UploadFile, UploadProps } from 'element-plus'
// / // /
const emit = defineEmits(['reset']); const emit = defineEmits(['reset']);
@ -104,28 +119,31 @@ const userapi = userApi()
// //
const userDialogFormRef = ref(); const userDialogFormRef = ref();
const uploadDisabled = ref(false);
const state = reactive({ const state = reactive({
ruleForm: { ruleForm: {
loading: false,//
username: '', // username: '', //
// userNickname: '', // userNickname: '', //
acgroupName: '', // acgroupName: '', //
// department: [] as string[], //
phone: '', // phone: '', //
mail: '', //
acgroup: 0, acgroup: 0,
// gender: '', //
password: '', // password: '', //
usertype:1 usertype: 1,
// overdueTime: '', // area: '', //
// status: true, // spot: '', //
// describe: '', // intelligence: '', //
intelligenceFile: '',
fileList: [], //
}, },
rules: { rules: {
username:{ required: true, message: '请输入账户名称', trigger:'blur'}, userNickname: { required: true, message: '请输入姓名', trigger: 'blur' },
acgroup:{ required: true, message: '请选择关联角色', trigger:'change'}, username: { required: true, message: '请输入账户', trigger: 'blur' },
// phone:{ required: true, message: '', trigger:'blur'}, acgroup: { required: true, message: '请选择角色', trigger: 'change' },
// mail:{ required: true, message: '', trigger:'blur'}, phone: { required: true, message: '请输入手机号', trigger: 'blur' },
password:{ required: true, message: '请输入账户密码', trigger:'blur'}, password: { required: true, message: '请输入密码', trigger: 'blur' },
area: { required: true, message: '请选择区域', trigger: 'change' },
intelligence: { required: true, message: '请选择飞行资质', trigger: 'change' }
}, },
// deptData: [] as DeptTreeType[], // // deptData: [] as DeptTreeType[], //
dialog: { dialog: {
@ -136,6 +154,64 @@ const state = reactive({
}, },
}); });
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
// api
const photoApi = photosApi();
const handleChange: UploadProps['onChange'] = async (file: uploadFile, uploadFiles) => {
state.ruleForm.loading = true;
if (file.raw.type === 'image/png' || file.raw.type === 'image/jpeg' || file.raw.type === 'image/jpg' || file.raw.type === 'image/gif') {
state.ruleForm.fileList = uploadFiles;
uploadDisabled.value = true;
try {
const formdata = new FormData();
formdata.append('file', file.raw);
let res = await photoApi.uploadFile(formdata);
if(res?.success){
state.ruleForm.intelligenceFile = res.data.path;
ElMessage({
message: '图片上传成功!',
type: 'success',
})
state.ruleForm.loading = false;
}else{
ElMessage.error('图片上传失败!');
}
} catch (error) {
state.ruleForm.loading = false;
console.log(error);
ElMessage.error('图片上传失败!');
}
} else {
ElMessageBox.alert('图片的格式不正确,请重新选择!', '提示', {
confirmButtonText: '确定',
})
console.log("handleChange3",uploadFiles);
uploadFiles.pop()
console.log("handleChange4",uploadFiles);
uploadDisabled.value = false;
}
}
//
const disabled = ref(false);
const handlePictureCardPreview = (file: UploadFile,uploadFiles) => {
dialogImageUrl.value = file.url!
dialogVisible.value = true
}
const uploadRef = ref();
const handleRemove = (file: UploadFile, uploadFiles) => {
uploadRef.value.clearFiles();
state.ruleForm.intelligenceFile = "";
uploadDisabled.value = false;
};
// //
const openDialog = (type: string, row: any) => { const openDialog = (type: string, row: any) => {
if (type === 'edit') { if (type === 'edit') {
@ -185,13 +261,19 @@ const getroleList = async() => {
// //
const resetForm = () => { const resetForm = () => {
state.ruleForm = { state.ruleForm = {
username:'', loading: false,//
username: '', //
userNickname: '', //
acgroupName: '', //
phone: '', //
acgroup: 0,
password: '', //
usertype: 1, usertype: 1,
acgroupName:'', area: '', //
// acgroup:, spot: '', //
phone:'', intelligence: '', //
mail:'', intelligenceFile: '',
password:'' fileList: [], //
} }
}; };
@ -222,12 +304,19 @@ const onSubmit = () => {
ElMessage.success('用户创建成功!'); ElMessage.success('用户创建成功!');
Object.assign(state.ruleForm,{ Object.assign(state.ruleForm,{
username:'', loading: false,//
username: '', //
userNickname: '', //
acgroupName: '', //
phone: '', //
acgroup: 0,
password: '', //
usertype: 1, usertype: 1,
usertypeName:'', area: '', //
phone:'', spot: '', //
mail:'', intelligence: '', //
password:'' intelligenceFile: '',
fileList: [], //
}) })
} }
} catch (error) { } catch (error) {
@ -289,3 +378,10 @@ onMounted(async() =>{
await getroleList() await getroleList()
}) })
</script> </script>
<style lang="scss" scoped>
::v-deep .disabled{
.el-upload--picture-card{
display: none;
}
}
</style>