初始化

master
袁子龙 2024-08-20 22:07:34 +08:00
parent 36539bff16
commit 29f470c7c1
8 changed files with 631 additions and 0 deletions

13
babel.config.js 100644
View File

@ -0,0 +1,13 @@
module.exports = {
presets: [
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
'@vue/cli-plugin-babel/preset'
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
'plugins': ['dynamic-import-node']
}
}
}

28
src/App.vue 100644
View File

@ -0,0 +1,28 @@
<template>
<div id="app">
<router-view/>
<theme-picker/>
</div>
</template>
<script>
import ThemePicker from "@/components/ThemePicker";
export default {
name: "App",
components: {ThemePicker},
metaInfo() {
return {
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
titleTemplate: title => {
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
}
}
}
};
</script>
<style scoped>
#app .theme-picker {
display: none;
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<section class="app-main">
<transition mode="out-in" name="fade-transform">
<keep-alive :include="cachedViews">
<router-view v-if="!$route.meta.link" :key="key"/>
</keep-alive>
</transition>
<iframe-toggle/>
</section>
</template>
<script>
import iframeToggle from "./IframeToggle/index"
export default {
name: 'AppMain',
components: {iframeToggle},
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
},
key() {
return this.$route.path
}
}
}
</script>
<style lang="scss" scoped>
.app-main {
/* 50= navbar 50 */
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: hidden;
}
.fixed-header + .app-main {
padding-top: 50px;
}
.hasTagsView {
.app-main {
/* 84 = navbar + tags-view = 50 + 34 */
min-height: calc(100vh - 84px);
}
.fixed-header + .app-main {
padding-top: 84px;
}
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 6px;
}
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background-color: #c0c0c0;
border-radius: 3px;
}
</style>

View File

@ -0,0 +1,60 @@
import store from '@/store'
function authPermission(permission) {
const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions
if (permission && permission.length > 0) {
return permissions.some(v => {
return all_permission === v || v === permission
})
} else {
return false
}
}
function authRole(role) {
const super_admin = "admin";
const roles = store.getters && store.getters.roles
if (role && role.length > 0) {
return roles.some(v => {
return super_admin === v || v === role
})
} else {
return false
}
}
export default {
// 验证用户是否具备某权限
hasPermi(permission) {
return authPermission(permission);
},
// 验证用户是否含有指定权限,只需包含其中一个
hasPermiOr(permissions) {
return permissions.some(item => {
return authPermission(item)
})
},
// 验证用户是否含有指定权限,必须全部拥有
hasPermiAnd(permissions) {
return permissions.every(item => {
return authPermission(item)
})
},
// 验证用户是否具备某角色
hasRole(role) {
return authRole(role);
},
// 验证用户是否含有指定角色,只需包含其中一个
hasRoleOr(roles) {
return roles.some(item => {
return authRole(item)
})
},
// 验证用户是否含有指定角色,必须全部拥有
hasRoleAnd(roles) {
return roles.every(item => {
return authRole(item)
})
}
}

29
src/utils/auth.js 100644
View File

@ -0,0 +1,29 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
const ExpiresInKey = 'Admin-Expires-In'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
export function getExpiresIn() {
return Cookies.get(ExpiresInKey) || -1
}
export function setExpiresIn(time) {
return Cookies.set(ExpiresInKey, time)
}
export function removeExpiresIn() {
return Cookies.remove(ExpiresInKey)
}

View File

@ -0,0 +1,103 @@
<template>
<div :class="className" :style="{height:height,width:width}"/>
</template>
<script>
import * as echarts from 'echarts'
import resize from './mixins/resize'
require('echarts/theme/macarons') // echarts theme
const animationDuration = 6000
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
}
},
data() {
return {
chart: null
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.chart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: { //
type: 'shadow' // 线'line' | 'shadow'
}
},
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '3%',
containLabel: true
},
xAxis: [{
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisTick: {
alignWithLabel: true
}
}],
yAxis: [{
type: 'value',
axisTick: {
show: false
}
}],
series: [{
name: 'pageA',
type: 'bar',
stack: 'vistors',
barWidth: '60%',
data: [79, 52, 200, 334, 390, 330, 220],
animationDuration
}, {
name: 'pageB',
type: 'bar',
stack: 'vistors',
barWidth: '60%',
data: [80, 52, 200, 334, 390, 330, 220],
animationDuration
}, {
name: 'pageC',
type: 'bar',
stack: 'vistors',
barWidth: '60%',
data: [30, 52, 200, 334, 390, 330, 220],
animationDuration
}]
})
}
}
}
</script>

View File

