Browse Source

设备管理

master
hx 2 weeks ago
parent
commit
a060f46e92
  1. 2
      .env.development
  2. 2
      .env.production
  3. 2
      .env.staging
  4. 53
      src/api/business/businessApiConfig.js
  5. 53
      src/api/business/businessLogininfor.js
  6. 45
      src/api/device/device.js
  7. 26
      src/api/system/role.js
  8. 30
      src/api/system/user.js
  9. 2
      src/utils/auth.js
  10. 431
      src/views/business/businessApiConfig/index.vue
  11. 369
      src/views/business/businessLogininfor/index.vue
  12. 209
      src/views/device/device/index.vue
  13. 138
      src/views/system/menu/index.vue
  14. 1046
      src/views/system/role/index.vue
  15. 226
      src/views/system/user/index.vue
  16. 4
      vue.config.js

2
.env.development

@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = GEO TAG管理系统
VUE_APP_TITLE = 客户 GEO TAG管理系统
# 开发环境配置
ENV = 'development'

2
.env.production

@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = GEO TAG管理系统
VUE_APP_TITLE = 客户GEO TAG管理系统
# 生产环境配置
ENV = 'production'

2
.env.staging

@ -1,5 +1,5 @@
NODE_ENV = production
VUE_APP_TITLE = GEO TAG管理系统
VUE_APP_TITLE =客户 GEO TAG管理系统
# 测试环境配置
ENV = 'staging'

53
src/api/business/businessApiConfig.js

@ -1,53 +0,0 @@
import request from '@/utils/request'
// 查询企业api配置表列表
export function listBusinessApiConfig(query) {
return request({
url: '/business/businessApiConfig/list',
method: 'get',
params: query
})
}
// 查询企业api配置表详细
export function getBusinessApiConfig(id) {
return request({
url: '/business/businessApiConfig/' + id,
method: 'get'
})
}
// 新增企业api配置表
export function addBusinessApiConfig(data) {
return request({
url: '/business/businessApiConfig',
method: 'post',
data: data
})
}
// 修改企业api配置表
export function updateBusinessApiConfig(data) {
return request({
url: '/business/businessApiConfig',
method: 'put',
data: data
})
}
// 删除企业api配置表
export function delBusinessApiConfig(id) {
return request({
url: '/business/businessApiConfig/' + id,
method: 'delete'
})
}
// 导出企业api配置表
export function exportBusinessApiConfig(query) {
return request({
url: '/business/businessApiConfig/export',
method: 'get',
params: query
})
}

53
src/api/business/businessLogininfor.js

@ -1,53 +0,0 @@
import request from '@/utils/request'
// 查询企业登录日志列表
export function listBusinessLogininfor(query) {
return request({
url: '/business/businessLogininfor/list',
method: 'get',
params: query
})
}
// 查询企业登录日志详细
export function getBusinessLogininfor(id) {
return request({
url: '/business/businessLogininfor/' + id,
method: 'get'
})
}
// 新增企业登录日志
export function addBusinessLogininfor(data) {
return request({
url: '/business/businessLogininfor',
method: 'post',
data: data
})
}
// 修改企业登录日志
export function updateBusinessLogininfor(data) {
return request({
url: '/business/businessLogininfor',
method: 'put',
data: data
})
}
// 删除企业登录日志
export function delBusinessLogininfor(id) {
return request({
url: '/business/businessLogininfor/' + id,
method: 'delete'
})
}
// 导出企业登录日志
export function exportBusinessLogininfor(query) {
return request({
url: '/business/businessLogininfor/export',
method: 'get',
params: query
})
}

45
src/api/device/device.js

