提交 afa6208a authored 作者: 龙菲's avatar 龙菲

修改用户赋予角色时父子节点不关联

上级 1ac6aa12
......@@ -2,29 +2,13 @@
<span>
<span v-for="(op, index) in operations" :key="index">
<span v-if="op.type == 'delete'">
<el-popconfirm
:title="deleteTitle ? deleteTitle : '确定删除吗?'"
@onConfirm="clickOperation(op)"
>
<el-button
type="danger"
size="mini"
slot="reference"
:icon="icons[op.type]"
style="margin-right: 4px"
>
{{ op.title }}</el-button
>
<el-popconfirm :title="deleteTitle ? deleteTitle : '确定删除吗?'" @onConfirm="clickOperation(op)">
<el-button type="danger" size="mini" slot="reference" :icon="icons[op.type]" style="margin-right: 4px">
{{ op.title }}</el-button>
</el-popconfirm>
</span>
<el-button
size="mini"
:icon="icons[op.type]"
@click="clickOperation(op)"
type="primary"
style="margin-right: 4px"
v-else
>{{ op.title }}
<el-button size="mini" :icon="icons[op.type]" @click="clickOperation(op)" type="primary" style="margin-right: 4px"
v-else>{{ op.title }}
</el-button>
</span>
</span>
......@@ -53,6 +37,8 @@ export default {
download: "el-icon-download",
dataPermission: "el-icon-key",
editRole: "el-icon-user",
editPassword: 'el-icon-lock',
approval: 'el-icon-s-check',
},
};
},
......
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1669797548250" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1955" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M791.04 522.24c0 20.48-2.048 39.936-6.144 58.88 8.704 3.072 16.896 6.656 24.576 11.264 5.12-22.528 8.704-46.08 8.704-70.656 0-131.584-83.456-243.2-199.68-286.208-0.512 9.216-2.048 17.92-5.12 26.624 103.424 40.96 177.664 141.824 177.664 260.096z m-551.424 59.392c-4.096-18.944-6.144-38.912-6.144-58.88 0-118.272 74.24-219.648 178.176-260.096-2.56-8.704-4.608-17.408-5.12-26.624-116.736 43.008-199.68 154.624-199.68 286.208 0 24.064 3.072 47.616 8.704 70.144 7.168-4.608 15.36-8.192 24.064-10.752z m272.384-285.184c36.864 0 66.56-29.696 66.56-66.56s-29.696-66.56-66.56-66.56-66.56 29.696-66.56 66.56 29.696 66.56 66.56 66.56z m0-105.984c22.016 0 39.936 17.92 39.936 39.936s-17.92 39.936-39.936 39.936-39.936-17.92-39.936-39.936 17.92-39.936 39.936-39.936z m159.232 560.64c-45.056 31.232-99.84 50.176-159.232 50.176-59.392 0-114.176-18.432-159.232-50.176-6.144 6.656-12.288 13.312-19.968 18.432 50.176 36.864 112.128 58.368 179.2 58.368s129.024-22.016 179.2-58.368c-7.68-5.12-13.824-11.776-19.968-18.432z m-398.336-135.68c-36.864 0-66.56 29.696-66.56 66.56s29.696 66.56 66.56 66.56 66.56-29.696 66.56-66.56-29.696-66.56-66.56-66.56z m0 106.496c-22.016 0-39.936-17.92-39.936-39.936s17.92-39.936 39.936-39.936 39.936 17.92 39.936 39.936-17.92 39.936-39.936 39.936z m478.208-106.496c-36.864 0-66.56 29.696-66.56 66.56s29.696 66.56 66.56 66.56 66.56-29.696 66.56-66.56-29.696-66.56-66.56-66.56z m0 106.496c-22.016 0-39.936-17.92-39.936-39.936s17.92-39.936 39.936-39.936 39.936 17.92 39.936 39.936-17.92 39.936-39.936 39.936z" p-id="1956"></path></svg>
\ No newline at end of file
<template>
<div class="navbar">
<hamburger
:is-active="sidebar.opened"
class="hamburger-container"
@toggleClick="toggleSideBar"
/>
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb class="breadcrumb-container" />
<div class="right-menu">
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img v-if="avatar" :src="avatar" class="user-avatar" />
......@@ -38,22 +35,13 @@
</el-dropdown>
</div>
<el-drawer
:title="isUserInfo ? '个人资料' : '修改密码'"
:visible.sync="showDrawer"
direction="rtl"
:before-close="handleClose"
append-to-body
v-loading="loading"
>
<div class="username-container">欢迎你,{{ userInfo.nickName || userInfo.username }}</div>
<el-drawer :title="isUserInfo ? '个人资料' : '修改密码'" :visible.sync="showDrawer" direction="rtl"
:before-close="handleClose" append-to-body v-loading="loading">
<!-- <span>{{ isUserInfo ? "个人资料" : "修改密码" }}</span> -->
<el-form
ref="userInfoForm"
v-if="isUserInfo"
:label-width="labelWidth"
:rules="userInfoRules"
:model="userInfoForm"
>
<el-form ref="userInfoForm" v-if="isUserInfo" :label-width="labelWidth" :rules="userInfoRules"
:model="userInfoForm">
<el-form-item label="用户名" prop="username">
<span v-if="!isEditingUserInfo">{{ userInfo.username }}</span>
<el-input v-else v-model="userInfoForm.username"></el-input>
......@@ -68,23 +56,12 @@
</el-form-item>
<el-form-item>
<el-button type="primary" @click.native="handleSubmitUserInfo" icon="el-icon-circle-check">{{
isEditingUserInfo ? "保存" : "修改个人信息"
isEditingUserInfo ? "保存" : "修改个人信息"
}}</el-button>
<el-button
type="primary"
@click.native="handleCancelChangeUserInfo"
v-if="isEditingUserInfo"
>取消</el-button
>
<el-button type="primary" @click.native="handleCancelChangeUserInfo" v-if="isEditingUserInfo">取消</el-button>
</el-form-item>
</el-form>
<el-form
ref="pwdForm"
:model="pwdForm"
:label-width="labelWidth"
:rules="pwdRules"
v-else
>
<el-form ref="pwdForm" :model="pwdForm" :label-width="labelWidth" :rules="pwdRules" v-else>
<el-form-item label="旧密码" prop="oldPwd">
<el-input v-model="pwdForm.oldPwd" type="password"></el-input>
</el-form-item>
......@@ -95,12 +72,8 @@
<el-input v-model="pwdForm.checkPass" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-circle-check" @click.native="handleSubmitPwd"
>保存</el-button
>
<el-button type="primary" @click.native="handleCancelChangePwd"
>取消</el-button
>
<el-button type="primary" icon="el-icon-circle-check" @click.native="handleSubmitPwd">保存</el-button>
<el-button type="primary" @click.native="handleCancelChangePwd">取消</el-button>
</el-form-item>
</el-form>
</el-drawer>
......@@ -313,6 +286,13 @@ export default {
float: left;
}
.username-container {
float: right;
line-height: 50px;
padding: 0 16px;
font-size: 14px;
}
.right-menu {
float: right;
height: 100%;
......@@ -365,6 +345,7 @@ export default {
}
}
}
::v-deep .el-drawer__body {
padding: 10px 60px 0 20px;
}
......
......@@ -58,9 +58,16 @@ router.afterEach((to, from) => {
function gotoRouter(to, next) {
getMenu() // 获取动态路由的方法
.then(res => {
const asyncRouter = addRouter(res.data.menus); // 进行递归解析
// const asyncRouter = addRouter(res.data.menus); // 进行递归解析
// return asyncRouter;
//TODO:前端暂时写死
const asyncRouter = addRouter(); // 进行递归解析
return asyncRouter;
// store.dispatch("user/setroles", res.data.permit);
return asyncRouter;
})
.then(asyncRouter => {
// 后置添加404页面,防止刷新404
......
......@@ -36,7 +36,7 @@ import Layout from '@/layout'
* 静态路由
*/
export const constantRoutes = [{
export const constantRoutes = [{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
......@@ -65,12 +65,12 @@ import Layout from '@/layout'
}]
},
// 404 page must be placed at the end !!!
// {
// path: '*',
// redirect: '/404',
// hidden: true
// }
// 404 page must be placed at the end !!!
// {
// path: '*',
// redirect: '/404',
// hidden: true
// }
]
......@@ -89,68 +89,98 @@ export const asyncRouterMap = [
},
redirect: '/culturalRelic',
children: [{
path: 'culturalRelic',
name: 'CulturalRelic',
component: () => import('@/views/culturalRelic/index'),
meta: {
title: '文物管理',
icon: 'culturalRelic'
},
},
{
path: 'display',
name: 'Display',
component: () => import('@/views/display/index'),
meta: {
title: '展览管理',
icon: 'display'
}
},
// {
// path: 'boutique',
// name: 'Boutique',
// component: () => import('@/views/boutique/index'),
// meta: {
// title: '精品展管理',
// icon: 'boutique'
// }
// },
{
path: 'museum',
name: 'Museum',
component: () => import('@/views/museum/index'),
meta: {
title: '博物馆管理',
icon: 'museum'
}
path: 'culturalRelic',
name: 'CulturalRelic',
component: () => import('@/views/culturalRelic/index'),
meta: {
title: '文物管理',
icon: 'culturalRelic'
},
{
path: 'virtual',
name: 'Virtual',
component: () => import('@/views/virtual/index'),
meta: {
title: '虚拟展厅',
icon: 'virtual'
}
},
{
path: 'literature',
name: 'Literature',
component: () => import('@/views/literature/index'),
meta: {
title: '文献管理',
icon: 'literature'
}
},
{
path: 'display',
name: 'Display',
component: () => import('@/views/display/index'),
meta: {
title: '展览管理',
icon: 'display'
}
},
// {
// path: 'boutique',
// name: 'Boutique',
// component: () => import('@/views/boutique/index'),
// meta: {
// title: '精品展管理',
// icon: 'boutique'
// }
// },
{
path: 'museum',
name: 'Museum',
component: () => import('@/views/museum/index'),
meta: {
title: '博物馆管理',
icon: 'museum'
}
},
{
path: 'virtual',
name: 'Virtual',
component: () => import('@/views/virtual/index'),
meta: {
title: '虚拟展厅',
icon: 'virtual'
}
},
{
path: 'literature',
name: 'Literature',
component: () => import('@/views/literature/index'),
meta: {
title: '文献管理',
icon: 'literature'
}
},
{
path: 'product',
name: 'Product',
component: () => import('@/views/product/index'),
meta: {
title: '文创产品管理',
icon: 'product'
}
},
{
path: 'approval',
name: 'Approval',
component: () => import('@/views/approval/culturalRelic'),
redirect: '/crApproval',
meta: {
title: '审批管理',
icon: 'product'
},
{
path: 'product',
name: 'Product',
component: () => import('@/views/product/index'),
meta: {
title: '文创产品管理',
icon: 'product'
children: [
{
path: 'crApproval',
name: 'CrApproval',
component: () => import('@/views/approval/culturalRelic.vue'),
meta: {
title: '文物',
icon: 'culturalRelic'
}
},
{
path: 'displayApproval',
name: 'DisplayApproval',
component: () => import('@/views/approval/display.vue'),
meta: {
title: '展览',
icon: 'display'
}
}
}
]
}
]
},
{
......@@ -164,32 +194,32 @@ export const asyncRouterMap = [
},
redirect: '/user',
children: [{
path: 'user',
name: 'User',
component: () => import('@/views/user/index'),
meta: {
title: '用户管理',
icon: 'user2'
}
},
{
path: 'role',
name: 'Role',
component: () => import('@/views/role/index'),
meta: {
title: '角色管理',
icon: 'role'
}
},
{
path: 'log',
name: 'Log',
component: () => import('@/views/log/index'),
meta: {
title: '日志管理',
icon: 'log'
}
},
path: 'user',
name: 'User',
component: () => import('@/views/user/index'),
meta: {
title: '用户管理',
icon: 'user2'
}
},
{
path: 'role',
name: 'Role',
component: () => import('@/views/role/index'),
meta: {
title: '角色管理',
icon: 'role'
}
},
{
path: 'log',
name: 'Log',
component: () => import('@/views/log/index'),
meta: {
title: '日志管理',
icon: 'log'
}
},
]
},
]
......
import Layout from '@/layout'
/**
* 生成路由
* @param {Array} routerlist 格式化路由
* @returns
*/
export function addRouter(routerlist) {
const router = []
try {
routerlist.forEach(e => {
if (e.path && e.menuName && e.component) {
let e_new = {
path: e.path,
name: e.menuName,
component: resolve => e.component === 'Layout' ? require([`@/layout`], resolve) : require([`@/views/${e.component}/index`], resolve)
}
if (e.children) {
const children = addRouter(e.children)
// 保存权限
e_new = { ...e_new, children: children }
}
if (e.redirect) {
e_new = { ...e_new, redirect: e.redirect }
}
// if (e.generatemenu === 0) {
// e_new = { ...e_new, hidden: true }
// }
if (e.icon !== '' && e.menuLabel !== '') {
e_new = { ...e_new, meta: { title: e.menuLabel, icon: e.icon } }
} else if (e.menuLabel !== '' && e.icon === '') {
e_new = { ...e_new, meta: { title: e.menuLabel } }
}
router.push(e_new)
// export function addRouter(routerlist) {
// const router = []
// try {
// routerlist.forEach(e => {
// if (e.path && e.menuName && e.component) {
// let e_new = {
// path: e.path,
// name: e.menuName,
// component: resolve => e.component === Layout ? require([`@/layout`], resolve) : require([`@/views/${e.component}/index`], resolve)
// }
// if (e.children) {
// const children = addRouter(e.children)
// // 保存权限
// e_new = { ...e_new, children: children }
// }
// if (e.redirect) {
// e_new = { ...e_new, redirect: e.redirect }
// }
// // if (e.generatemenu === 0) {
// // e_new = { ...e_new, hidden: true }
// // }
// if (e.icon !== '' && e.menuLabel !== '') {
// e_new = { ...e_new, meta: { title: e.menuLabel, icon: e.icon } }
// } else if (e.menuLabel !== '' && e.icon === '') {
// e_new = { ...e_new, meta: { title: e.menuLabel } }
// }
// router.push(e_new)
// }
// })
// } catch (error) {
// console.error(error)
// return []
// }
// return router
// }
/**
* 前端测试使用,暂时写死
*/
export function addRouter() {
const asyncRouterMap = [
{
path: '/business',
component: Layout,
name: 'Business',
hidden: false,
meta: {
title: '业务管理',
icon: 'yewu'
},
redirect: '/culturalRelic',
children: [{
path: 'culturalRelic',
name: 'CulturalRelic',
component: () => import('@/views/culturalRelic/index'),
meta: {
title: '文物管理',
icon: 'culturalRelic'
},
},
{
path: 'display',
name: 'Display',
component: () => import('@/views/display/index'),
meta: {
title: '展览管理',
icon: 'display'
}
},
// {
// path: 'boutique',
// name: 'Boutique',
// component: () => import('@/views/boutique/index'),
// meta: {
// title: '精品展管理',
// icon: 'boutique'
// }
// },
{
path: 'museum',
name: 'Museum',
component: () => import('@/views/museum/index'),
meta: {
title: '博物馆管理',
icon: 'museum'
}
},
{
path: 'virtual',
name: 'Virtual',
component: () => import('@/views/virtual/index'),
meta: {
title: '虚拟展厅',
icon: 'virtual'
}
},
{
path: 'literature',
name: 'Literature',
component: () => import('@/views/literature/index'),
meta: {
title: '文献管理',
icon: 'literature'
}
},
{
path: 'product',
name: 'Product',
component: () => import('@/views/product/index'),
meta: {
title: '文创产品管理',
icon: 'product'
}
},
{
path: 'approval',
name: 'Approval',
component: () => import('@/views/approval/index'),
redirect: '/crApproval',
meta: {
title: '审批管理',
icon: 'approval'
},
children: [
{
path: 'crApproval',
name: 'CrApproval',
component: () => import('@/views/approval/culturalRelic.vue'),
meta: {
title: '文物',
icon: 'culturalRelic'
}
},
{
path: 'displayApproval',
name: 'DisplayApproval',
component: () => import('@/views/approval/display.vue'),
meta: {
title: '展览',
icon: 'display'
}
}
]
}
]
},
{
path: '/system',
component: Layout,
name: 'System',
hidden: false,
meta: {
title: '系统管理',
icon: 'xitong'
},
redirect: '/user',
children: [{
path: 'user',
name: 'User',
component: () => import('@/views/user/index'),
meta: {
title: '用户管理',
icon: 'user2'
}
},
{
path: 'role',
name: 'Role',
component: () => import('@/views/role/index'),
meta: {
title: '角色管理',
icon: 'role'
}
},
{
path: 'log',
name: 'Log',
component: () => import('@/views/log/index'),
meta: {
title: '日志管理',
icon: 'log'
}
},
]
},
]
})
} catch (error) {
console.error(error)
return []
}
return router
return asyncRouterMap
}
\ No newline at end of file
export const title = [{
prop: "title",
label: "标题",
columnAlign: 'center',
width: 120,
showOverFlowToolTip: true,
},
{
prop: "keyword",
label: "关键词",
columnAlign: 'center',
showOverFlowToolTip: true,
},
{
prop: "type",
label: "展览类型",
columnAlign: 'center',
isDisplayType: true,
showOverFlowToolTip: true,
},
{
prop: "faceImageUrl",
label: "封面",
columnAlign: 'center',
isFaceImage: true,
width: 130
},
{
prop: "remark",
label: "备注",
columnAlign: 'center', showOverFlowToolTip: true,
},
{
prop: "status",
label: "状态",
columnAlign: 'center',
isStatus: true
},
]
export const operates = {
operate: true,
label: "操作",
width: "260px",
minwidth: "220px",
titleAlign: "center",
columnAlign: "center",
}
export const operations = [{
type: 'approval',
title: '审批'
}
]
<template>
<div class="app-container">
<div class="top-bar">
<SearchBar :config="searchConfig" @search="search" @reset="reset" />
<!-- <el-button
type="primary"
@click.native="handleOperation({ type: 'add' })"
icon="el-icon-plus"
>
发布</el-button
>
</div> -->
<!-- <el-button type="primary" @click.native="handleCopy">复制</el-button> -->
</div>
<TablePage
:data="list.records"
:tableTitle="tableTitle"
:operates="tableOperates"
>
<template v-slot:status="data">
<el-popconfirm
:title="getStatusTitle(data.scope.status)"
@onConfirm="handleChangeStatus(data.scope)"
>
<el-switch
slot="reference"
:value="Boolean(Number(data.scope.status))"
></el-switch>
</el-popconfirm>
</template>
<template v-slot:displayType="data">
{{ dicts.displayType[data.scope.type] }}
</template>
<template v-slot:faceImageUrl="data">
<img
:src="
$getFullUrl(data.scope.faceImagePressUrl || data.scope.faceImageUrl)
"
alt="暂无图片"
v-if="
$getFullUrl(data.scope.faceImagePressUrl || data.scope.faceImageUrl)
"
style="cursor: pointer"
width="100px"
@click="handelPreviewImages(data.scope.faceImageUrl)"
/>
</template>
<template v-slot:operates="scope">
<TableOperation
:operations="tableOperations"
:rawData="scope.scope.row"
@handleOperation="handleOperation"
></TableOperation>
</template>
</TablePage>
<el-pagination
style="margin: 16px 0"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="Number(list.current)"
:page-sizes="[10, 20, 50, 100]"
:page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper"
:total="Number(list.total)"
class="pagination"
>
</el-pagination>
<InfoEditDialog
:visible="editDialogVisible"
:form="form"
:currentPageIds="currentPageIds"
@handleClose="handleClose"
@refresh="loadData"
@changeDisplay="reloadDisplay"
ref="InfoEditDialog"
/>
<PreviewDialog
v-if="Object.keys(curPreviewObj).length > 0"
:visible="previewDialogVisible"
:displayDetail="curPreviewObj"
@handleClose="handleClosePreviewDialog"
/>
<!-- <CopyDialog
:visible="copyDialogVisible"
@handleClose="handleCloseCopyDialog"
@handleCopySelect="handleCopySelect"
:list="list"
/> -->
<el-image-viewer
v-if="imgViewerVisible"
:on-close="closeImgViewer"
:url-list="imgList"
/>
</div>
</template>
<script>
import TablePage from "@/components/Table/TablePage.vue";
import TableOperation from "@/components/Table/TableOperation.vue";
import { title, operates, operations } from "./config";
import {
getListPer,
deleteDisplay,
getDisplayById,
editDisplay,
} from "@/api/display";
// import CopyDialog from "./components/CopyDialog";
import SearchBar from "@/components/SearchBar";
import { mapGetters } from "vuex";
import { getToken } from "@/utils/auth";
import { importZip } from "@/utils/file";
export default {
components: {
TablePage,
TableOperation,
SearchBar,
"el-image-viewer": () =>
import("element-ui/packages/image/src/image-viewer"),
},
data() {
let that = this;
return {
list: {
record: [],
size: 10,
current: 1,
total: 0,
},
searchForm: {
name: "",
status: "",
},
searchConfig: [
{
prop: "title",
type: "input",
label: "展览名称",
},
{
prop: "status",
type: "select",
label: "状态",
selectOptions: [
{
label: "已上线",
value: "1",
},
{
label: "已下线",
value: "0",
},
],
},
],
editDialogVisible: false,
isAdd: true,
form: {
title: "", //标题
type: "", // 类别(待定)--枚举值(社会、生活等)
displayCharacter: "1", //展览性质(精品展2、布展1、文物展3)--此处填写布展类别
keyword: "", // 关键词
deptId: "", //展览单位id--暂填入用户自己的单位
regionCode: "", // 所在地域--暂填入用户自己的地区
intro: "", //展览介绍,
themeType: "1", //模板主题--前端枚举
literature: "", //关联文献。id1,id2,id3--接口查询
remark: "", //备注
status: 1, //上下架状态(0-下架,1-上架)
faceImage: "", // 封面(图片1张)
images: "", //展览图片
videos: "", //展览视频
audios: "", //展览音频
exhibitionUnits: [], //布展单元
},
loading: false,
imgViewerVisible: false,
previewDialogVisible: false,
copyDialogVisible: false,
previewVideos: [],
displayTypes: {},
curPreviewObj: {}, //当前预览的对象
currentPageIds: [], //当前的id数组,用于给详情页切换用
importZipUrl: process.env.VUE_APP_BASE_API + "/bizImport/importZip",
headers: {
authorization: getToken(),
},
multiUploadVisible: false, //控制批量上传弹窗显示
importRecordVisible: false, //上传记录
filesList: [], //上传当中的文件队列
uploadCount: 0, //处于上传中的文件数量,当等于fileList的时候就关闭弹窗,请求完毕一个就++
cancelUploadArr: [], //保存每个文件上传接口对应的取消请求的函数[fn,fn,fn...]
isUpLoading: false,
};
},
computed: {
...mapGetters(["dicts"]),
tableTitle() {
return title;
},
tableOperates() {
return operates;
},
tableOperations() {
return operations;
},
getStatusTitle(status) {
return (status) => {
if (Number(status)) {
return "是否确定要下架?";
} else {
return "是否确定要上架?";
}
};
},
},
async created() {
await this.$store.dispatch("dict/getDictList", ["displayType"]);
this.loadData();
},
//watch部分
watch: {
//监听弹窗变化
multiUploadVisible(val) {
//弹窗关闭记得清空,开启执行批量上传
if (val) {
for (let i = 0; i < this.filesList.length; i++) {
this.uploadSelf(this.filesList[i].file, i); //弹窗显示的时候,就根据文件队列的数量调用上传接口
}
} else {
//弹窗关闭,还原数据到初始位置
this.filesList = [];
this.uploadCount = 0;
this.cancelUploadArr = [];
}
},
},
methods: {
async search(form) {
var params = {
page: 1,
limit: this.list.size,
...form,
};
if (params.status == "") {
delete params.status;
}
let res = await getListPer(params);
if (res.code == 0) {
this.list = res.data;
this.currentPageIds = this.list.records.map((item) => {
return item.exhibitionId;
});
}
},
reset() {
this.loadData();
},
// 加载表格数据
async loadData() {
var params = {
page: this.list.current,
limit: this.list.size,
};
let res = await getListPer(params);
if (res.code == 0) {
this.list = res.data;
this.currentPageIds = this.list.records.map((item) => {
return item.exhibitionId;
});
}
},
async handleOperation(value, row) {
switch (value.type) {
case "add":
this.editDialogVisible = true;
case "view":
if (row) {
this.previewDialogVisible = true;
let res = await getDisplayById({ exhibitionId: row.exhibitionId });
this.curPreviewObj = res.data;
}
break;
case "edit":
let editRes = await getDisplayById({
exhibitionId: row.exhibitionId,
});
this.form = editRes.data;
this.editDialogVisible = true;
break;
case "delete":
let deleteRes = await deleteDisplay([row.exhibitionId]);
if (deleteRes.code === 0) {
this.loadData();
this.$message.success("删除成功!");
}
break;
case "multiAdd":
// debugger
// this.multiUploadVisible = true;
// console.log("this.multiUploadVisible", this.multiUploadVisible);
break;
case "downloadTemplate":
this.handleDownloadTemplate();
break;
case "viewImportRecord":
this.importRecordVisible = true;
break;
}
},
//下载批量导入模板
handleDownloadTemplate() {
let a = document.createElement("a");
a.href = "./static/展览导入模板.zip";
a.download = "展览整量导入模板.zip";
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.remove();
},
uploadSelf(file, index) {
let formData = new FormData();
formData.append("type", "biz_exhibition");
formData.append("zipFile", file);
importZip(
formData,
(progressEvent) => this.uploadUnderWayCallback(progressEvent, index),
(c) => this.cancelCallBack(c, index)
).then((res) => {
if (res.data.code == 0) {
this.$set(this.filesList[index], "status", "success");
this.$set(this.filesList[index], "desc", "上传成功");
this.$message.success("文件" + file.name + "上传成功!");
this.loadData()
} else {
this.$set(this.filesList[index], "status", "warning");
this.$set(this.filesList[index], "desc", "上传失败" + res.data.msg);
this.$message.error("上传失败:" + res.data.msg);
this.loadData();
}
});
},
// 文件上传进度回调
uploadUnderWayCallback(progressEvent, index) {
let completeVal =
(progressEvent.loaded / progressEvent.total) * 100 - 1 || 0; //处理成组件库进度组件需要的格式
this.$set(this.filesList[index], "percent", Math.floor(completeVal)); //直接改变数组某一项不是响应式的,因此我们需要用到这个api,将其响应式化,添加到数组中
},
// 文件取消回调
cancelCallBack(c, index) {
this.$set(this.cancelUploadArr, index, c); //添加取消队列中,关闭弹窗批量取消
this.uploadCount = 0;
},
handleMultiUploadClose() {
// 文件列表中如果Status为null,则代表有仍在上传中
let isUpLoading = false;
this.filesList.map((item) => {
if (item.status == null) {
isUpLoading = true;
return;
}
});
let title = isUpLoading ? "当前有上传任务,是否取消上传" : "确认关闭?";
let confirmButtonText = isUpLoading ? "关闭并取消上传" : "确定";
let cancelButtonText = isUpLoading ? "否" : "取消";
let that = this;
this.$confirm(title, "提示", {
confirmButtonText,
cancelButtonText,
type: "warning",
})
.then(() => {
// 点击取消上传
if (that.isUpLoading) {
this.handleCancelAllUpLoad();
this.$message.warning("已取消上传!");
}
this.multiUploadVisible = false; //最后关闭
})
.catch(() => {
console.log("用户取消操作");
});
},
handleMultiUploadCancel(index) {
if (this.cancelUploadArr[index]) {
this.cancelUploadArr[index](); //取消上传
this.cancelUploadArr.splice(index, 1); //从取消队列中删除
}
if (this.filesList[index]) {
this.filesList.splice(index, 1);
}
this.$message.info("已取消上传!");
},
handleCancelAllUpLoad() {
this.cancelUploadArr.forEach((cancelCallBack) => cancelCallBack()); //批量取消上传
},
handleSuccess(res) {
res.Success && this.$Message.success("上传成功"); //提示
// this.processModal = false; //成功后关闭弹窗
this.filesList = [];
},
async reloadDisplay(exhibitionId) {
this.$refs.InfoEditDialog.submitLoading = true;
this.$refs.InfoEditDialog.loadingText = "加载中...";
let editRes = await getDisplayById({
exhibitionId,
});
this.form = editRes.data;
this.$refs.InfoEditDialog.submitLoading = false;
},
async handleChangeStatus(row) {
const { status } = row;
let newStatus = status === "0" ? "1" : "0";
const params = {
...row,
status: newStatus,
};
let res = await editDisplay(params);
if (res.code == 0) {
this.loadData();
this.$message.success("修改成功!");
}
},
// 多选
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 改变页容量
handleSizeChange(value) {
this.list.size = value;
this.loadData();
},
// 改变当前显示页
handleCurrentChange(value) {
this.list.current = value;
this.loadData();
},
// 搜索
onSubmitSearch() {
console.log("submit!");
},
// 关闭Dialog
handleClose() {
this.editDialogVisible = false;
this.form = {
status: 1,
faceImage: "", // 封面(图片1张)
images: "", //展览图片
videos: "", //展览视频
audios: "", //展览音频
exhibitionUnits: [], //布展单元
};
},
// 关闭预览图片
closeImgViewer() {
this.imgViewerVisible = false;
},
// 预览图片
handelPreviewImages(images) {
this.imgViewerVisible = true;
this.imgList = [images];
},
handleClosePreviewDialog() {
this.previewDialogVisible = false;
},
handleCopy() {
this.copyDialogVisible = true;
},
handleCloseCopyDialog() {
this.copyDialogVisible = false;
},
async handleCopySelect(value) {
const { exhibitionId } = value;
let res = await getDisplayById({ exhibitionId });
delete res.data.exhibitionId;
this.form = { ...res.data };
this.editDialogVisible = true;
console.log("this.form", this.form);
},
// // 文件个数超出
// handleExceed() {
// this.$message.error(`超出上传文件个数,请删除以后再上传!`);
// },
handleUpload(file) {
this.multiUploadVisible = true; //显示弹窗
this.filesList.push({
file,
name: file.name,
size: file.size,
status: null,
desc: null,
});
return false; //阻止自动上传
},
handleSuccess(res) {
res.Success && this.$Message.success("上传成功"); //提示
// this.processModal = false; //成功后关闭弹窗
this.filesList = [];
},
handleImportRecordClose() {
this.importRecordVisible = false;
},
handleMultiUploadClose() {
// 文件列表中如果Status为null,则代表有仍在上传中
let isUpLoading = false;
this.filesList.map((item) => {
if (item.status == null) {
isUpLoading = true;
return;
}
});
let title = isUpLoading ? "当前有上传任务,是否取消上传" : "确认关闭?";
let confirmButtonText = isUpLoading ? "关闭并取消上传" : "确定";
let cancelButtonText = isUpLoading ? "否" : "取消";
let that = this;
this.$confirm(title, "提示", {
confirmButtonText,
cancelButtonText,
type: "warning",
})
.then(() => {
// 点击取消上传
if (that.isUpLoading) {
this.handleCancelAllUpLoad();
this.$message.warning("已取消上传!");
}
this.multiUploadVisible = false; //最后关闭
})
.catch(() => {
console.log("用户取消操作");
});
},
handleMultiUploadCancel(index) {
if (this.cancelUploadArr[index]) {
this.cancelUploadArr[index](); //取消上传
this.cancelUploadArr.splice(index, 1); //从取消队列中删除
}
if (this.filesList[index]) {
this.filesList.splice(index, 1);
}
this.$message.info("已取消上传!");
},
handleCancelAllUpLoad() {
this.cancelUploadArr.forEach((cancelCallBack) => cancelCallBack()); //批量取消上传
},
},
};
</script>
<style lang="scss" scoped>
.top-bar {
display: flex;
justify-content: space-between;
flex-direction: column;
height: 68px;
}
.tools {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
.tools-item {
display: flex;
&:last-child {
justify-content: flex-end;
}
}
.upload-button {
margin: 0 10px;
}
}
</style>
\ No newline at end of file
<template>
<div class="app-container">
<div class="top-bar">
<SearchBar :config="searchConfig" @search="search" @reset="reset" />
<!-- <el-button
type="primary"
@click.native="handleOperation({ type: 'add' })"
icon="el-icon-plus"
>
发布</el-button
>
</div> -->
<!-- <el-button type="primary" @click.native="handleCopy">复制</el-button> -->
</div>
<TablePage
:data="list.records"
:tableTitle="tableTitle"
:operates="tableOperates"
>
<template v-slot:status="data">
<el-popconfirm
:title="getStatusTitle(data.scope.status)"
@onConfirm="handleChangeStatus(data.scope)"
>
<el-switch
slot="reference"
:value="Boolean(Number(data.scope.status))"
></el-switch>
</el-popconfirm>
</template>
<template v-slot:displayType="data">
{{ dicts.displayType[data.scope.type] }}
</template>
<template v-slot:faceImageUrl="data">
<img
:src="
$getFullUrl(data.scope.faceImagePressUrl || data.scope.faceImageUrl)
"
alt="暂无图片"
v-if="
$getFullUrl(data.scope.faceImagePressUrl || data.scope.faceImageUrl)
"
style="cursor: pointer"
width="100px"
@click="handelPreviewImages(data.scope.faceImageUrl)"
/>
</template>
<template v-slot:operates="scope">
<TableOperation
:operations="tableOperations"
:rawData="scope.scope.row"
@handleOperation="handleOperation"
></TableOperation>
</template>
</TablePage>
<el-pagination
style="margin: 16px 0"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="Number(list.current)"
:page-sizes="[10, 20, 50, 100]"
:page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper"
:total="Number(list.total)"
class="pagination"
>
</el-pagination>
<InfoEditDialog
:visible="editDialogVisible"
:form="form"
:currentPageIds="currentPageIds"
@handleClose="handleClose"
@refresh="loadData"
@changeDisplay="reloadDisplay"
ref="InfoEditDialog"
/>
<PreviewDialog
v-if="Object.keys(curPreviewObj).length > 0"
:visible="previewDialogVisible"
:displayDetail="curPreviewObj"
@handleClose="handleClosePreviewDialog"
/>
<!-- <CopyDialog
:visible="copyDialogVisible"
@handleClose="handleCloseCopyDialog"
@handleCopySelect="handleCopySelect"
:list="list"
/> -->
<el-image-viewer
v-if="imgViewerVisible"
:on-close="closeImgViewer"
:url-list="imgList"
/>
</div>
</template>
<script>
import TablePage from "@/components/Table/TablePage.vue";
import TableOperation from "@/components/Table/TableOperation.vue";
import { title, operates, operations } from "./config";
import {
getListPer,
deleteDisplay,
getDisplayById,
editDisplay,
} from "@/api/display";
// import CopyDialog from "./components/CopyDialog";
import SearchBar from "@/components/SearchBar";
import { mapGetters } from "vuex";
import { getToken } from "@/utils/auth";
import { importZip } from "@/utils/file";
export default {
components: {
TablePage,
TableOperation,
SearchBar,
"el-image-viewer": () =>
import("element-ui/packages/image/src/image-viewer"),
},
data() {
let that = this;
return {
list: {
record: [],
size: 10,
current: 1,
total: 0,
},
searchForm: {
name: "",
status: "",
},
searchConfig: [
{
prop: "title",
type: "input",
label: "展览名称",
},
{
prop: "status",
type: "select",
label: "状态",
selectOptions: [
{
label: "已上线",
value: "1",
},
{
label: "已下线",
value: "0",
},
],
},
],
editDialogVisible: false,
isAdd: true,
form: {
title: "", //标题
type: "", // 类别(待定)--枚举值(社会、生活等)
displayCharacter: "1", //展览性质(精品展2、布展1、文物展3)--此处填写布展类别
keyword: "", // 关键词
deptId: "", //展览单位id--暂填入用户自己的单位
regionCode: "", // 所在地域--暂填入用户自己的地区
intro: "", //展览介绍,
themeType: "1", //模板主题--前端枚举
literature: "", //关联文献。id1,id2,id3--接口查询
remark: "", //备注
status: 1, //上下架状态(0-下架,1-上架)
faceImage: "", // 封面(图片1张)
images: "", //展览图片
videos: "", //展览视频
audios: "", //展览音频
exhibitionUnits: [], //布展单元
},
loading: false,
imgViewerVisible: false,
previewDialogVisible: false,
copyDialogVisible: false,
previewVideos: [],
displayTypes: {},
curPreviewObj: {}, //当前预览的对象
currentPageIds: [], //当前的id数组,用于给详情页切换用
importZipUrl: process.env.VUE_APP_BASE_API + "/bizImport/importZip",
headers: {
authorization: getToken(),
},
multiUploadVisible: false, //控制批量上传弹窗显示
importRecordVisible: false, //上传记录
filesList: [], //上传当中的文件队列
uploadCount: 0, //处于上传中的文件数量,当等于fileList的时候就关闭弹窗,请求完毕一个就++
cancelUploadArr: [], //保存每个文件上传接口对应的取消请求的函数[fn,fn,fn...]
isUpLoading: false,
};
},
computed: {
...mapGetters(["dicts"]),
tableTitle() {
return title;
},
tableOperates() {
return operates;
},
tableOperations() {
return operations;
},
getStatusTitle(status) {
return (status) => {
if (Number(status)) {
return "是否确定要下架?";
} else {
return "是否确定要上架?";
}
};
},
},
async created() {
await this.$store.dispatch("dict/getDictList", ["displayType"]);
this.loadData();
},
//watch部分
watch: {
//监听弹窗变化
multiUploadVisible(val) {
//弹窗关闭记得清空,开启执行批量上传
if (val) {
for (let i = 0; i < this.filesList.length; i++) {
this.uploadSelf(this.filesList[i].file, i); //弹窗显示的时候,就根据文件队列的数量调用上传接口
}
} else {
//弹窗关闭,还原数据到初始位置
this.filesList = [];
this.uploadCount = 0;
this.cancelUploadArr = [];
}
},
},
methods: {
async search(form) {
var params = {
page: 1,
limit: this.list.size,
...form,
};
if (params.status == "") {
delete params.status;
}
let res = await getListPer(params);
if (res.code == 0) {
this.list = res.data;
this.currentPageIds = this.list.records.map((item) => {
return item.exhibitionId;
});
}
},
reset() {
this.loadData();
},
// 加载表格数据
async loadData() {
var params = {
page: this.list.current,
limit: this.list.size,
};
let res = await getListPer(params);
if (res.code == 0) {
this.list = res.data;
this.currentPageIds = this.list.records.map((item) => {
return item.exhibitionId;
});
}
},
async handleOperation(value, row) {
switch (value.type) {
case "add":
this.editDialogVisible = true;
case "view":
if (row) {
this.previewDialogVisible = true;
let res = await getDisplayById({ exhibitionId: row.exhibitionId });
this.curPreviewObj = res.data;
}
break;
case "edit":
let editRes = await getDisplayById({
exhibitionId: row.exhibitionId,
});
this.form = editRes.data;
this.editDialogVisible = true;
break;
case "delete":
let deleteRes = await deleteDisplay([row.exhibitionId]);
if (deleteRes.code === 0) {
this.loadData();
this.$message.success("删除成功!");
}
break;
case "multiAdd":
// debugger
// this.multiUploadVisible = true;
// console.log("this.multiUploadVisible", this.multiUploadVisible);
break;
case "downloadTemplate":
this.handleDownloadTemplate();
break;
case "viewImportRecord":
this.importRecordVisible = true;
break;
}
},
//下载批量导入模板
handleDownloadTemplate() {
let a = document.createElement("a");
a.href = "./static/展览导入模板.zip";
a.download = "展览整量导入模板.zip";
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.remove();
},
uploadSelf(file, index) {
let formData = new FormData();
formData.append("type", "biz_exhibition");
formData.append("zipFile", file);
importZip(
formData,
(progressEvent) => this.uploadUnderWayCallback(progressEvent, index),
(c) => this.cancelCallBack(c, index)
).then((res) => {
if (res.data.code == 0) {
this.$set(this.filesList[index], "status", "success");
this.$set(this.filesList[index], "desc", "上传成功");
this.$message.success("文件" + file.name + "上传成功!");
this.loadData()
} else {
this.$set(this.filesList[index], "status", "warning");
this.$set(this.filesList[index], "desc", "上传失败" + res.data.msg);
this.$message.error("上传失败:" + res.data.msg);
this.loadData();
}
});
},
// 文件上传进度回调
uploadUnderWayCallback(progressEvent, index) {
let completeVal =
(progressEvent.loaded / progressEvent.total) * 100 - 1 || 0; //处理成组件库进度组件需要的格式
this.$set(this.filesList[index], "percent", Math.floor(completeVal)); //直接改变数组某一项不是响应式的,因此我们需要用到这个api,将其响应式化,添加到数组中
},
// 文件取消回调
cancelCallBack(c, index) {
this.$set(this.cancelUploadArr, index, c); //添加取消队列中,关闭弹窗批量取消
this.uploadCount = 0;
},
handleMultiUploadClose() {
// 文件列表中如果Status为null,则代表有仍在上传中
let isUpLoading = false;
this.filesList.map((item) => {
if (item.status == null) {
isUpLoading = true;
return;
}
});
let title = isUpLoading ? "当前有上传任务,是否取消上传" : "确认关闭?";
let confirmButtonText = isUpLoading ? "关闭并取消上传" : "确定";
let cancelButtonText = isUpLoading ? "否" : "取消";
let that = this;
this.$confirm(title, "提示", {
confirmButtonText,
cancelButtonText,
type: "warning",
})
.then(() => {
// 点击取消上传
if (that.isUpLoading) {
this.handleCancelAllUpLoad();
this.$message.warning("已取消上传!");
}
this.multiUploadVisible = false; //最后关闭
})
.catch(() => {
console.log("用户取消操作");
});
},
handleMultiUploadCancel(index) {
if (this.cancelUploadArr[index]) {
this.cancelUploadArr[index](); //取消上传
this.cancelUploadArr.splice(index, 1); //从取消队列中删除
}
if (this.filesList[index]) {
this.filesList.splice(index, 1);
}
this.$message.info("已取消上传!");
},
handleCancelAllUpLoad() {
this.cancelUploadArr.forEach((cancelCallBack) => cancelCallBack()); //批量取消上传
},
handleSuccess(res) {
res.Success && this.$Message.success("上传成功"); //提示
// this.processModal = false; //成功后关闭弹窗
this.filesList = [];
},
async reloadDisplay(exhibitionId) {
this.$refs.InfoEditDialog.submitLoading = true;
this.$refs.InfoEditDialog.loadingText = "加载中...";
let editRes = await getDisplayById({
exhibitionId,
});
this.form = editRes.data;
this.$refs.InfoEditDialog.submitLoading = false;
},
async handleChangeStatus(row) {
const { status } = row;
let newStatus = status === "0" ? "1" : "0";
const params = {
...row,
status: newStatus,
};
let res = await editDisplay(params);
if (res.code == 0) {
this.loadData();
this.$message.success("修改成功!");
}
},
// 多选
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 改变页容量
handleSizeChange(value) {
this.list.size = value;
this.loadData();
},
// 改变当前显示页
handleCurrentChange(value) {
this.list.current = value;
this.loadData();
},
// 搜索
onSubmitSearch() {
console.log("submit!");
},
// 关闭Dialog
handleClose() {
this.editDialogVisible = false;
this.form = {
status: 1,
faceImage: "", // 封面(图片1张)
images: "", //展览图片
videos: "", //展览视频
audios: "", //展览音频
exhibitionUnits: [], //布展单元
};
},
// 关闭预览图片
closeImgViewer() {
this.imgViewerVisible = false;
},
// 预览图片
handelPreviewImages(images) {
this.imgViewerVisible = true;
this.imgList = [images];
},
handleClosePreviewDialog() {
this.previewDialogVisible = false;
},
handleCopy() {
this.copyDialogVisible = true;
},
handleCloseCopyDialog() {
this.copyDialogVisible = false;
},
async handleCopySelect(value) {
const { exhibitionId } = value;
let res = await getDisplayById({ exhibitionId });
delete res.data.exhibitionId;
this.form = { ...res.data };
this.editDialogVisible = true;
console.log("this.form", this.form);
},
// // 文件个数超出
// handleExceed() {
// this.$message.error(`超出上传文件个数,请删除以后再上传!`);
// },
handleUpload(file) {
this.multiUploadVisible = true; //显示弹窗
this.filesList.push({
file,
name: file.name,
size: file.size,
status: null,
desc: null,
});
return false; //阻止自动上传
},
handleSuccess(res) {
res.Success && this.$Message.success("上传成功"); //提示
// this.processModal = false; //成功后关闭弹窗
this.filesList = [];
},
handleImportRecordClose() {
this.importRecordVisible = false;
},
handleMultiUploadClose() {
// 文件列表中如果Status为null,则代表有仍在上传中
let isUpLoading = false;
this.filesList.map((item) => {
if (item.status == null) {
isUpLoading = true;
return;
}
});
let title = isUpLoading ? "当前有上传任务,是否取消上传" : "确认关闭?";
let confirmButtonText = isUpLoading ? "关闭并取消上传" : "确定";
let cancelButtonText = isUpLoading ? "否" : "取消";
let that = this;
this.$confirm(title, "提示", {
confirmButtonText,
cancelButtonText,
type: "warning",
})
.then(() => {
// 点击取消上传
if (that.isUpLoading) {
this.handleCancelAllUpLoad();
this.$message.warning("已取消上传!");
}
this.multiUploadVisible = false; //最后关闭
})
.catch(() => {
console.log("用户取消操作");
});
},
handleMultiUploadCancel(index) {
if (this.cancelUploadArr[index]) {
this.cancelUploadArr[index](); //取消上传
this.cancelUploadArr.splice(index, 1); //从取消队列中删除
}
if (this.filesList[index]) {
this.filesList.splice(index, 1);
}
this.$message.info("已取消上传!");
},
handleCancelAllUpLoad() {
this.cancelUploadArr.forEach((cancelCallBack) => cancelCallBack()); //批量取消上传
},
},
};
</script>
<style lang="scss" scoped>
.top-bar {
display: flex;
justify-content: space-between;
flex-direction: column;
height: 68px;
}
.tools {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
.tools-item {
display: flex;
&:last-child {
justify-content: flex-end;
}
}
.upload-button {
margin: 0 10px;
}
}
</style>
\ No newline at end of file
......@@ -50,7 +50,7 @@
</el-form-item>
<el-form-item label="菜单权限" :label-width="formLabelWidth">
<el-tree
ref="tree"
ref="menuPermisionTree"
:data="dialogForm.permissionRespNodes"
show-checkbox
:props="props"
......@@ -189,10 +189,9 @@ export default {
handleSubmit() {
this.$refs.dialogForm.validate(async (valid) => {
if (valid) {
debugger
const { name, remark } = this.dialogForm;
let status = this.status ? 1 : 0;
let permissions = this.$refs.tree.getCheckedKeys();
let permissions = this.$refs.menuPermisionTree.getCheckedKeys();
const params = {
name,
......@@ -230,7 +229,7 @@ export default {
this.$refs.dialogForm.resetFields();
this.$emit("refresh");
this.$nextTick(() => {
this.$refs.tree.setCheckedKeys([]);
this.$refs.menuPermisionTree.setCheckedKeys([]);
});
this.allRole = [];
},
......@@ -261,7 +260,7 @@ export default {
}
setTimeout(() => {
if (checkedIds.length > 0) {
this.$refs.tree.setCheckedKeys(checkedIds);
this.$refs.menuPermisionTree.setCheckedKeys(checkedIds);
}
}, 100);
},
......
<template>
<el-dialog :visible="dialogVisible" width="30%" :before-close="handleClose" lock-scroll>
<el-form ref="pwdForm" :model="pwdForm" :label-width="labelWidth" :rules="pwdRules" class="form" size="small"
v-loading="loading">
<!-- <el-form-item label="旧密码" prop="oldPwd">
<el-input v-model="pwdForm.oldPwd" type="password"></el-input>
</el-form-item> -->
<el-form-item label="新密码" prop="password">
<el-input v-model="pwdForm.password" clearable type="text">
<el-button @click.native="handleClickReset" slot="append" icon="el-icon-refresh-left">重置为初始密码</el-button>
</el-input>
</el-form-item>
<!-- <el-form-item label="确认密码" prop="checkPass" >
<el-input v-model="pwdForm.checkPass" type="password" show-password></el-input>
</el-form-item> -->
<!-- <el-form-item>
<el-button type="primary" icon="el-icon-circle-check" @click.native="handleSubmitPwd">保存</el-button>
<el-button type="primary" @click.native="handleCancelChangePwd">取消</el-button>
</el-form-item> -->
</el-form>
<div class="buttons">
<el-button type="primary" icon="el-icon-circle-check" @click.native="handleSubmitPwd" size="small">保存
</el-button>
<el-button @click.native="handleCancelChangePwd" size="mini">取消</el-button>
</div>
</el-dialog>
</template>
<script>
import { upadateUser } from "@/api/user";
export default {
name: 'EditPassword',
props: {
visible: {
type: Boolean,
default: false,
},
id: {
type: String,
default: null,
},
},
watch: {
visible: {
handler: function (value) {
this.dialogVisible = value;
},
deep: true,
immediate: true,
},
},
data() {
var validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入新密码"));
} else {
var pattern =
/^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\W_!@#$%^&*`~()-+=]{8,30}$/;
if (!pattern.test(value)) {
callback(
new Error(
"密码长度至少8位,至少含数字,大写字母,小写字母,特殊符其中三种"
)
);
}
// if (this.pwdForm.checkPass !== "") {
// this.$refs.pwdForm.validateField("checkPass");
// }
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== this.pwdForm.newPwd) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
return {
dialogVisible: false,
labelWidth: "100px",
pwdForm: {
// oldPwd: "",
password: "",
// checkPass: "",
},
pwdRules: {
// oldPwd: [
// { trigger: "blur", required: true, message: "请输入当前密码" },
// ],
password: [{ validator: validatePass, trigger: "blur", required: true }],
// checkPass: [
// { validator: validatePass2, trigger: "blur", required: true },
// ],
},
loading: false
}
},
methods: {
handleSubmitPwd() {
this.$refs.pwdForm.validate(async (valid) => {
if (valid) {
this.loading = true
// const { newPwd, oldPwd } = this.pwdForm;
const params = {
// newPwd,
// oldPwd,
password: this.pwdForm.password,
id: this.id
};
// console.log(params);
// return
let res = await upadateUser(params);
if (res.code == "0") {
this.$message.success("修改成功!");
this.$emit("handleClose");
this.$refs.pwdForm.resetFields()
}
this.loading = false
}
this.loading = false
});
},
handleClickReset() {
this.pwdForm.password = 'qwe@1234'
},
handleCancelChangePwd() {
this.handleClose()
},
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
// done();
this.$emit("handleClose");
this.$refs.pwdForm.resetFields()
})
.catch((_) => { });
},
}
}
</script>
<style lang="scss" scoped>
.title {
display: flex;
margin-bottom: 16px;
.divider {
width: 8px;
border-left: 4px solid #409eff;
margin-right: 8px;
}
.label {
font-weight: bold;
}
}
.dialog-content {
padding: 0 32px;
// display: flex;
.basic-info {
flex: 1;
margin-right: 48px;
}
}
.dialog-footer {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
.form {
padding-right: 60px;
}
.buttons {
padding: 40px 60px 0;
display: flex;
justify-content: flex-end;
}
</style>
\ No newline at end of file
......@@ -15,12 +15,14 @@
<el-tree
:data="allRole"
show-checkbox
default-expand-all
node-key="id"
ref="myTree"
highlight-current
:props="{ label: 'name' }"
:default-checked-keys="ownRoles"
@check="roleParentTreeCheck"
check-strictly
default-expand-all
>
</el-tree>
</div>
......@@ -122,7 +124,8 @@ export default {
},
async handleSubmit() {
let ids = this.$refs.myTree.getCheckedKeys(true);
// debugger
let ids = this.$refs.myTree.getCheckedKeys();
let params = ids;
let res = await updateUserOwnRoles(this.userId, params);
......@@ -139,6 +142,7 @@ export default {
this.$emit("refresh");
this.$emit("handleClose");
},
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
......@@ -149,6 +153,12 @@ export default {
})
.catch((_) => {});
},
roleParentTreeCheck(node, list) {
if (list.checkedKeys.length > 1) {
//单选实现
this.$refs.myTree.setCheckedKeys([node.id]);
}
},
},
};
</script>
......@@ -168,7 +178,7 @@ export default {
}
.dialog-content {
padding: 0 32px;
display: flex;
// display: flex;
.basic-info {
flex: 1;
margin-right: 48px;
......
......@@ -347,10 +347,11 @@ export default {
}
.dialog-content {
padding: 0 32px;
display: flex;
// display: flex;
.basic-info {
flex: 1;
margin-right: 48px;
margin-right: 48px;
}
}
......
......@@ -44,20 +44,25 @@ export const title = [{
export const operates = {
operate: true,
label: "操作",
width: "300px",
width: "400px",
titleAlign: "center",
columnAlign: "center",
}
export const operations = [
{
type: 'editRole',
title: '赋予角色'
type:'editPassword',
title: '修改密码'
},
{
type: 'edit',
title: '编辑'
},
{
type: 'editRole',
title: '赋予角色'
},
{
type: 'delete',
title: '删除'
......
<template>
<div class="users app-container">
<el-row :gutter="16">
<el-col :span="4">
<el-tree
:data="treeData"
:props="defaultProps"
@node-click="handleNodeClick"
default-expand-all
:expand-on-click-node="false"
></el-tree>
<el-col :span="4" class="left-tree">
<el-scrollbar style="height:100%;">
<el-tree :data="treeData" :props="defaultProps" @node-click="handleNodeClick" default-expand-all
:expand-on-click-node="false"></el-tree>
</el-scrollbar>
</el-col>
<el-col :span="20">
<div class="top-bar">
<SearchBar :config="searchConfig" @search="search" @reset="reset" />
<el-button
type="primary"
@click.native="handleOperation({ type: 'add' })"
icon="el-icon-plus"
>
新增</el-button
>
<el-button type="primary" @click.native="handleOperation({ type: 'add' })" icon="el-icon-plus">
新增</el-button>
</div>
<TablePage
:data="list.records"
:tableTitle="tableTitle"
:operates="tableOperates"
>
<TablePage :data="list.records" :tableTitle="tableTitle" :operates="tableOperates">
<template v-slot:status="data">
<el-popconfirm
:title="getStatusTitle(data.scope.status)"
@onConfirm="handleChangeStatus(data.scope)"
>
<el-switch
slot="reference"
:value="Boolean(Number(data.scope.status))"
></el-switch>
<el-popconfirm :title="getStatusTitle(data.scope.status)" @onConfirm="handleChangeStatus(data.scope)">
<el-switch slot="reference" :value="Boolean(Number(data.scope.status))"></el-switch>
</el-popconfirm>
</template>
<template v-slot:operates="scope">
<TableOperation
:operations="tableOperations"
:rawData="scope.scope.row"
@handleOperation="handleOperation"
>
<TableOperation :operations="tableOperations" :rawData="scope.scope.row" @handleOperation="handleOperation">
</TableOperation>
</template>
</TablePage>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="Number(list.current)"
:page-sizes="[10, 20, 40, 50]"
:page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper"
:total="Number(list.total)"
class="pagination"
>
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="Number(list.current)" :page-sizes="[10, 20, 40, 50]" :page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper" :total="Number(list.total)" class="pagination">
</el-pagination>
</el-col>
</el-row>
<InfoEditDialog
:visible="dialogVisible"
:form="form"
:orgTreeData="treeData"
@handleClose="handleClose"
@refresh="loadListData"
/>
<EditRole
:visible="editRoleVisible"
:roleData="currentRoleData"
:id="currentId"
@handleClose="handleCloseEditRole"
/>
<InfoEditDialog :visible="dialogVisible" :form="form" :orgTreeData="treeData" @handleClose="handleClose"
@refresh="loadListData" />
<EditRole :visible="editRoleVisible" :roleData="currentRoleData" :id="currentId"
@handleClose="handleCloseEditRole" />
<EditPassword :visible="editPasswordVisible" :id="currentId" @handleClose="handleCloseEditPassword" />
</div>
</template>
......@@ -90,6 +55,7 @@ import {
} from "@/api/user";
import InfoEditDialog from "./components/InfoEditDialog.vue";
import EditRole from "./components/EditRole.vue";
import EditPassword from "./components/EditPassword.vue";
export default {
components: {
......@@ -98,6 +64,7 @@ export default {
SearchBar,
InfoEditDialog,
EditRole,
EditPassword
},
computed: {
tableTitle() {
......@@ -157,6 +124,7 @@ export default {
},
dialogVisible: false,
editRoleVisible: false,
editPasswordVisible: false,
currentRoleData: {},
currentId: null,
};
......@@ -172,7 +140,7 @@ export default {
if (res.code == 0) {
this.treeData = res.data[0].children; //去除默认顶级部门
this.currentDeptNo = this.treeData[0].deptNo;
this.loadListData();
this.loadListData();
}
},
// 加载表格数据
......@@ -244,6 +212,11 @@ export default {
this.currentRoleData = roleRes.data;
this.currentId = row.id;
break;
case 'editPassword':
console.log('editPassword');
this.editPasswordVisible = true;
this.currentId = row.id;
break;
}
},
......@@ -255,9 +228,14 @@ export default {
},
handleCloseEditRole() {
this.editRoleVisible = false;
this.currentRoleData ={};
this.currentRoleData = {};
this.currentId = null;
},
handleCloseEditPassword(){
this.editPasswordVisible = false;
this.currentId = null;
}
},
};
</script>
......@@ -277,4 +255,12 @@ export default {
.el-button {
margin-bottom: 22px;
}
.left-tree {
height: calc(100vh - 130px);
}
::v-deep .el-scrollbar .el-scrollbar__wrap {
overflow-x: hidden;
}
</style>
\ No newline at end of file
......@@ -42,17 +42,17 @@ module.exports = {
'/api': {
// target: 'http://172.24.100.109:8080/',
// target:'http://222.85.214.245:9603/api',
// target:'http://192.168.1.230:9603/api',
target: 'http://114.115.157.218:9602/api',//生产
target:'http://192.168.1.230:9603/api',
// target: 'http://114.115.157.218:9602/api',//生产
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
},
'/files': {
// target: 'http://192.168.1.230:9563/files',
target: 'http://192.168.1.230:9604/files',
// target: 'http://222.85.214.245:9604/files',
target: 'http://114.115.157.218:9602/files',//生产
// target: 'http://114.115.157.218:9602/files',//生产
changeOrigin: true,
pathRewrite: {
'^/files': ''
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论