@ -0,0 +1,205 @@
<template>
<div class="app-container">
<el-form v-show="showSearch" ref="queryForm" :inline="true" :model="queryParams" size="small">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
clearable
placeholder="请输入用户名称"
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
clearable
placeholder="请输入手机号码"
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-search" size="mini" type="primary" @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
v-hasPermi="['system:role:add']"
icon="el-icon-plus"
plain
size="mini"
type="primary"
@click="openSelectUser"
>添加用户
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['system:role:remove']"
:disabled="multiple"
icon="el-icon-circle-close"
plain
size="mini"
type="danger"
@click="cancelAuthUserAll"
>批量取消授权
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
icon="el-icon-close"
plain
size="mini"
type="warning"
@click="handleClose"
>关闭
</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column align="center" type="selection" width="55"/>
<el-table-column :show-overflow-tooltip="true" label="用户名称" prop="userName"/>
<el-table-column :show-overflow-tooltip="true" label="用户昵称" prop="nickName"/>
<el-table-column :show-overflow-tooltip="true" label="邮箱" prop="email"/>
<el-table-column :show-overflow-tooltip="true" label="手机" prop="phonenumber"/>
<el-table-column align="center" label="状态" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column align="center" label="创建时间" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column align="center" class-name="small-padding fixed-width" label="操作">
<template slot-scope="scope">
<el-button
v-hasPermi="['system:role:remove']"
icon="el-icon-circle-close"
size="mini"
type="text"
@click="cancelAuthUser(scope.row)"
>取消授权
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:limit.sync="queryParams.pageSize"
:page.sync="queryParams.pageNum"
:total="total"
@pagination="getList"
/>
<select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery"/>
</div>
</template>
<script>
import {allocatedUserList, authUserCancel, authUserCancelAll} from "@/api/system/role";
import selectUser from "./selectUser";
export default {
name: "AuthUser",
dicts: ['sys_normal_disable'],
components: {selectUser},
data() {
return {
//
loading: true,
//
userIds: [],
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
userList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
roleId: undefined,
userName: undefined,
phonenumber: undefined
}
};
},
created() {
const roleId = this.$route.params && this.$route.params.roleId;
if (roleId) {
this.queryParams.roleId = roleId;
this.getList();
}
},
methods: {
/** 查询授权用户列表 */
getList() {
this.loading = true;
allocatedUserList(this.queryParams).then(response => {
this.userList = response.data.rows;
this.total = response.data.total;
this.loading = false;
}
);
},
//
handleClose() {
const obj = {path: "/system/role"};
this.$tab.closeOpenPage(obj);
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.userIds = selection.map(item => item.userId)
this.multiple = !selection.length
},
/** 打开授权用户表弹窗 */
openSelectUser() {
this.$refs.select.show();
},
/** 取消授权按钮操作 */
cancelAuthUser(row) {
const roleId = this.queryParams.roleId;
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function () {
return authUserCancel({userId: row.userId, roleId: roleId});
}).then(() => {
this.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {
});
},
/** 批量取消授权按钮操作 */
cancelAuthUserAll(row) {
const roleId = this.queryParams.roleId;
const userIds = this.userIds.join(",");
this.$modal.confirm('是否取消选中用户授权数据项?').then(function () {
return authUserCancelAll({roleId: roleId, userIds: userIds});
}).then(() => {
this.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {
});
}
}
};
</script>

View File

@ -0,0 +1,118 @@
<template>
<div class="app-container">
<h4 class="form-header h4">基本信息</h4>
<el-form ref="form" :model="form" label-width="80px">
<el-row>
<el-col :offset="2" :span="8">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" disabled/>
</el-form-item>
</el-col>
<el-col :offset="2" :span="8">
<el-form-item label="登录账号" prop="userName">
<el-input v-model="form.userName" disabled/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<h4 class="form-header h4">角色信息</h4>
<el-table ref="table" v-loading="loading" :data="roles.slice((pageNum-1)*pageSize,pageNum*pageSize)" :row-key="getRowKey"
@row-click="clickRow" @selection-change="handleSelectionChange">
<el-table-column align="center" label="序号" type="index">
<template slot-scope="scope">
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column :reserve-selection="true" type="selection" width="55"></el-table-column>
<el-table-column align="center" label="角色编号" prop="roleId"/>
<el-table-column align="center" label="角色名称" prop="roleName"/>
<el-table-column align="center" label="权限字符" prop="roleKey"/>
<el-table-column align="center" label="创建时间" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :limit.sync="pageSize" :page.sync="pageNum" :total="total"/>
<el-form label-width="100px">
<el-form-item style="text-align: center;margin-left:-120px;margin-top:30px;">
<el-button type="primary" @click="submitForm()"></el-button>
<el-button @click="close()"></el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {getAuthRole, updateAuthRole} from "@/api/system/user";
export default {
name: "AuthRole",
data() {
return {
//
loading: true,
//
total: 0,
pageNum: 1,
pageSize: 10,
//
roleIds: [],
//
roles: [],
//
form: {}
};
},
created() {
const userId = this.$route.params && this.$route.params.userId;
if (userId) {
this.loading = true;
getAuthRole(userId).then((response) => {
this.form = response.data.user;
this.roles = response.data.roles;
this.total = this.roles.length;
this.$nextTick(() => {
this.roles.forEach((row) => {
if (row.flag) {
this.$refs.table.toggleRowSelection(row);
}
});
});
this.loading = false;
});
}
},
methods: {
/** 单击选中行数据 */
clickRow(row) {
this.$refs.table.toggleRowSelection(row);
},
//
handleSelectionChange(selection) {
this.roleIds = selection.map((item) => item.roleId);
},
//
getRowKey(row) {
return row.roleId;
},
/** 提交按钮 */
submitForm() {
const userId = this.form.userId;
const roleIds = this.roleIds.join(",");
updateAuthRole({userId: userId, roleIds: roleIds}).then((response) => {
this.$modal.msgSuccess("授权成功");
this.close();
});
},
/** 关闭按钮 */
close() {
const obj = {path: "/system/user"};
this.$tab.closeOpenPage(obj);
},
},
};
</script>