@ -1,6 +1,5 @@
import request from '@/utils/request'
// 查询系统设备主列表
export function listDevice(query) {
return request({
url: '/device/device/list',
@ -9,7 +8,6 @@ export function listDevice(query) {
})
}
// 查询系统设备主详细
export function getDevice(id) {
return request({
url: '/device/device/' + id,
@ -17,7 +15,6 @@ export function getDevice(id) {
})
}
// 新增系统设备主
export function addDevice(data) {
return request({
url: '/device/device',
@ -26,7 +23,6 @@ export function addDevice(data) {
})
}
// 修改系统设备主
export function updateDevice(data) {
return request({
url: '/device/device',
@ -35,7 +31,6 @@ export function updateDevice(data) {
})
}
// 删除系统设备主
export function delDevice(id) {
return request({
url: '/device/device/' + id,
@ -43,7 +38,6 @@ export function delDevice(id) {
})
}
// 导出系统设备主
export function exportDevice(query) {
return request({
url: '/device/device/export',
@ -53,13 +47,35 @@ export function exportDevice(query) {
}
export function importDevice(data) {
return importDeviceSync(data)
}
export function importDeviceSync(data) {
return request({
url: '/device/device/import', // 替换为你后端实际的导入接口地址
url: '/device/device/import/sync',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data' // 文件上传必须的请求头
'Content-Type': 'multipart/form-data'
},
data: data // 接收FormData参数
data: data
})
}
export function importDeviceAsync(data) {
return request({
url: '/device/device/import/async',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
})
}
export function getDeviceImportTask(taskId) {
return request({
url: '/device/device/import/task/' + taskId,
method: 'get'
})
}
@ -69,3 +85,14 @@ export function getBatchNo() {
method: 'get'
})
}
// 批量激活设备(将选中设备标记为激活:1)
export function batchActivateDevice(ids) {
return request({
url: '/device/device/activate/batch',
method: 'put',
data: {
ids: ids
}
})
}

26
src/api/system/role.js

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 查询角色列表
export function listRole(query) {
return request({
url: '/system/role/list',
url: '/business/businessRole/list',
method: 'get',
params: query
})
@ -12,7 +12,7 @@ export function listRole(query) {
// 查询角色详细
export function getRole(roleId) {
return request({
url: '/system/role/' + roleId,
url: '/business/businessRole/' + roleId,
method: 'get'
})
}
@ -20,7 +20,7 @@ export function getRole(roleId) {
// 新增角色
export function addRole(data) {
return request({
url: '/system/role',
url: '/business/businessRole',
method: 'post',
data: data
})
@ -29,7 +29,7 @@ export function addRole(data) {
// 修改角色
export function updateRole(data) {
return request({
url: '/system/role',
url: '/business/businessRole',
method: 'put',
data: data
})
@ -38,7 +38,7 @@ export function updateRole(data) {
// 角色数据权限
export function dataScope(data) {
return request({
url: '/system/role/dataScope',
url: '/business/businessRole/dataScope',
method: 'put',
data: data
})
@ -51,7 +51,7 @@ export function changeRoleStatus(roleId, status) {
status
}
return request({
url: '/system/role/changeStatus',
url: '/business/businessRole/changeStatus',
method: 'put',
data: data
})
@ -60,7 +60,7 @@ export function changeRoleStatus(roleId, status) {
// 删除角色
export function delRole(roleId) {
return request({
url: '/system/role/' + roleId,
url: '/business/businessRole/' + roleId,
method: 'delete'
})
}
@ -68,7 +68,7 @@ export function delRole(roleId) {
// 查询角色已授权用户列表
export function allocatedUserList(query) {
return request({
url: '/system/role/authUser/allocatedList',
url: '/business/businessRole/authUser/allocatedList',
method: 'get',
params: query
})
@ -77,7 +77,7 @@ export function allocatedUserList(query) {
// 查询角色未授权用户列表
export function unallocatedUserList(query) {
return request({
url: '/system/role/authUser/unallocatedList',
url: '/business/businessRole/authUser/unallocatedList',
method: 'get',
params: query
})
@ -86,7 +86,7 @@ export function unallocatedUserList(query) {
// 取消用户授权角色
export function authUserCancel(data) {
return request({
url: '/system/role/authUser/cancel',
url: '/business/businessRole/authUser/cancel',
method: 'put',
data: data
})
@ -95,7 +95,7 @@ export function authUserCancel(data) {
// 批量取消用户授权角色
export function authUserCancelAll(data) {
return request({
url: '/system/role/authUser/cancelAll',
url: '/business/businessRole/authUser/cancelAll',
method: 'put',
params: data
})
@ -104,7 +104,7 @@ export function authUserCancelAll(data) {
// 授权用户选择
export function authUserSelectAll(data) {
return request({
url: '/system/role/authUser/selectAll',
url: '/business/businessRole/authUser/selectAll',
method: 'put',
params: data
})
@ -113,7 +113,7 @@ export function authUserSelectAll(data) {
// 根据角色ID查询部门树结构
export function deptTreeSelect(roleId) {
return request({
url: '/system/role/deptTree/' + roleId,
url: '/business/businessRole/deptTree/' + roleId,
method: 'get'
})
}

30
src/api/system/user.js

@ -4,7 +4,7 @@ import { praseStrEmpty } from "@/utils/ruoyi";
// 查询用户列表
export function listUser(query) {
return request({
url: '/system/user/list',
url: '/business/businessUser/list',
method: 'get',
params: query
})
@ -13,7 +13,7 @@ export function listUser(query) {
// 查询用户详细
export function getUser(userId) {
return request({
url: '/system/user/' + praseStrEmpty(userId),
url: '/business/businessUser/' + praseStrEmpty(userId),
method: 'get'
})
}
@ -21,7 +21,7 @@ export function getUser(userId) {
// 新增用户
export function addUser(data) {
return request({
url: '/system/user',
url: '/business/businessUser',
method: 'post',
data: data
})
@ -30,7 +30,7 @@ export function addUser(data) {
// 修改用户
export function updateUser(data) {
return request({
url: '/system/user',
url: '/business/businessUser',
method: 'put',
data: data
})
@ -39,7 +39,7 @@ export function updateUser(data) {
// 删除用户
export function delUser(userId) {
return request({
url: '/system/user/' + userId,
url: '/business/businessUser/' + userId,
method: 'delete'
})
}
@ -47,7 +47,7 @@ export function delUser(userId) {
// 导出用户
export function exportUser(query) {
return request({
url: '/system/user/export',
url: '/business/businessUser/export',
method: 'get',
params: query
})
@ -56,11 +56,11 @@ export function exportUser(query) {
// 用户密码重置
export function resetUserPwd(userId, password) {
const data = {
userId,
password
id: userId,
passwordHash: password
}
return request({
url: '/system/user/resetPwd',
url: '/business/businessUser/resetPwd',
method: 'put',
data: data
})
@ -73,7 +73,7 @@ export function changeUserStatus(userId, status) {
status
}
return request({
url: '/system/user/changeStatus',
url: '/business/businessUser/changeStatus',
method: 'put',
data: data
})
@ -82,7 +82,7 @@ export function changeUserStatus(userId, status) {
// 查询用户个人信息
export function getUserProfile() {
return request({
url: '/system/user/profile',
url: '/business/businessUser/profile',
method: 'get'
})
}
@ -90,7 +90,7 @@ export function getUserProfile() {
// 修改用户个人信息
export function updateUserProfile(data) {
return request({
url: '/system/user/profile',
url: '/business/businessUser/profile',
method: 'put',
data: data
})
@ -103,7 +103,7 @@ export function updateUserPwd(oldPassword, newPassword) {
newPassword
}
return request({
url: '/system/user/profile/updatePwd',
url: '/business/businessUser/profile/updatePwd',
method: 'put',
params: data
})
@ -112,7 +112,7 @@ export function updateUserPwd(oldPassword, newPassword) {
// 用户头像上传
export function uploadAvatar(data) {
return request({
url: '/system/user/profile/avatar',
url: '/business/businessUser/profile/avatar',
method: 'post',
data: data
})
@ -121,7 +121,7 @@ export function uploadAvatar(data) {
// 下载用户导入模板
export function importTemplate() {
return request({
url: '/system/user/importTemplate',
url: '/business/businessUser/importTemplate',
method: 'get'
})
}

2
src/utils/auth.js

@ -1,6 +1,6 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
const TokenKey = 'Admin-Token-CUSTOMER'
export function getToken() {
return Cookies.get(TokenKey)

431
src/views/business/businessApiConfig/index.vue

@ -1,431 +0,0 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryForm"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="企业ID" prop="merchantId" v-show="false">
<el-input
v-model="queryParams.merchantId"
placeholder="请输入企业ID"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="所属企业" prop="merchantName">
<el-input
v-model="queryParams.merchantName"
placeholder="请选择企业"
clearable
readonly
@click="searchBusinessSelectVisible = true"
/>
<el-button
icon="el-icon-search"
size="mini"
type="primary"
@click="searchBusinessSelectVisible = true"
>选择</el-button
>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
clearable
size="small"
>
<el-option label="启用" :value="1" />
<el-option label="禁用" :value="0" />
</el-select>
</el-form-item>
<el-form-item label="IP白名单" prop="ipWhitelist">
<el-input
v-model="queryParams.ipWhitelist"
placeholder="请输入IP白名单"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['business:businessApiConfig:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['business:businessApiConfig:edit']"
>修改</el-button
>
</el-col>
<!-- <el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['business:businessApiConfig:remove']"
>删除</el-button
>
</el-col> -->
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['business:businessApiConfig:export']"
>导出</el-button
>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="businessApiConfigList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="企业编号" align="center" prop="merchantNo" />
<el-table-column label="企业公钥" align="center" prop="merchantPubligKey" />
<el-table-column label="系统公钥" align="center" prop="systemPubligKey" />
<el-table-column label="系统私钥" align="center" prop="systemPrivateKey" />
<el-table-column label="状态" align="center" prop="status" />
<el-table-column label="IP白名单" align="center" prop="ipWhitelist" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['business:businessApiConfig:edit']"
>修改</el-button
>
<!-- <el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['business:businessApiConfig:remove']"
>删除</el-button
> -->
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改企业api配置表对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="企业ID" prop="merchantId" v-show="false">
<el-input v-model="form.merchantId" placeholder="请输入企业ID" />
</el-form-item>
<el-form-item label="企业编号" prop="merchantNo">
<el-input
v-model="form.merchantNo"
placeholder="请输入企业编号"
:disabled="true"
/>
</el-form-item>
<el-form-item label="企业名称" prop="merchantName">
<el-input
v-model="form.merchantName"
placeholder="请选择企业"
clearable
readonly
@click="businessSelectVisible = true"
/>
<el-button
icon="el-icon-search"
size="mini"
type="primary"
@click="businessSelectVisible = true"
>选择</el-button
>
</el-form-item>
<el-form-item label="企业公钥" prop="merchantPubligKey">
<el-input
v-model="form.merchantPubligKey"
type="textarea"
placeholder="请输入内容"
/>
</el-form-item>
<el-form-item label="系统公钥" prop="systemPubligKey">
<el-input
v-model="form.systemPubligKey"
type="textarea"
placeholder="请输入内容"
/>
</el-form-item>
<el-form-item label="系统私钥" prop="systemPrivateKey">
<el-input
v-model="form.systemPrivateKey"
type="textarea"
placeholder="请输入内容"
/>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio :label="1">启用</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="IP白名单" prop="ipWhitelist">
<el-input v-model="form.ipWhitelist" placeholder="请输入IP白名单" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 1. 新增搜索专用 -->
<BusinessSelect
:visible.sync="searchBusinessSelectVisible"
@select="handleSearchBusinessSelect"
/>
<BusinessSelect
:visible.sync="businessSelectVisible"
@select="handleAddBusinessSelect"
/>
</div>
</template>
<script>
import {
listBusinessApiConfig,
getBusinessApiConfig,
delBusinessApiConfig,
addBusinessApiConfig,
updateBusinessApiConfig,
exportBusinessApiConfig,
} from "@/api/business/businessApiConfig";
import BusinessSelect from "@/components/business/BusinessSelect";
export default {
name: "BusinessApiConfig",
components: { BusinessSelect },
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
// api
businessApiConfigList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
merchantId: null,
merchantNo: null,
merchantPubligKey: null,
systemPubligKey: null,
systemPrivateKey: null,
status: null,
ipWhitelist: null,
},
//
form: {},
//
rules: {
systemPubligKey: [
{ required: true, message: "系统公钥不能为空", trigger: "blur" },
],
systemPrivateKey: [
{ required: true, message: "系统私钥不能为空", trigger: "blur" },
],
status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
updateTime: [{ required: true, message: "更新时间不能为空", trigger: "blur" }],
},
searchBusinessSelectVisible: false,
businessSelectVisible: false,
};
},
created() {
this.getList();
},
methods: {
/** 查询企业api配置表列表 */
getList() {
this.loading = true;
listBusinessApiConfig(this.queryParams).then((response) => {
this.businessApiConfigList = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
merchantId: null,
merchantNo: null,
merchantPubligKey: null,
systemPubligKey: null,
systemPrivateKey: null,
status: 1,
ipWhitelist: null,
createTime: null,
updateTime: null,
merchantName: "",
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加企业api配置表";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids;
getBusinessApiConfig(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = "修改企业api配置表";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.id != null) {
updateBusinessApiConfig(this.form).then((response) => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addBusinessApiConfig(this.form).then((response) => {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$confirm('是否确认删除企业api配置表编号为"' + ids + '"的数据项?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delBusinessApiConfig(ids);
})
.then(() => {
this.getList();
this.msgSuccess("删除成功");
});
},
/** 导出按钮操作 */
handleExport() {
const queryParams = this.queryParams;
this.$confirm("是否确认导出所有企业api配置表数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return exportBusinessApiConfig(queryParams);
})
.then((response) => {
this.download(response.msg);
});
},
handleSearchBusinessSelect(row) {
this.queryParams.merchantId = row.id; // ID
this.queryParams.merchantName = row.name; //
this.queryParams.merchantNo = row.merchantNo;
this.searchBusinessSelectVisible = false; //
},
handleAddBusinessSelect(row) {
this.form.merchantId = row.id; // ID
this.form.merchantName = row.name; //
this.form.merchantNo = row.merchantNo;
this.businessSelectVisible = false; //
},
},
};
</script>

369
src/views/business/businessLogininfor/index.vue

@ -1,369 +0,0 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryForm"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="企业名称" prop="merchantName">
<el-input
v-model="queryParams.merchantName"
placeholder="请输入企业名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="登录IP地址" prop="ipaddr">
<el-input
v-model="queryParams.ipaddr"
placeholder="请输入登录IP地址"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="登录状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择登录状态"
clearable
size="small"
>
<el-option label="成功" :value="0" />
<el-option label="失败" :value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['business:businessLogininfor:add']"
>新增</el-button
>
</el-col> -->
<!-- <el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['business:businessLogininfor:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['business:businessLogininfor:remove']"
>删除</el-button
>
</el-col> -->
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['business:businessLogininfor:export']"
>导出</el-button
>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="businessLogininforList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="" align="center" prop="id" />
<el-table-column label="企业Id" align="center" prop="merchantId" />
<el-table-column label="企业名称" align="center" prop="merchantName" />
<el-table-column label="登录IP地址" align="center" prop="ipaddr" />
<el-table-column label="登录地点" align="center" prop="loginLocation" />
<el-table-column label="浏览器类型" align="center" prop="browser" />
<el-table-column label="操作系统" align="center" prop="os" />
<el-table-column label="登录状态" align="center" prop="status" />
<el-table-column label="提示信息" align="center" prop="msg" />
<el-table-column label="访问时间" align="center" prop="loginTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.loginTime, "{y}-{m}-{d}") }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['business:businessLogininfor:edit']"
>修改</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['business:businessLogininfor:remove']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改企业登录日志对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="企业Id" prop="merchantId">
<el-input v-model="form.merchantId" placeholder="请输入企业Id" />
</el-form-item>
<el-form-item label="企业名称" prop="merchantName">
<el-input v-model="form.merchantName" placeholder="请输入企业名称" />
</el-form-item>
<el-form-item label="登录IP地址" prop="ipaddr">
<el-input v-model="form.ipaddr" placeholder="请输入登录IP地址" />
</el-form-item>
<el-form-item label="登录地点" prop="loginLocation">
<el-input v-model="form.loginLocation" placeholder="请输入登录地点" />
</el-form-item>
<el-form-item label="浏览器类型" prop="browser">
<el-input v-model="form.browser" placeholder="请输入浏览器类型" />
</el-form-item>
<el-form-item label="操作系统" prop="os">
<el-input v-model="form.os" placeholder="请输入操作系统" />
</el-form-item>
<el-form-item label="登录状态">
<el-radio-group v-model="form.status">
<el-radio label="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="提示信息" prop="msg">
<el-input v-model="form.msg" placeholder="请输入提示信息" />
</el-form-item>
<el-form-item label="访问时间" prop="loginTime">
<el-date-picker
clearable
size="small"
v-model="form.loginTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择访问时间"
>
</el-date-picker>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listBusinessLogininfor,
getBusinessLogininfor,
delBusinessLogininfor,
addBusinessLogininfor,
updateBusinessLogininfor,
exportBusinessLogininfor,
} from "@/api/business/businessLogininfor";
export default {
name: "BusinessLogininfor",
components: {},
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
businessLogininforList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
merchantId: null,
merchantName: null,
ipaddr: null,
loginLocation: null,
browser: null,
os: null,
status: null,
msg: null,
loginTime: null,
},
//
form: {},
//
rules: {},
};
},
created() {
this.getList();
},
methods: {
/** 查询企业登录日志列表 */
getList() {
this.loading = true;
listBusinessLogininfor(this.queryParams).then((response) => {
this.businessLogininforList = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
merchantId: null,
merchantName: null,
ipaddr: null,
loginLocation: null,
browser: null,
os: null,
status: "0",
msg: null,
loginTime: null,
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加企业登录日志";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids;
getBusinessLogininfor(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = "修改企业登录日志";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.id != null) {
updateBusinessLogininfor(this.form).then((response) => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addBusinessLogininfor(this.form).then((response) => {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$confirm('是否确认删除企业登录日志编号为"' + ids + '"的数据项?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delBusinessLogininfor(ids);
})
.then(() => {
this.getList();
this.msgSuccess("删除成功");
});
},
/** 导出按钮操作 */
handleExport() {
const queryParams = this.queryParams;
this.$confirm("是否确认导出所有企业登录日志数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return exportBusinessLogininfor(queryParams);
})
.then((response) => {
this.download(response.msg);
});
},
},
};
</script>

209
src/views/device/device/index.vue

@ -1,4 +1,4 @@
<template>
<template>
<div class="app-container">
<el-form
:model="queryParams"
@ -191,66 +191,9 @@
:rules="importRules"
label-width="90px"
>
<!-- 企业信息核心 -->
<el-form-item label="企业ID" prop="bindBusinessId" v-show="false">
<el-input
v-model="importForm.bindBusinessId"
placeholder="请选择企业"
clearable
readonly
/>
</el-form-item>
<el-form-item label="企业名称" prop="businessName">
<el-input
v-model="importForm.businessName"
placeholder="请选择企业"
clearable
readonly
@click="businessSelectVisible = true"
/>
<el-button
icon="el-icon-search"
size="mini"
type="primary"
@click="businessSelectVisible = true"
>选择</el-button
>
</el-form-item>
<!-- 订单号输入框 -->
<el-form-item label="订单号" prop="orderCode">
<el-input
v-model="importForm.orderCode"
placeholder="请输入订单号"
clearable
maxlength="50"
show-word-limit
@change="handleOrderCodeChange"
/>
</el-form-item>
<!-- 新增批次号输入框只读从后台获取 -->
<el-form-item label="批次号" prop="batchNo">
<el-input
v-model="importForm.batchNo"
placeholder="请等待获取批次号..."
clearable
maxlength="50"
show-word-limit
readonly
/>
</el-form-item>
<!-- 备注输入框 -->
<el-form-item label="备注" prop="remark">
<el-input
v-model="importForm.remark"
placeholder="请输入备注(选填)"
type="textarea"
:rows="3"
maxlength="200"
show-word-limit
/>
</el-form-item>
<!-- Excel文件上传仅1个文件修复核心 -->
<el-form-item label="Excel文件">
@ -281,6 +224,77 @@
<el-button @click="cancelImport"> </el-button>
</div>
</el-dialog>
<el-dialog
title="导入结果"
:visible.sync="resultOpen"
width="700px"
append-to-body
>
<div v-if="latestImportResult">
<el-alert
:title="getImportStatusMessage(latestImportResult)"
:type="getImportStatusType(latestImportResult.status)"
:closable="false"
show-icon
/>
<el-descriptions :column="2" border class="import-result-summary">
<el-descriptions-item label="状态">
{{ getImportStatusLabel(latestImportResult.status) }}
</el-descriptions-item>
<el-descriptions-item label="总数">
{{ latestImportResult.total }}
</el-descriptions-item>
<el-descriptions-item label="成功数">
{{ latestImportResult.successCount }}
</el-descriptions-item>
<el-descriptions-item label="失败数">
{{ latestImportResult.failCount }}
</el-descriptions-item>
<el-descriptions-item label="开始时间">
{{ parseTime(latestImportResult.startTime) }}
</el-descriptions-item>
<el-descriptions-item label="结束时间">
{{ parseTime(latestImportResult.finishTime) }}
</el-descriptions-item>
</el-descriptions>
<div
v-if="latestImportResult.requestErrors && latestImportResult.requestErrors.length"
class="import-result-block"
>
<div class="import-result-title">请求错误</div>
<div
v-for="(item, index) in latestImportResult.requestErrors"
:key="'request-error-' + index"
class="import-result-text"
>
{{ index + 1 }}. {{ item }}
</div>
</div>
<div
v-if="latestImportResult.errors && latestImportResult.errors.length"
class="import-result-block"
>
<div class="import-result-title">失败明细</div>
<el-table
:data="latestImportResult.errors"
size="mini"
border
max-height="320"
>
<el-table-column label="行号" prop="rowIndex" width="100" align="center" />
<el-table-column label="错误信息" prop="message" min-width="460" />
</el-table>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="resultOpen = false"> </el-button>
</div>
</el-dialog>
<!-- 核心必须挂载企业选择组件且绑定正确的开关 -->
<BusinessSelect
:visible.sync="businessSelectVisible"
@ -396,8 +410,7 @@ import {
getBatchNo,
} from "@/api/device/device";
// API
import { importDevice } from "@/api/device/device";
import { getToken } from "@/utils/auth";
import { importDeviceSync } from "@/api/device/device";
//
import BusinessSelect from "@/components/business/BusinessSelect"; //
@ -453,6 +466,10 @@ export default {
fileList: [],
// Excel
uploadFile: null,
//
latestImportResult: null,
//
resultOpen: false,
//
queryParams: {
pageNum: 1,
@ -716,10 +733,18 @@ export default {
try {
this.importing = true;
// 4.
const res = await importDevice(formData);
this.$message.success("导入成功!");
const res = await importDeviceSync(formData);
this.latestImportResult = this.normalizeImportResult(res.data);
this.importOpen = false;
this.getList();
this.resultOpen = true;
if (this.latestImportResult.successCount > 0) {
this.getList();
}
if (this.latestImportResult.failCount > 0 || this.latestImportResult.requestErrors.length > 0) {
this.$message.warning(this.getImportStatusMessage(this.latestImportResult));
} else {
this.$message.success("导入成功!");
}
} catch (error) {
this.$message.error("导入失败:" + (error.message || "服务器异常"));
} finally {
@ -769,6 +794,62 @@ export default {
this.businessSelectVisible = false; //
},
normalizeImportResult(data) {
return {
status: data?.status || "",
total: data?.total || 0,
successCount: data?.successCount || 0,
failCount: data?.failCount || 0,
startTime: data?.startTime || null,
finishTime: data?.finishTime || null,
requestErrors: Array.isArray(data?.requestErrors) ? data.requestErrors : [],
errors: Array.isArray(data?.errors) ? data.errors : [],
};
},
getImportStatusLabel(status) {
const statusMap = {
SUCCESS: "导入成功",
PARTIAL_SUCCESS: "部分成功",
FAILED: "导入失败",
REQUEST_INVALID: "请求校验失败",
};
return statusMap[status] || status || "未知状态";
},
getImportStatusType(status) {
const typeMap = {
SUCCESS: "success",
PARTIAL_SUCCESS: "warning",
FAILED: "error",
REQUEST_INVALID: "error",
};
return typeMap[status] || "info";
},
getImportStatusMessage(result) {
const statusLabel = this.getImportStatusLabel(result.status);
return `${statusLabel},成功 ${result.successCount} 条,失败 ${result.failCount}`;
},
},
};
</script>
<style scoped>
.import-result-summary {
margin-top: 16px;
}
.import-result-block {
margin-top: 16px;
}
.import-result-title {
margin-bottom: 8px;
font-size: 14px;
font-weight: 600;
color: #303133;
}
.import-result-text {
line-height: 1.8;
color: #606266;
}
</style>

138
src/views/system/menu/index.vue

@ -12,10 +12,10 @@
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
v-for="item in normalDisableOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
@ -54,20 +54,20 @@
:data="menuList"
row-key="menuId"
:default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160" />
<el-table-column prop="icon" label="图标" align="center" width="100">
<template slot-scope="scope">
<svg-icon :icon-class="scope.row.icon" />
</template>
</el-table-column>
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="orderNum" label="排序" width="60" />
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true" />
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true" />
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
<dict-tag :options="normalDisableOptions" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
@ -102,7 +102,6 @@
</el-table-column>
</el-table>
<!-- 添加或修改菜单对话框 -->
<el-dialog :title="title" :visible.sync="open" width="680px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row>
@ -136,7 +135,7 @@
placement="bottom-start"
width="460"
trigger="click"
@show="$refs['iconSelect'].reset()"
@show="$refs.iconSelect.reset()"
>
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
@ -168,7 +167,7 @@
<el-input v-model="form.routeName" placeholder="请输入路由名称" />
<span slot="label">
<el-tooltip content="默认不填则和路由地址相同:如地址为:`user`,则名称为`User`(注意:为避免名字的冲突,特殊情况下请自定义,保证唯一性)" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
路由名称
</span>
@ -180,7 +179,7 @@
<el-form-item prop="isFrame">
<span slot="label">
<el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
是否外链
</span>
@ -194,7 +193,7 @@
<el-form-item prop="path">
<span slot="label">
<el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
路由地址
</span>
@ -207,7 +206,7 @@
<el-form-item prop="component">
<span slot="label">
<el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
组件路径
</span>
@ -219,7 +218,7 @@
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
<span slot="label">
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
权限字符
</span>
@ -232,7 +231,7 @@
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
<span slot="label">
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
路由参数
</span>
@ -242,7 +241,7 @@
<el-form-item prop="isCache">
<span slot="label">
<el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
是否缓存
</span>
@ -258,16 +257,16 @@
<el-form-item prop="visible">
<span slot="label">
<el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
显示状态
</span>
<el-radio-group v-model="form.visible">
<el-radio
v-for="dict in dict.type.sys_show_hide"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
v-for="item in showHideOptions"
:key="item.value"
:label="item.value"
>{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
@ -275,16 +274,16 @@
<el-form-item prop="status">
<span slot="label">
<el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
<i class="el-icon-question"></i>
<i class="el-icon-question" />
</el-tooltip>
菜单状态
</span>
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
v-for="item in normalDisableOptions"
:key="item.value"
:label="item.value"
>{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
@ -304,36 +303,35 @@ import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import IconSelect from "@/components/IconSelect"
const SHOW_HIDE_FALLBACK = [
{ label: "显示", value: "0" },
{ label: "隐藏", value: "1" }
]
const NORMAL_DISABLE_FALLBACK = [
{ label: "正常", value: "0" },
{ label: "停用", value: "1" }
]
export default {
name: "Menu",
dicts: ['sys_show_hide', 'sys_normal_disable'],
dicts: [],
components: { Treeselect, IconSelect },
data() {
return {
//
loading: true,
//
showSearch: true,
//
menuList: [],
//
menuOptions: [],
//
title: "",
//
open: false,
//
isExpandAll: false,
//
refreshTable: true,
//
queryParams: {
menuName: undefined,
visible: undefined
status: undefined
},
//
form: {},
//
rules: {
menuName: [
{ required: true, message: "菜单名称不能为空", trigger: "blur" }
@ -347,15 +345,38 @@ export default {
}
}
},
computed: {
// showHideOptions() {
// return this.normalizeDictOptions(this.dict.type.sys_show_hide, SHOW_HIDE_FALLBACK)
// },
// normalDisableOptions() {
// return this.normalizeDictOptions(this.dict.type.sys_normal_disable, NORMAL_DISABLE_FALLBACK)
// }
},
created() {
this.getList()
},
methods: {
//
normalizeDictOptions(options, fallback) {
const source = Array.isArray(options) && options.length ? options : fallback
return source.map(item => ({
...item,
value: String(item.value)
}))
},
normalizeMenuForm(data = {}) {
return {
...data,
menuType: data.menuType !== undefined && data.menuType !== null ? String(data.menuType) : "M",
isFrame: data.isFrame !== undefined && data.isFrame !== null ? String(data.isFrame) : "1",
isCache: data.isCache !== undefined && data.isCache !== null ? String(data.isCache) : "0",
visible: data.visible !== undefined && data.visible !== null ? String(data.visible) : "0",
status: data.status !== undefined && data.status !== null ? String(data.status) : "0"
}
},
selected(name) {
this.form.icon = name
},
/** 查询菜单列表 */
getList() {
this.loading = true
listMenu(this.queryParams).then(response => {
@ -363,7 +384,6 @@ export default {
this.loading = false
})
},
/** 转换菜单数据结构 */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children
@ -374,23 +394,20 @@ export default {
children: node.children
}
},
/** 查询菜单下拉树结构 */
getTreeselect() {
listMenu().then(response => {
this.menuOptions = []
const menu = { menuId: 0, menuName: '主类目', children: [] }
const menu = { menuId: 0, menuName: "主类目", children: [] }
menu.children = this.handleTree(response.data, "menuId")
this.menuOptions.push(menu)
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
this.form = this.normalizeMenuForm({
menuId: undefined,
parentId: 0,
menuName: undefined,
@ -401,19 +418,16 @@ export default {
isCache: "0",
visible: "0",
status: "0"
}
})
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
/** 新增按钮操作 */
handleAdd(row) {
this.reset()
this.getTreeselect()
@ -425,7 +439,6 @@ export default {
this.open = true
this.title = "添加菜单"
},
/** 展开/折叠操作 */
toggleExpandAll() {
this.refreshTable = false
this.isExpandAll = !this.isExpandAll
@ -433,28 +446,26 @@ export default {
this.refreshTable = true
})
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
this.getTreeselect()
getMenu(row.menuId).then(response => {
this.form = response.data
this.form = this.normalizeMenuForm(response.data)
this.open = true
this.title = "修改菜单"
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
if (this.form.menuId != undefined) {
updateMenu(this.form).then(response => {
if (this.form.menuId !== undefined) {
updateMenu(this.form).then(() => {
this.$modal.msgSuccess("修改成功")
this.open = false
this.getList()
})
} else {
addMenu(this.form).then(response => {
addMenu(this.form).then(() => {
this.$modal.msgSuccess("新增成功")
this.open = false
this.getList()
@ -463,7 +474,6 @@ export default {
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() {
return delMenu(row.menuId)

1046
src/views/system/role/index.vue

File diff suppressed because it is too large

226
src/views/system/user/index.vue

@ -4,9 +4,9 @@
<!--用户数据-->
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户名称" prop="userName">
<el-form-item label="用户名称" prop="account">
<el-input
v-model="queryParams.userName"
v-model="queryParams.account"
placeholder="请输入用户名称"
clearable
size="small"
@ -14,10 +14,10 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-form-item label="昵称" prop="nickName">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
v-model="queryParams.nickName"
placeholder="请输入昵称"
clearable
size="small"
style="width: 240px"
@ -32,26 +32,10 @@
size="small"
style="width: 240px"
>
<el-option
v-for="dict in statusOptions"
:key="dict.dictValue"
:label="dict.dictLabel"
:value="dict.dictValue"
/>
<el-option label="启用" :value="0" />
<el-option label="禁用" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
size="small"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -91,7 +75,7 @@
v-hasPermi="['system:user:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<!-- <el-col :span="1.5">
<el-button
type="info"
plain
@ -100,7 +84,7 @@
@click="handleImport"
v-hasPermi="['system:user:import']"
>导入</el-button>
</el-col>
</el-col> -->
<el-col :span="1.5">
<el-button
type="warning"
@ -116,8 +100,8 @@
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="用户编号" align="center" key="id" prop="id" v-if="columns[0].visible" />
<el-table-column label="用户名称" align="center" key="account" prop="account" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
<!-- <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />-->
<!-- <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />-->
@ -131,9 +115,11 @@
></el-switch>
</template>
</el-table-column>
<el-table-column label="谷歌令牌" align="center" key="googleCaptcha" prop="googleCaptcha" v-if="columns[6].visible">
<el-table-column label="谷歌令牌" align="center" key="googleAuthSecret" prop="googleAuthSecret" v-if="columns[6].visible">
<template slot-scope="scope">
<img :src="columns[6].url+'?content=otpauth://totp/GEO TAG_'+scope.row.userName+'?secret='+scope.row.googleCaptcha" style="width: 100px; height: 100px;">
<!-- <img :src="columns[6].url+'?content=otpauth://totp/GEO TAG_'+scope.row.account+'?secret='+scope.row.googleAuthSecret" style="width: 100px; height: 100px;"> -->
<img :src="columns[6].url + '?content=' + encodeURIComponent(`otpauth://totp/GEO TAG_${scope.row.account}?secret=${scope.row.googleAuthSecret}`)" style="width: 100px; height: 100px;">
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[7].visible" width="160">
@ -156,7 +142,7 @@
v-hasPermi="['system:user:edit']"
>修改</el-button>
<el-button
v-if="scope.row.userId !== 1"
v-if="scope.row.id !== 1"
size="mini"
type="text"
icon="el-icon-delete"
@ -188,13 +174,13 @@
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
<el-input v-model="form.userName" placeholder="请输入用户名称" />
<el-form-item v-if="form.id == undefined" label="用户名称" prop="account">
<el-input v-model="form.account" placeholder="请输入用户名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" />
<el-form-item v-if="form.id == undefined" label="用户密码" prop="passwordHash">
<el-input v-model="form.passwordHash" placeholder="请输入用户密码" type="passwordHash" />
</el-form-item>
</el-col>
</el-row>
@ -207,14 +193,19 @@
<el-col :span="12">
<el-form-item label="角色">
<el-select v-model="form.roleIds" label="item.roleName" :options="roleOptions" multiple placeholder="请选择">
<el-select
v-model="form.roleIds"
multiple
filterable
placeholder="请选择角色(全部角色)"
style="width: 100%"
>
<el-option
v-for="item in roleOptions"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
:disabled="item.status == 1"
></el-option>
:label="(item.roleName || item.name) || ('角色' + item.roleId)"
:value="String(item.roleId)"
/>
</el-select>
</el-form-item>
</el-col>
@ -224,13 +215,10 @@
<el-row>
<el-col :span="12">
<el-form-item label="状态">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{{dict.dictLabel}}</el-radio>
<el-radio :label="0">启用</el-radio>
<el-radio :label="1">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
@ -285,6 +273,7 @@
<script>
import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus, importTemplate } from "@/api/system/user";
import { listRole } from "@/api/system/role";
import { getToken } from "@/utils/auth";
// import { treeselect } from "@/api/system/dept";
import Treeselect from "@riophae/vue-treeselect";
@ -318,7 +307,7 @@ export default {
//
deptName: undefined,
//
initPassword: undefined,
passwordHash: undefined,
//
dateRange: [],
//
@ -329,8 +318,10 @@ export default {
postOptions: [],
//
roleOptions: [],
//
form: {},
// roleIds
form: {
roleIds: []
},
defaultProps: {
children: "children",
label: "label"
@ -354,7 +345,7 @@ export default {
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
account: undefined,
phonenumber: undefined,
status: undefined,
deptId: undefined
@ -367,18 +358,18 @@ export default {
{ key: 3, label: `部门`, visible: true },
{ key: 4, label: `手机号码`, visible: true },
{ key: 5, label: `状态`, visible: true },
{ key: 6, label: `谷歌令牌`, visible: true, url: process.env.VUE_APP_BASE_API + "/system/config/activityCode" },
{ key: 6, label: `谷歌令牌`, visible: true, url: process.env.VUE_APP_BASE_API + "/business/businessUser/activityCode" },
{ key: 7, label: `创建时间`, visible: true }
],
//
rules: {
userName: [
account: [
{ required: true, message: "用户名称不能为空", trigger: "blur" }
],
nickName: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
],
password: [
passwordHash: [
{ required: true, message: "用户密码不能为空", trigger: "blur" }
],
email: [
@ -406,24 +397,38 @@ export default {
},
created() {
this.getList();
this.getRoleList();
// this.getTreeselect();
this.getDicts("sys_normal_disable").then(response => {
this.statusOptions = response.data;
});
this.getDicts("sys_user_sex").then(response => {
this.sexOptions = response.data;
});
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg;
});
// this.getDicts("sys_normal_disable").then(response => {
// this.statusOptions = response.data;
// });
// this.getDicts("sys_user_sex").then(response => {
// this.sexOptions = response.data;
// });
// this.getConfigKey("sys.user.passwordHash").then(response => {
// this.passwordHash = response.msg;
// });
},
methods: {
/** 查询角色列表(拉取全部角色,统一为 roleId/roleName 便于下拉展示) */
getRoleList() {
listRole({ pageNum: 1, pageSize: 1000 }).then(response => {
const list = response.data.list || response.data || [];
this.roleOptions = list.map(item => ({
roleId: item.roleId != null ? item.roleId : item.id,
roleName: item.roleName != null ? item.roleName : item.name
}));
});
},
/** 查询用户列表 */
getList() {
this.loading = true;
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.data.list;
// console.log(this.userList[0].googleCaptcha)
this.userList = response.data.list.map(user => ({
...user,
status: String(user.status) //
}));
// console.log(this.userList[0].googleAuthSecret)
this.total = Number(response.data.total);
this.loading = false;
}
@ -448,12 +453,12 @@ export default {
//
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用";
this.$confirm('确认要"' + text + '""' + row.userName + '"用户吗?', "警告", {
this.$confirm('确认要"' + text + '""' + row.account + '"用户吗?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(function() {
return changeUserStatus(row.userId, row.status);
return changeUserStatus(row.id, row.status);
}).then(() => {
this.msgSuccess(text + "成功");
}).catch(function() {
@ -468,15 +473,15 @@ export default {
//
reset() {
this.form = {
userId: undefined,
id: undefined,
deptId: undefined,
userName: undefined,
account: undefined,
nickName: undefined,
password: undefined,
passwordHash: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
status: 0,
remark: undefined,
postIds: [],
roleIds: []
@ -496,49 +501,66 @@ export default {
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.userId);
this.ids = selection.map(item => item.id);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
// this.getTreeselect();
getUser().then(response => {
this.postOptions = response.posts;
this.roleOptions = response.roles;
this.open = true;
this.title = "添加用户";
this.form.password = this.initPassword;
});
this.getRoleList();
this.open = true;
this.title = "添加用户";
this.form.passwordHash = this.passwordHash;
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
// this.getTreeselect();
const userId = row.userId || this.ids;
getUser(userId).then(response => {
this.form = response.data;
this.postOptions = response.posts;
this.roleOptions = response.roles;
this.form.postIds = response.postIds;
this.form.roleIds = [];
response.roleIds.forEach((roleId)=>{
this.form.roleIds.push(roleId.toString())
})
const id = row.id || this.ids;
Promise.all([getUser(id), listRole({ pageNum: 1, pageSize: 1000 })]).then(([userRes, roleRes]) => {
const data = userRes.data; // data
// roleIdsroles data
const resRoleIds = userRes.roleIds || [];
const resRoles = userRes.roles || [];
const list = roleRes.data?.list || roleRes.data || [];
// listRole getUser roles roleName /
const optionsMap = new Map();
list.forEach(item => {
optionsMap.set(String(item.roleId != null ? item.roleId : item.id), {
roleId: item.roleId != null ? item.roleId : item.id,
roleName: item.roleName != null ? item.roleName : item.name
});
});
resRoles.forEach(r => {
const rid = r.roleId != null ? r.roleId : r.id;
const name = r.roleName != null ? r.roleName : r.name;
if (rid != null) optionsMap.set(String(rid), { roleId: rid, roleName: name });
});
this.roleOptions = Array.from(optionsMap.values());
// roleIds
const roleIds = resRoleIds.map(rid => String(rid));
this.open = true;
this.form = Object.assign({}, data, {
postIds: userRes.postIds || [],
roleIds: roleIds,
passwordHash: ""
});
this.$set(this.form, "roleIds", roleIds);
this.title = "修改用户";
this.form.password = "";
this.$nextTick(() => {
this.open = true;
});
});
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
this.$prompt('请输入"' + row.account + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => {
resetUserPwd(row.id, value).then(response => {
this.msgSuccess("修改成功,新密码是:" + value);
});
}).catch(() => {});
@ -547,14 +569,20 @@ export default {
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.userId != undefined) {
updateUser(this.form).then(response => {
// ID
const submitData = {
...this.form,
roleIds: this.form.roleIds.map(id => Number(id))
};
if (this.form.id != undefined) {
updateUser(submitData).then(response => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addUser(this.form).then(response => {
addUser(submitData).then(response => {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
@ -565,13 +593,13 @@ export default {
},
/** 删除按钮操作 */
handleDelete(row) {
const userIds = row.userId || this.ids;
this.$confirm('是否确认删除用户编号为"' + userIds + '"的数据项?', "警告", {
const ids = row.id || this.ids;
this.$confirm('是否确认删除用户编号为"' + ids + '"的数据项?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(function() {
return delUser(userIds);
return delUser(ids);
}).then(() => {
this.getList();
this.msgSuccess("删除成功");

4
vue.config.js

@ -9,9 +9,9 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '客户GEO TAG管理系统' // 网页标题
const baseUrl = 'http://127.0.0.1:10021' // 后端接口
const baseUrl = 'http://127.0.0.1:10022' // 后端接口
// const baseUrl ="https://hfmt8jvy.currencyacquirer.online/stage-api/"
const port = process.env.port || process.env.npm_config_port || 80 // 端口
const port = process.env.port || process.env.npm_config_port || 81 // 端口
// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions

Loading…
Cancel
Save