@@ -3049,7 +3049,11 @@ | |||
"node_modules/connect/node_modules/ms": { | |||
"version": "2.0.0", | |||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | |||
<<<<<<< HEAD | |||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", | |||
======= | |||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true | |||
}, | |||
"node_modules/consola": { | |||
@@ -3535,9 +3539,15 @@ | |||
} | |||
}, | |||
"node_modules/dayjs": { | |||
<<<<<<< HEAD | |||
"version": "1.11.3", | |||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", | |||
"integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" | |||
======= | |||
"version": "1.11.2", | |||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", | |||
"integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
}, | |||
"node_modules/debug": { | |||
"version": "4.3.4", | |||
@@ -4352,9 +4362,15 @@ | |||
} | |||
}, | |||
"node_modules/esbuild-register": { | |||
<<<<<<< HEAD | |||
"version": "3.3.3", | |||
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.3.tgz", | |||
"integrity": "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==", | |||
======= | |||
"version": "3.3.2", | |||
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.2.tgz", | |||
"integrity": "sha512-jceAtTO6zxPmCfSD5cBb3rgIK1vmuqCKYwgylHiS1BF4pq0jJiJb4K2QMuqF4BEw7XDBRatYzip0upyTzfkgsQ==", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true, | |||
"peerDependencies": { | |||
"esbuild": ">=0.12 <1" | |||
@@ -6082,7 +6098,11 @@ | |||
"node_modules/is-module": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", | |||
<<<<<<< HEAD | |||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", | |||
======= | |||
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true | |||
}, | |||
"node_modules/is-number": { | |||
@@ -6232,9 +6252,15 @@ | |||
} | |||
}, | |||
"node_modules/jake/node_modules/async": { | |||
<<<<<<< HEAD | |||
"version": "3.2.4", | |||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", | |||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", | |||
======= | |||
"version": "3.2.3", | |||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", | |||
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true | |||
}, | |||
"node_modules/jake/node_modules/chalk": { | |||
@@ -7854,9 +7880,15 @@ | |||
} | |||
}, | |||
"node_modules/pinia/node_modules/vue-demi": { | |||
<<<<<<< HEAD | |||
"version": "0.13.1", | |||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz", | |||
"integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==", | |||
======= | |||
"version": "0.12.5", | |||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", | |||
"integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"hasInstallScript": true, | |||
"bin": { | |||
"vue-demi-fix": "bin/vue-demi-fix.js", | |||
@@ -13694,7 +13726,11 @@ | |||
"ms": { | |||
"version": "2.0.0", | |||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | |||
<<<<<<< HEAD | |||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", | |||
======= | |||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true | |||
} | |||
} | |||
@@ -14049,9 +14085,15 @@ | |||
"requires": {} | |||
}, | |||
"dayjs": { | |||
<<<<<<< HEAD | |||
"version": "1.11.3", | |||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", | |||
"integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" | |||
======= | |||
"version": "1.11.2", | |||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", | |||
"integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
}, | |||
"debug": { | |||
"version": "4.3.4", | |||
@@ -14603,9 +14645,15 @@ | |||
"optional": true | |||
}, | |||
"esbuild-register": { | |||
<<<<<<< HEAD | |||
"version": "3.3.3", | |||
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.3.tgz", | |||
"integrity": "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==", | |||
======= | |||
"version": "3.3.2", | |||
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.2.tgz", | |||
"integrity": "sha512-jceAtTO6zxPmCfSD5cBb3rgIK1vmuqCKYwgylHiS1BF4pq0jJiJb4K2QMuqF4BEw7XDBRatYzip0upyTzfkgsQ==", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true, | |||
"requires": {} | |||
}, | |||
@@ -15884,7 +15932,11 @@ | |||
"is-module": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", | |||
<<<<<<< HEAD | |||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", | |||
======= | |||
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true | |||
}, | |||
"is-number": { | |||
@@ -15989,9 +16041,15 @@ | |||
}, | |||
"dependencies": { | |||
"async": { | |||
<<<<<<< HEAD | |||
"version": "3.2.4", | |||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", | |||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", | |||
======= | |||
"version": "3.2.3", | |||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", | |||
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"dev": true | |||
}, | |||
"chalk": { | |||
@@ -17254,9 +17312,15 @@ | |||
}, | |||
"dependencies": { | |||
"vue-demi": { | |||
<<<<<<< HEAD | |||
"version": "0.13.1", | |||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz", | |||
"integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==", | |||
======= | |||
"version": "0.12.5", | |||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", | |||
"integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", | |||
>>>>>>> 40d50ccf36aef63b9c0df852b2171d9185ea2c1f | |||
"requires": {} | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
import { defAxios as request } from '@/utils/http' | |||
export function updatePwd(data) { | |||
return request({ | |||
url: '/index/updatePwd', | |||
method: 'PUT', | |||
data | |||
}) | |||
} | |||
@@ -1,6 +1,6 @@ | |||
import { defAxios as request } from '@/utils/http' | |||
/** | |||
* 获取部门分页数据接口 | |||
* 获取部门管理数据接口 | |||
* @returns 部门分页 | |||
*/ | |||
export function getDeptList(params) { | |||
@@ -53,7 +53,7 @@ export function editDept(data) { | |||
*/ | |||
export function deleteDept(id) { | |||
return request({ | |||
url: `/dept/delete${[id]}`, | |||
url: `/dept/delete/${id}`, | |||
method: 'DELETE' | |||
}) | |||
} |
@@ -1,7 +1,7 @@ | |||
import { defAxios as request } from '@/utils/http' | |||
/** | |||
* 获取菜单分页数据接口 | |||
* @returns 菜单分页数据 | |||
* 获取菜单管理数据接口 | |||
* @returns 菜单数据 | |||
*/ | |||
export function getMenuList(params) { | |||
return request({ | |||
@@ -53,7 +53,7 @@ export function editMenu(data) { | |||
*/ | |||
export function deleteMenu(id) { | |||
return request({ | |||
url: `/menu/delete${[id]}`, | |||
url: `/menu/delete/${id}`, | |||
method: 'DELETE' | |||
}) | |||
} |
@@ -63,9 +63,9 @@ export function setRoleStatus(data) { | |||
* 删除角色 | |||
* params | |||
*/ | |||
export function deleteRole(id) { | |||
export function deleteRole(data) { | |||
return request({ | |||
url: `/role/delete${[id]}`, | |||
url: `/role/delete/${data}`, | |||
method: 'DELETE' | |||
}) | |||
} |
@@ -39,9 +39,9 @@ export function editUser(data) { | |||
* 删除用户 | |||
* params | |||
*/ | |||
export function deleteUser(id) { | |||
export function deleteUser(idList) { | |||
return request({ | |||
url: `/user/delete${[id]}`, | |||
url: `/user/delete/${idList}`, | |||
method: 'DELETE' | |||
}) | |||
} |
@@ -8,15 +8,9 @@ export function getUsers(data = {}) { | |||
}) | |||
} | |||
export function getUser(id) { | |||
if (id) { | |||
return request({ | |||
url: `/user/${id}`, | |||
method: 'get' | |||
}) | |||
} | |||
export function getUser() { | |||
return request({ | |||
url: '/user', | |||
url: '/index/getUserInfo', | |||
method: 'get' | |||
}) | |||
} |
@@ -0,0 +1,59 @@ | |||
<template> | |||
<n-modal | |||
v-bind="getModalOptions" | |||
:style="`width:${getModalOptions.width}px`" | |||
preset="card" | |||
:title="options.title" | |||
@update:show="handleClose" | |||
> | |||
<n-card :bordered="false"> | |||
<slot name="Context" /> | |||
<n-space style="float: right"> | |||
<n-button @click="handleClose">取消</n-button> | |||
<n-button type="primary" @click="handleClick">确认</n-button> | |||
</n-space> | |||
</n-card> | |||
</n-modal> | |||
</template> | |||
<script> | |||
import { defineComponent, computed, unref } from 'vue' | |||
export default defineComponent({ | |||
name: 'Modal', | |||
props: { | |||
options: { | |||
type: Object, | |||
default: () => {} | |||
} | |||
}, | |||
emits: { | |||
save: null, // click事件没有检验 | |||
onClose: (value) => { | |||
return value | |||
} | |||
}, | |||
setup(props, { emit }) { | |||
const getModalOptions = computed(() => { | |||
return { | |||
...props.options, | |||
width: props.options.width || 600 | |||
} | |||
}) | |||
const handleClick = function() { | |||
emit('save') | |||
} | |||
const handleClose = function() { | |||
emit('onClose', true) | |||
} | |||
return { | |||
getModalOptions, | |||
handleClick, | |||
handleClose | |||
} | |||
} | |||
}) | |||
</script> | |||
<style scoped lang='scss'> | |||
</style> |
@@ -44,7 +44,7 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL | |||
} | |||
} | |||
// 处理数据结构 | |||
const resultInfo = res[listField] ? res[listField] : [] | |||
const resultInfo = res[listField] ? res[listField] : res | |||
dataSourceRef.value = dataType === 'tree' ? dealTree(resultInfo) : resultInfo | |||
setPagination({ | |||
[pageField]: currentPage, | |||
@@ -74,7 +74,7 @@ export function useDataSource(propsRef, { getPaginationInfo, setPagination, setL | |||
* @returns 返回树形结构数据 | |||
*/ | |||
function dealTree(info) { | |||
const tree = toTreeData(info.data, 'id', 'pid', 'children') | |||
const tree = toTreeData(info, 'id', 'pid', 'children') | |||
return tree | |||
} | |||
@@ -9,7 +9,6 @@ | |||
点击上传 | |||
</n-upload> | |||
<n-modal | |||
v-model:show="showModal" | |||
preset="card" | |||
style="width: 600px" | |||
> | |||
@@ -50,8 +49,8 @@ export default defineComponent({ | |||
} | |||
} | |||
}) | |||
function handleChange(file) { | |||
console.log(222, file) | |||
function handleChange(res) { | |||
console.log('已选择的文件:', res.file.file) | |||
} | |||
/** | |||
* @description: 上传前判断文件是否符合条件 | |||
@@ -60,7 +59,6 @@ export default defineComponent({ | |||
*/ | |||
function handleBeforeUpload(options) { | |||
const { file, fileList } = options | |||
console.log(11, file, fileList) | |||
if (props.size) { | |||
const size = file.file.size | |||
if (size < props.size * 1024 * 1024) { |
@@ -50,7 +50,7 @@ export default { | |||
/* 初始化搜索表单信息 */ | |||
function initForm() { | |||
data.info.forEach((item) => { | |||
form.value[item.key] = '' | |||
form.value[item.key] = null | |||
}) | |||
} | |||
@@ -1,15 +1,35 @@ | |||
<template> | |||
<n-layout-header class="layout__header" bordered> | |||
Header Header Header | |||
<!-- <SideMenu menu-mode="horizontal" /> --> | |||
<log-out /> | |||
</n-layout-header> | |||
</template> | |||
<script> | |||
import SideMenu from '@/layout/components/Menu/index.vue' | |||
import LogOut from '../Logout/index.vue' | |||
import { defineComponent } from 'vue' | |||
export default defineComponent({ | |||
name: 'LayoutHeader', | |||
components: { SideMenu } | |||
components: { SideMenu, LogOut } | |||
}) | |||
</script> | |||
<style scoped> | |||
.layout__header { | |||
padding: 0 20px; | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
} | |||
.user_msg { | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
} | |||
.user_avatar { | |||
width: 30px; | |||
height: 30px; | |||
margin-right: 10px; | |||
} | |||
</style> |
@@ -0,0 +1,133 @@ | |||
<template> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-form | |||
ref="formRef" | |||
:model="form" | |||
label-placement="left" | |||
:rules="rules" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
> | |||
<n-form-item | |||
label="旧密码:" | |||
path="oldPassword" | |||
> | |||
<n-input | |||
v-model:value="form.oldPassword" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请输入旧密码" | |||
/> | |||
</n-form-item> | |||
<n-form-item | |||
label="新密码:" | |||
path="newPassword" | |||
> | |||
<n-input | |||
v-model:value="form.newPassword" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请输入新密码" | |||
/> | |||
</n-form-item> | |||
<n-form-item | |||
label="确认密码:" | |||
path="configmPassword" | |||
> | |||
<n-input | |||
v-model:value="form.configmPassword" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请再次输入新密码" | |||
/> | |||
</n-form-item> | |||
</n-form> | |||
</template> | |||
</Modal> | |||
</template> | |||
<script> | |||
import Modal from '../../../../components/Modal/index.vue' | |||
import { updatePwd } from '@/api/home/index.js' | |||
import { reactive, toRefs, computed } from '@vue/reactivity' | |||
export default { | |||
name: 'UpdateModal', | |||
components: { Modal }, | |||
props: { | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
form: { | |||
oldPassword: '', | |||
newPassword: '', | |||
configmPassword: '' | |||
}, | |||
rules: { | |||
oldPassword: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入旧密码' | |||
}, | |||
newPassword: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入新密码' | |||
}, | |||
configmPassword: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请再次输入新密码' | |||
} | |||
} | |||
}) | |||
const getModalOptions = computed(() => { | |||
return { | |||
title: '修改密码', | |||
show: props.visible, | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
}) | |||
/* 关闭弹窗 */ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
return { | |||
...toRefs(data), | |||
getModalOptions, | |||
handleClose | |||
} | |||
}, | |||
methods: { | |||
handleConfirm() { | |||
this.$refs.formRef.validate((errors) => { | |||
if (!errors) { | |||
updatePwd(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,108 @@ | |||
<template> | |||
<n-dropdown trigger="hover" :options="options" @select="selectKey"> | |||
<div class="user_msg"> | |||
<n-image | |||
class="user_avatar" | |||
:src="userInfo.avatar" | |||
preview-disabled | |||
/> | |||
<span class="user_name">{{ userInfo.realname }}</span> | |||
</div> | |||
</n-dropdown> | |||
<!-- 修改密码 --> | |||
<update-modal v-if="modalShow" v-modal:visible="modalShow" /> | |||
</template> | |||
<script> | |||
import { reactive, toRefs, h } from 'vue' | |||
import { NIcon } from 'naive-ui' | |||
import { | |||
Pencil as EditIcon, | |||
LogOutOutline as LogoutIcon | |||
} from '@vicons/ionicons5' | |||
import { useDialog } from 'naive-ui' | |||
import { loginOut } from '@/api/login/index.js' | |||
import { mapActions, mapState } from 'pinia' | |||
import { useUserStore } from '@/store/modules/user.js' | |||
import UpdateModal from './components/UpdateModal.vue' | |||
export default { | |||
name: 'LogOut', | |||
components: { UpdateModal }, | |||
setup() { | |||
const renderIcon = (icon) => { | |||
return () => { | |||
return h(NIcon, null, { | |||
default: () => h(icon) | |||
}) | |||
} | |||
} | |||
const data = reactive({ | |||
options: [ | |||
{ | |||
label: '修改密码', | |||
key: 'edit', | |||
icon: renderIcon(EditIcon) | |||
}, | |||
{ | |||
label: '退出登录', | |||
key: 'out', | |||
icon: renderIcon(LogoutIcon) | |||
} | |||
], | |||
modalShow: false | |||
}) | |||
// 选中选项触发的回调 | |||
const dialog = useDialog() | |||
return { | |||
...toRefs(data), | |||
dialog | |||
} | |||
}, | |||
computed: { | |||
...mapState(useUserStore, { | |||
userInfo: 'userInfo' | |||
}) | |||
}, | |||
methods: { | |||
...mapActions(useUserStore, ['logout']), | |||
selectKey(key) { | |||
console.log(key) | |||
if (key === 'out') { | |||
this.dialog.warning({ | |||
title: '提示', | |||
content: '确定要退出登录吗?', | |||
positiveText: '确定', | |||
negativeText: '取消', | |||
onPositiveClick: () => { | |||
loginOut().then((res) => { | |||
if (res.code === 0) { | |||
this.$router.replace('/login') | |||
this.logout() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
}) | |||
} else if (key === 'edit') { | |||
this.modalShow = true | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.user_msg { | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
} | |||
.user_avatar { | |||
width: 30px; | |||
height: 30px; | |||
margin-right: 10px; | |||
} | |||
</style> |
@@ -1,6 +1,7 @@ | |||
<template> | |||
<n-menu | |||
:mode="menuMode" | |||
:accordion="true" | |||
:value="(currentRoute.title && currentRoute.meta.activeMenu) || currentRoute.title" | |||
:options="getMenuOptions" | |||
@update:value="handleMenuSelect" |
@@ -0,0 +1,123 @@ | |||
<template> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-form | |||
ref="formRef" | |||
:model="form" | |||
label-placement="left" | |||
:rules="rules" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
> | |||
<n-form-item | |||
label="旧密码:" | |||
path="oldPassword" | |||
> | |||
<n-input | |||
v-model:value="form.oldPassword" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请输入旧密码" | |||
/> | |||
</n-form-item> | |||
<n-form-item | |||
label="新密码:" | |||
path="newPassword" | |||
> | |||
<n-input | |||
v-model:value="form.newPassword" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请输入新密码" | |||
/> | |||
</n-form-item> | |||
<n-form-item | |||
label="确认密码:" | |||
path="configmPassword" | |||
> | |||
<n-input | |||
v-model:value="form.configmPassword" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请再次输入新密码" | |||
/> | |||
</n-form-item> | |||
</n-form> | |||
</template> | |||
</Modal> | |||
</template> | |||
<script> | |||
import Modal from '@/components/Modal/index.vue' | |||
import { updatePwd } from '@/api/home/index.js' | |||
import { reactive, toRefs } from '@vue/reactivity' | |||
export default { | |||
name: 'UpdateModal', | |||
components: { Modal }, | |||
props: { | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
form: { | |||
oldPassword: '', | |||
newPassword: '', | |||
configmPassword: '' | |||
}, | |||
rules: { | |||
oldPassword: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入旧密码' | |||
}, | |||
newPassword: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入新密码' | |||
}, | |||
configmPassword: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请再次输入新密码' | |||
} | |||
} | |||
}) | |||
/* 关闭弹窗 */ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
return { | |||
...toRefs(data), | |||
handleClose | |||
} | |||
}, | |||
methods: { | |||
handleConfirm() { | |||
this.$refs.formRef.validate((errors) => { | |||
if (!errors) { | |||
updatePwd(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
} | |||
} | |||
</script> |
@@ -32,9 +32,15 @@ import SideBar from './components/Sidebar/index.vue' | |||
import Tags from './components/Tags/index.vue' | |||
import { useSettingStore } from '@/store/modules/setting.js' | |||
import { computed } from 'vue' | |||
import { useUserStore } from '@/store/modules/user.js' | |||
const settingStore = useSettingStore() | |||
const menuMode = computed(() => settingStore.getMenuMode) | |||
const tagsMenuSetting = computed(() => settingStore.getTagsMenuSetting) | |||
const useUser = useUserStore() | |||
function getUserNow() { | |||
useUser.getUserInfo() | |||
} | |||
getUserNow() | |||
</script> | |||
@@ -9,17 +9,8 @@ export const useUserStore = defineStore('user', { | |||
} | |||
}, | |||
getters: { | |||
userId() { | |||
return this.userInfo?.id | |||
}, | |||
name() { | |||
return this.userInfo?.name | |||
}, | |||
avatar() { | |||
return this.userInfo?.avatar | |||
}, | |||
role() { | |||
return this.userInfo?.role || [] | |||
userInfoMsg() { | |||
return this.userInfo | |||
} | |||
}, | |||
actions: { | |||
@@ -27,15 +18,14 @@ export const useUserStore = defineStore('user', { | |||
try { | |||
const res = await getUser() | |||
if (res.code === 0) { | |||
const { id, name, avatar, role } = res.data | |||
this.userInfo = { id, name, avatar, role } | |||
return Promise.resolve(res.data) | |||
this.userInfo = res.data | |||
return Promise.resolve(res.msg) | |||
} else { | |||
return Promise.reject(res.message) | |||
return Promise.reject(res.msg) | |||
} | |||
} catch (error) { | |||
console.error(error) | |||
return Promise.reject(error.message) | |||
return Promise.reject(error.msg) | |||
} | |||
}, | |||
logout() { |
@@ -38,19 +38,38 @@ | |||
<script> | |||
import { userLogin, userCaptcha } from '@/api/login/index.js' | |||
import { setToken } from '@/utils/token' | |||
import { ref, reactive, onMounted } from 'vue' | |||
import { ref, toRefs, reactive, onMounted } from 'vue' | |||
export default { | |||
name: 'LoginPage', | |||
setup() { | |||
const loginForm = reactive({ | |||
username: '', | |||
password: '', | |||
key: '', | |||
captcha: '', | |||
remember: false | |||
const data = reactive({ | |||
loginForm: { | |||
username: '', | |||
password: '', | |||
key: '', | |||
captcha: '', | |||
remember: false | |||
}, | |||
rules: { | |||
username: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入用户名' | |||
}, | |||
password: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入密码' | |||
}, | |||
captcha: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入验证码' | |||
} | |||
} | |||
}) | |||
onMounted(() => { | |||
changeCode(loginForm) | |||
changeCode(data.loginForm) | |||
}) | |||
// 获取图形验证码 | |||
const captcha = ref('') | |||
@@ -62,35 +81,18 @@ export default { | |||
} | |||
const captForm = await userCaptcha(params) | |||
captcha.value = captForm.data.captcha | |||
loginForm.key = captForm.data.key | |||
data.loginForm.key = captForm.data.key | |||
} | |||
return { | |||
loginForm, | |||
...toRefs(data), | |||
captcha, | |||
changeCode, | |||
rules: reactive({ | |||
username: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入用户名' | |||
}, | |||
password: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入密码' | |||
}, | |||
captcha: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入验证码' | |||
} | |||
}) | |||
changeCode | |||
} | |||
}, | |||
methods: { | |||
handleLogin() { | |||
console.log(this.loginForm) | |||
userLogin(this.loginForm).then((res) => { | |||
if (res.code === 0) { | |||
// 登录成功存储token,跳转首页 |
@@ -0,0 +1,187 @@ | |||
<template> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-form | |||
ref="formRef" | |||
:model="form" | |||
label-placement="left" | |||
:rules="rules" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
> | |||
<n-form-item label="部门编号:" path="code"> | |||
<n-input | |||
v-model:value="form.code" | |||
clearable | |||
:maxlength="20" | |||
placeholder="请输入部门编号" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="部门名称:" path="name"> | |||
<n-input | |||
v-model:value="form.name" | |||
clearable | |||
:maxlength="20" | |||
placeholder="请输入部门名称" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="所属部门:" path="pid"> | |||
<n-select | |||
v-model:value="form.pid" | |||
:options="getDeptList" | |||
placeholder="请选择所属部门" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="排序号" path="sort"> | |||
<n-input-number v-model:value="form.sort" placeholder="请输入排序号" /> | |||
</n-form-item> | |||
<n-form-item | |||
label="备注:" | |||
> | |||
<n-input | |||
v-model:value="form.note" | |||
type="textarea" | |||
:rows="3" | |||
:maxlength="200" | |||
placeholder="请输入备注" | |||
/> | |||
</n-form-item> | |||
</n-form> | |||
</template> | |||
</Modal> | |||
</template> | |||
<script> | |||
import { defineComponent, computed, reactive, toRefs } from 'vue' | |||
import Modal from '@/components/Modal/index.vue' | |||
import { addDept, editDept } from '@/api/system/dept/index' | |||
export default defineComponent({ | |||
name: 'UserModal', | |||
components: { Modal }, | |||
props: { | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
row: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
deptList: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null, | |||
'done': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
form: { | |||
avatar: '/images/user/20211011/20211011151447698.jpg', | |||
code: '', | |||
deptId: null, | |||
username: '', | |||
realname: '', | |||
password: '', | |||
roleIds: [], | |||
status: 1, | |||
note: '' | |||
}, | |||
deptOptions: [], | |||
rolesOptions: [], | |||
rules: { | |||
code: [ | |||
{ required: true, message: '请输入部门编号', trigger: 'blur' } | |||
], | |||
name: [ | |||
{ required: true, message: '请输入部门名称', type: 'string', trigger: 'blur' } | |||
], | |||
sort: [ | |||
{ required: true, type: 'number', message: '请输入排序号', trigger: 'blur' } | |||
] | |||
} | |||
}) | |||
// 获取部门选项 | |||
const getDeptList = computed(() => { | |||
const list = props.deptList.map((item) => { | |||
const menu = { | |||
label: item.name, | |||
value: item.id | |||
} | |||
return menu | |||
}) | |||
return list | |||
}) | |||
const getModalOptions = computed(() => { | |||
const row = props.row | |||
if (props.row.pid === 0) { | |||
row.pid = null | |||
} | |||
console.log('====部门计算属性触发了====', row) | |||
return { | |||
title: props.row.name ? '修改部门' : '添加部门', | |||
show: props.visible, | |||
form: Object.assign(data.form, row), | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
}) | |||
/* 关闭弹窗 */ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
return { | |||
...toRefs(data), | |||
getDeptList, | |||
getModalOptions, | |||
handleClose | |||
} | |||
}, | |||
methods: { | |||
// 表单提交 | |||
handleConfirm() { | |||
const type = this.row.name ? 'edit' : 'add' | |||
this.$refs.formRef.validate((errors) => { | |||
if (!errors) { | |||
if (type === 'add') { | |||
addDept(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} else if (type === 'edit') { | |||
editDept(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
} | |||
}) | |||
} | |||
} | |||
}) | |||
</script> | |||
<style scoped lang='scss'> | |||
</style> |
@@ -1,81 +1,52 @@ | |||
<template> | |||
<div> | |||
<n-card> | |||
<headSearch :info="info" @search="handleSearch" /> | |||
<data-table | |||
:columns="data.columns" | |||
:data="data.data" | |||
:pagination="data.pagination" | |||
ref="tableRef" | |||
:columns="columns" | |||
:request="loadDataTable" | |||
:row-key="(row) => row.id" | |||
:pagination="false" | |||
data-type="tree" | |||
size="large" | |||
scroll-x="1200" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary"> 新建 </n-button> | |||
<n-button type="primary"> 删除 </n-button> | |||
<n-button type="primary" @click="handleModal"> 新建 </n-button> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
<!-- 新增、编辑弹窗 --> | |||
<dept-modal | |||
v-if="modalShow" | |||
v-model:visible="modalShow" | |||
:row="rowData" | |||
:dept-list="deptList" | |||
@done="handleSearch" | |||
/> | |||
</template> | |||
<script> | |||
import headSearch from '@/components/Search/index.vue' | |||
import dataTable from '@/components/DataTable/index.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import { getDeptList } from '@/api/system/index.js' | |||
import { h, onMounted, unref } from 'vue' | |||
import { reactive } from 'vue' | |||
import { | |||
getDeptList, | |||
getDeptAll, | |||
deleteDept | |||
} from '@/api/system/dept/index.js' | |||
import { h, unref, toRefs, ref, reactive, onMounted } from 'vue' | |||
import DeptModal from './components/DeptModal.vue' | |||
import info from './info.js' | |||
import table from './table.js' | |||
export default { | |||
name: 'MenuPage', | |||
components: { dataTable }, | |||
components: { dataTable, DeptModal, headSearch }, | |||
setup() { | |||
const data = reactive({ | |||
columns: [ | |||
{ | |||
title: '部门编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门名称', | |||
key: 'name', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门全称', | |||
key: 'fullname', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '排序', | |||
key: 'sort', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '备注', | |||
key: 'note', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
...table.columns, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
@@ -89,18 +60,29 @@ export default { | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
onClick: play.bind(null, row) | |||
onClick: add.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '修改', | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
onClick: play.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '删除', | |||
type: 'popconfirm', | |||
auth: 'basic_list' | |||
auth: 'basic_list', | |||
tip: '确定删除这条数据吗?', | |||
props: { | |||
negativeText: '取消', | |||
positiveText: '确认', | |||
onPositiveClick: deleteSingle.bind(null, row.id) | |||
} | |||
} | |||
], | |||
align: 'center' | |||
@@ -108,31 +90,38 @@ export default { | |||
} | |||
} | |||
], | |||
data: [], | |||
pagination: { | |||
pageSize: 10 | |||
} | |||
info: ref(info), | |||
modalShow: false, | |||
rowData: { | |||
status: 1, | |||
type: 0, | |||
hide: 0 | |||
}, | |||
deptList: [] | |||
}) | |||
function play(row) { | |||
console.log(row) | |||
// 获取全部菜单信息 | |||
async function getDept() { | |||
const list = await getDeptAll() | |||
data.deptList = list.data | |||
} | |||
onMounted(() => { | |||
getDept() | |||
}) | |||
/** | |||
* @description: 获取部门数据并做树形结构处理 | |||
* @return {*} | |||
*/ | |||
async function fetchList() { | |||
const params = { | |||
page: 1, | |||
limit: 10 | |||
const params = ref({}) | |||
const tableRef = ref() | |||
function handleSearch(data) { | |||
params.value = { | |||
...data | |||
} | |||
const res = await getDeptList(params) | |||
data.data = res.data | |||
tableRef.value.reFetch({ ...unref(params) }) | |||
} | |||
const params = reactive({ | |||
name: 'xiaoMa' | |||
}) | |||
const loadDataTable = async(res) => { | |||
const _params = { | |||
@@ -142,11 +131,53 @@ export default { | |||
return await getDeptList(_params) | |||
} | |||
onMounted(() => { | |||
fetchList() | |||
}) | |||
// 新增 | |||
function handleModal() { | |||
data.modalShow = true | |||
data.rowData = {} | |||
} | |||
// 行内新增 | |||
function add(row) { | |||
data.modalShow = true | |||
data.rowData = {} | |||
data.rowData.pid = row.id | |||
} | |||
// 编辑 | |||
function play(row) { | |||
data.rowData = row | |||
data.modalShow = true | |||
} | |||
// 单个删除数据 | |||
function deleteSingle(id) { | |||
deleteData(id) | |||
} | |||
return { data, loadDataTable } | |||
// 删除方法 | |||
function deleteData(id) { | |||
deleteDept(id) | |||
.then((res) => { | |||
if (res.code === 0) { | |||
handleSearch({}) | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
.catch((e) => { | |||
console.log(e) | |||
}) | |||
} | |||
return { | |||
...toRefs(data), | |||
tableRef, | |||
loadDataTable, | |||
handleSearch, | |||
handleModal, | |||
deleteSingle | |||
} | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,12 @@ | |||
const data = [ | |||
{ | |||
label: '部门名称', | |||
key: 'name', | |||
props: { | |||
placeholder: '请输入部门名称' | |||
} | |||
} | |||
] | |||
export default data | |||
@@ -0,0 +1,30 @@ | |||
const table = { | |||
columns: [{ | |||
title: '部门编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '部门名称', | |||
key: 'name', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '排序', | |||
key: 'sort', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
minWidth: 120 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
minWidth: 120 | |||
}] | |||
} | |||
export default table |
@@ -6,21 +6,21 @@ | |||
:on-negative-click="handleClose" | |||
> | |||
<template #Context> | |||
<n-form ref="formRef" :model="menuForm" :rules="menuRules" require-mark-placement="left" :label-width="80" label-placement="left"> | |||
<n-form ref="formRef" :model="form" :rules="rules" require-mark-placement="left" :label-width="80" label-placement="left"> | |||
<n-grid x-gap="12" :cols="2"> | |||
<n-gi> | |||
<n-form-item label="上级菜单" path="pid"> | |||
<n-select | |||
v-model:value="menuForm.pid" | |||
placeholder="请选择上级菜单" | |||
v-model:value="form.pid" | |||
:options="getMenuList" | |||
placeholder="请选择上级菜单" | |||
/> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="菜单类型" path="type"> | |||
<n-radio-group v-model:value="menuForm.type" name="type"> | |||
<n-radio v-for="item in typeOptions" :key="`type_${item.key}`" :value="item.key"> | |||
<n-radio-group v-model:value="form.type" name="type"> | |||
<n-radio v-for="item in typeOptions" :key="item.key" :value="item.key"> | |||
{{ item.label }} | |||
</n-radio> | |||
</n-radio-group> | |||
@@ -28,13 +28,13 @@ | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="菜单名称" path="title"> | |||
<n-input v-model:value="menuForm.title" placeholder="请输入菜单名称" /> | |||
<n-input v-model:value="form.title" placeholder="请输入菜单名称" /> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="打开方式" path="target"> | |||
<n-radio-group v-model:value="menuForm.target" name="target"> | |||
<n-radio v-for="item in openOptions" :key="`target_${item.key}`" :value="item.key"> | |||
<n-radio-group v-model:value="form.target" name="target"> | |||
<n-radio v-for="item in openOptions" :key="item.key" :value="item.key"> | |||
{{ item.label }} | |||
</n-radio> | |||
</n-radio-group> | |||
@@ -42,33 +42,33 @@ | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="菜单图标" path="icon"> | |||
<n-input v-model:value="menuForm.icon" placeholder="请选择菜单图标" /> | |||
<n-input v-model:value="form.icon" :disabled="form.type === 1" placeholder="请选择菜单图标" /> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="权限标识" path="permission"> | |||
<n-input v-model:value="menuForm.permission" placeholder="请输入权限标识" /> | |||
<n-input v-model:value="form.permission" :disabled="form.type === 0" placeholder="请输入权限标识" /> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="路由地址" path="path"> | |||
<n-input v-model:value="menuForm.path" placeholder="请输入路由地址" /> | |||
<n-input v-model:value="form.path" :disabled="form.type === 1" placeholder="请输入路由地址" /> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="排序号" path="sort"> | |||
<n-input v-model:value="menuForm.sort" placeholder="请输入排序号" /> | |||
<n-input-number v-model:value="form.sort" placeholder="请输入排序号" /> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="组件路径" path="component"> | |||
<n-input v-model:value="menuForm.component" placeholder="请输入组件路径" /> | |||
<n-input v-model:value="form.component" :disabled="form.type === 1" placeholder="请输入组件路径" /> | |||
</n-form-item> | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="是否可见" path="hide"> | |||
<n-radio-group v-model:value="menuForm.hide" name="hide"> | |||
<n-radio v-for="item in visibleOptions" :key="`hide_${item.key}`" :value="item.key"> | |||
<n-radio-group v-model:value="form.hide" name="hide"> | |||
<n-radio v-for="item in visibleOptions" :key="item.key" :value="item.key"> | |||
{{ item.label }} | |||
</n-radio> | |||
</n-radio-group> | |||
@@ -76,8 +76,8 @@ | |||
</n-gi> | |||
<n-gi> | |||
<n-form-item label="菜单状态" path="status"> | |||
<n-radio-group v-model:value="menuForm.status" name="status"> | |||
<n-radio v-for="item in statusOptions" :key="`status_${item.key}`" :value="item.key"> | |||
<n-radio-group v-model:value="form.status" name="status"> | |||
<n-radio v-for="item in statusOptions" :key="item.key" :value="item.key"> | |||
{{ item.label }} | |||
</n-radio> | |||
</n-radio-group> | |||
@@ -91,9 +91,9 @@ | |||
</template> | |||
<script> | |||
import { defineComponent, computed, reactive, toRefs, ref } from 'vue' | |||
import { defineComponent, computed, reactive, toRefs } from 'vue' | |||
import Modal from '@/components/Modal/index.vue' | |||
import { addMenu } from '@/api/system/menu/index.js' | |||
import { addMenu, editMenu } from '@/api/system/menu/index.js' | |||
export default defineComponent({ | |||
name: 'MenuModal', | |||
components: { Modal }, | |||
@@ -114,51 +114,48 @@ export default defineComponent({ | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null | |||
'update:visible': null, | |||
'done': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
menuForm: { | |||
pid: null, | |||
type: '0', | |||
form: { | |||
title: '', | |||
target: '0', | |||
icon: '', | |||
permission: '', | |||
path: '', | |||
sort: '', | |||
component: '', | |||
hide: '0', | |||
status: '1' | |||
hide: 0, | |||
status: 1 | |||
}, | |||
menuRules: { | |||
title: { | |||
rules: { | |||
title: [{ | |||
required: true, | |||
message: '请输入菜单名称', | |||
trigger: ['blur'] | |||
}, | |||
sort: { | |||
trigger: 'blur' | |||
}], | |||
sort: [{ | |||
required: true, | |||
type: 'number', | |||
message: '请输入排序号', | |||
trigger: ['blur'] | |||
} | |||
trigger: 'blur' | |||
}] | |||
}, | |||
typeOptions: [ | |||
{ key: '0', label: '菜单' }, | |||
{ key: '1', label: '按钮' } | |||
{ key: 0, label: '菜单' }, | |||
{ key: 1, label: '按钮' } | |||
], | |||
openOptions: [ | |||
{ key: '0', label: '组件' }, | |||
{ key: '1', label: '内链' }, | |||
{ key: '2', label: '外链' } | |||
{ key: '1', label: '内部' }, | |||
{ key: '2', label: '外部' } | |||
], | |||
visibleOptions: [ | |||
{ key: '0', label: '可见' }, | |||
{ key: '1', label: '不可见' } | |||
{ key: 0, label: '可见' }, | |||
{ key: 1, label: '不可见' } | |||
], | |||
statusOptions: [ | |||
{ key: '1', label: '在用' }, | |||
{ key: '2', label: '停用' } | |||
{ key: 1, label: '在用' }, | |||
{ key: 2, label: '停用' } | |||
] | |||
}) | |||
@@ -166,7 +163,7 @@ export default defineComponent({ | |||
const list = props.menuList.map((item) => { | |||
const menu = { | |||
label: item.title, | |||
value: item.pid | |||
value: item.id | |||
} | |||
return menu | |||
}) | |||
@@ -174,10 +171,15 @@ export default defineComponent({ | |||
}) | |||
const getModalOptions = computed(() => { | |||
const row = props.data | |||
if (props.data.pid === 0) { | |||
row.pid = null | |||
} | |||
console.log('菜单页面计算属性触发:', row) | |||
return { | |||
title: props.data.title ? '修改菜单' : '添加菜单', | |||
show: props.visible, | |||
title: props.data ? '修改菜单' : '新建菜单', | |||
width: 700, | |||
form: Object.assign(data.form, row), | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
@@ -187,31 +189,47 @@ export default defineComponent({ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
const formRef = ref() | |||
const handleConfirm = () => { | |||
formRef.value?.validate((errors) => { | |||
if (!errors) { | |||
const params = { | |||
...data.menuForm | |||
} | |||
addMenu(params) | |||
.then(res => { | |||
handleClose() | |||
}) | |||
} else { | |||
$message.error('清先完成校验') | |||
} | |||
}) | |||
return false | |||
} | |||
return { | |||
...toRefs(data), | |||
formRef, | |||
getMenuList, | |||
getModalOptions, | |||
handleClose, | |||
handleConfirm | |||
handleClose | |||
} | |||
}, | |||
methods: { | |||
// 表单提交 | |||
handleConfirm() { | |||
const type = this.data.title ? 'edit' : 'add' | |||
this.$refs.formRef.validate((errors) => { | |||
if (!errors) { | |||
if (type === 'add') { | |||
addMenu(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} else if (type === 'edit') { | |||
editMenu(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
} else { | |||
$message.error('请完善必填信息') | |||
} | |||
}) | |||
} | |||
} | |||
}) |
@@ -1,92 +1,46 @@ | |||
<template> | |||
<div> | |||
<n-card> | |||
<data-table :columns="data.columns" :pagination="false" :data="data.data" size="large" @fetch-success="getFechData"> | |||
<headSearch :info="info" @search="handleSearch" /> | |||
<data-table | |||
ref="tableRef" | |||
:columns="columns" | |||
:pagination="false" | |||
data-type="tree" | |||
:request="loadDataTable" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary" @click="handlleRoleAdd"> | |||
添加菜单 | |||
</n-button> | |||
<n-button type="primary" @click="handleModal"> 添加菜单 </n-button> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
<RoleModal v-model:visible="data.modalShow" :data="data.selectRow" :menu-list="data.data" /> | |||
<MenuModal | |||
v-if="modalShow" | |||
v-model:visible="modalShow" | |||
:data="rowData" | |||
:menu-list="menuList" | |||
@done="handleSearch" | |||
/> | |||
</template> | |||
<script> | |||
import headSearch from '@/components/Search/index.vue' | |||
import dataTable from '@/components/DataTable/index.vue' | |||
import RoleModal from './components/MenuModal.vue' | |||
import MenuModal from './components/MenuModal.vue' | |||
import Action from '@/components/DataTable/tools/Action.vue' | |||
import { getMenuList } from '@/api/system/index.js' | |||
import { h, onMounted } from 'vue' | |||
import { reactive } from 'vue' | |||
import { getMenu, getMenuList, deleteMenu } from '@/api/system/menu/index.js' | |||
import { h, ref, unref, reactive, toRefs, onMounted } from 'vue' | |||
import info from './info.js' | |||
import table from './table.js' | |||
export default { | |||
name: 'MenuPage', | |||
components: { dataTable, RoleModal }, | |||
components: { dataTable, MenuModal, headSearch }, | |||
setup() { | |||
const data = reactive({ | |||
columns: [ | |||
{ | |||
title: '菜单标题', | |||
key: 'title', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '菜单类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '请求方式', | |||
key: 'method', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '路由地址', | |||
key: 'path', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '组件路径', | |||
key: 'component', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '权限标识', | |||
key: 'permission', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '状态', | |||
key: 'status', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '排序', | |||
key: 'sort', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '可见', | |||
key: 'hide', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
...table.columns, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
@@ -100,18 +54,29 @@ export default { | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
onClick: play.bind(null, row) | |||
onClick: add.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '修改', | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
onClick: play.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '删除', | |||
type: 'popconfirm', | |||
auth: 'basic_list' | |||
auth: 'basic_list', | |||
tip: '确定删除这条数据吗?', | |||
props: { | |||
negativeText: '取消', | |||
positiveText: '确认', | |||
onPositiveClick: deleteSingle.bind(null, row.id) | |||
} | |||
} | |||
], | |||
align: 'center' | |||
@@ -119,48 +84,94 @@ export default { | |||
} | |||
} | |||
], | |||
data: [], | |||
info: ref(info), | |||
modalShow: false, | |||
selectRow: null | |||
menuList: [], | |||
rowData: { | |||
status: 1, | |||
type: 0, | |||
hide: 0 | |||
} | |||
}) | |||
function play(row) { | |||
console.log(row) | |||
// 获取全部菜单信息 | |||
async function getMenuAll() { | |||
const list = await getMenu() | |||
data.menuList = list.data | |||
} | |||
onMounted(() => { | |||
getMenuAll() | |||
}) | |||
/** | |||
* @description: 获取菜单数据 | |||
* @return {*} | |||
*/ | |||
async function fetchList() { | |||
const res = await getMenuList() | |||
data.data = res.data | |||
} | |||
function handlleRoleAdd() { | |||
data.modalShow = true | |||
const params = ref({}) | |||
const tableRef = ref() | |||
function handleSearch(data) { | |||
params.value = { | |||
...data | |||
} | |||
tableRef.value.reFetch({ ...unref(params) }) | |||
} | |||
/** | |||
* @description: 获取表单数据 | |||
* @param {*} data | |||
* @return {*} | |||
*/ | |||
function getFechData(data) { | |||
const loadDataTable = async(res) => { | |||
const _params = { | |||
...unref(params), | |||
...res | |||
} | |||
return await getMenuList(_params) | |||
} | |||
// 打开新增弹框 | |||
function handleModal() { | |||
data.modalShow = true | |||
data.rowData = {} | |||
} | |||
// 行内新增 | |||
function add(row) { | |||
data.modalShow = true | |||
data.rowData = {} | |||
data.rowData.pid = row.id | |||
} | |||
// 编辑 | |||
function play(row) { | |||
data.rowData = row | |||
data.modalShow = true | |||
} | |||
// 单个删除数据 | |||
function deleteSingle(id) { | |||
deleteData(id) | |||
} | |||
onMounted(() => { | |||
fetchList() | |||
}) | |||
// 删除方法 | |||
function deleteData(id) { | |||
deleteMenu(id) | |||
.then((res) => { | |||
if (res.code === 0) { | |||
handleSearch({}) | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
.catch((e) => { | |||
console.log(e) | |||
}) | |||
} | |||
return { | |||
data, | |||
handlleRoleAdd, | |||
getFechData | |||
...toRefs(data), | |||
tableRef, | |||
loadDataTable, | |||
handleSearch, | |||
handleModal, | |||
deleteSingle | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang='scss'> | |||
</style> |
@@ -0,0 +1,12 @@ | |||
const data = [ | |||
{ | |||
label: '菜单名称', | |||
key: 'title', | |||
props: { | |||
placeholder: '请输入菜单名称' | |||
} | |||
} | |||
] | |||
export default data | |||
@@ -0,0 +1,101 @@ | |||
import { h } from 'vue' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
const table = { | |||
columns: [ | |||
{ | |||
title: '菜单标题', | |||
key: 'title', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '菜单类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100, | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.type, | |||
filters: [ | |||
{ | |||
key: 0, | |||
label: '菜单' | |||
}, | |||
{ | |||
key: 1, | |||
label: '节点' | |||
} | |||
] | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '路由地址', | |||
key: 'path', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '组件路径', | |||
key: 'component', | |||
align: 'center', | |||
width: 200 | |||
}, | |||
{ | |||
title: '状态', | |||
key: 'status', | |||
align: 'center', | |||
width: 100, | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.status, | |||
filters: [ | |||
{ | |||
key: 1, | |||
label: '在用' | |||
}, | |||
{ | |||
key: 2, | |||
label: '停用' | |||
} | |||
] | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '排序', | |||
key: 'sort', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '是否可见', | |||
key: 'hide', | |||
align: 'center', | |||
width: 100, | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.hide, | |||
filters: [ | |||
{ | |||
key: 1, | |||
label: '可见' | |||
}, | |||
{ | |||
key: 2, | |||
label: '不可见' | |||
} | |||
] | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
} | |||
] | |||
} | |||
export default table |
@@ -0,0 +1,113 @@ | |||
<template> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-tree | |||
block-line | |||
cascade | |||
checkable | |||
:data="allTreeData" | |||
key-field="id" | |||
label-field="title" | |||
:default-expand-all="true" | |||
:default-checked-keys="checkedTreeData" | |||
@update:checked-keys="handleCheckTree" | |||
/> | |||
</template> | |||
</Modal> | |||
</template> | |||
<script> | |||
import { defineComponent, computed, onBeforeMount, reactive, toRefs } from 'vue' | |||
import { getRolePermission, savePermission } from '@/api/system/role/index' | |||
import Modal from '@/components/Modal/index.vue' | |||
import { toTreeData } from '@/utils/handleData.js' | |||
export default defineComponent({ | |||
name: 'ConfigModal', | |||
components: { Modal }, | |||
props: { | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
row: { | |||
type: Object, | |||
default: () => {} | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null, | |||
'done': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
menuIds: [], | |||
checkedTreeData: [], | |||
allTreeData: [] | |||
}) | |||
const getModalOptions = computed(() => { | |||
return { | |||
title: '权限分配', | |||
show: props.visible, | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
}) | |||
onBeforeMount(() => { | |||
getMenuByRoleId() | |||
}) | |||
// 获取当前角色的权限菜单列表 | |||
async function getMenuByRoleId() { | |||
const res = await getRolePermission(props.row.id) | |||
data.allTreeData = toTreeData(res.data, 'id', 'pid', 'children') | |||
const checkedArr = res.data | |||
if (checkedArr.length) { | |||
checkedArr.forEach((item) => { | |||
if (item.checked) { | |||
data.checkedTreeData.push(item.id) | |||
} | |||
}) | |||
} | |||
data.menuIds = data.checkedTreeData | |||
} | |||
// 勾选节点 | |||
function handleCheckTree(keys) { | |||
data.menuIds = keys | |||
} | |||
/* 关闭弹窗 */ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
return { | |||
...toRefs(data), | |||
getModalOptions, | |||
handleClose, | |||
handleCheckTree | |||
} | |||
}, | |||
methods: { | |||
// 提交 | |||
handleConfirm() { | |||
console.log(this.menuIds, this.checkedTreeData) | |||
savePermission({ roleId: this.row.id, menuIds: this.menuIds }).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} | |||
} | |||
}) | |||
</script> |
@@ -0,0 +1,166 @@ | |||
<template> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-form | |||
ref="formRef" | |||
:model="form" | |||
label-placement="left" | |||
:rules="rules" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
> | |||
<n-form-item label="角色编号:" path="code"> | |||
<n-input | |||
v-model:value="form.code" | |||
clearable | |||
:maxlength="20" | |||
placeholder="请输入角色编号" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="角色名称:" path="name"> | |||
<n-input | |||
v-model:value="form.name" | |||
clearable | |||
:maxlength="20" | |||
placeholder="请输入角色名称" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="状态" path="status"> | |||
<n-radio-group | |||
v-model:value="form.status" | |||
> | |||
<n-radio :value="1">正常</n-radio> | |||
<n-radio :value="2">禁用</n-radio> | |||
</n-radio-group> | |||
</n-form-item> | |||
<n-form-item | |||
label="备注:" | |||
> | |||
<n-input | |||
v-model:value="form.note" | |||
type="textarea" | |||
:rows="3" | |||
:maxlength="200" | |||
placeholder="请输入备注" | |||
/> | |||
</n-form-item> | |||
</n-form> | |||
</template> | |||
</Modal> | |||
</template> | |||
<script> | |||
import { defineComponent, computed, reactive, toRefs } from 'vue' | |||
import Modal from '@/components/Modal/index.vue' | |||
import { addRole, editRole } from '@/api/system/role/index' | |||
export default defineComponent({ | |||
name: 'RoleModal', | |||
components: { Modal }, | |||
props: { | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
row: { | |||
type: Object, | |||
default: () => {} | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null, | |||
'done': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
form: { | |||
code: '', | |||
name: '', | |||
status: 1, | |||
note: '' | |||
}, | |||
rules: { | |||
code: [ | |||
{ required: true, message: '请输入角色编号', trigger: 'blur' } | |||
], | |||
name: [ | |||
{ required: true, message: '请输入角色名称', type: 'string', trigger: 'blur' } | |||
], | |||
status: [ | |||
{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' } | |||
] | |||
} | |||
}) | |||
const getModalOptions = computed(() => { | |||
return { | |||
title: Object.keys(props.row).length === 0 ? '添加角色' : '编辑角色', | |||
show: props.visible, | |||
form: Object.assign(data.form, props.row), | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
}) | |||
/* 关闭弹窗 */ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
return { | |||
getModalOptions, | |||
handleClose, | |||
...toRefs(data), | |||
rules: reactive({ | |||
code: [ | |||
{ required: true, message: '请输入角色编号', trigger: 'blur' } | |||
], | |||
name: [ | |||
{ required: true, message: '请输入角色名称', type: 'string', trigger: 'blur' } | |||
], | |||
status: [ | |||
{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' } | |||
] | |||
}) | |||
} | |||
}, | |||
methods: { | |||
// 表单提交 | |||
handleConfirm() { | |||
const type = Object.keys(this.row).length === 0 ? 'add' : 'edit' | |||
this.$refs.formRef.validate((errors) => { | |||
if (!errors) { | |||
if (type === 'add') { | |||
addRole(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} else if (type === 'edit') { | |||
editRole(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
} | |||
}) | |||
} | |||
} | |||
}) | |||
</script> | |||
<style scoped lang='scss'> | |||
</style> |
@@ -1,45 +1,86 @@ | |||
<template> | |||
<div> | |||
<n-card> | |||
<headSearch :info="data.info" @search="handleSearch" /> | |||
<headSearch :info="info" @search="handleSearch" /> | |||
<data-table | |||
ref="tableRef" | |||
:columns="data.columns" | |||
:columns="columns" | |||
:row-key="(row) => row.id" | |||
:request="loadDataTable" | |||
size="large" | |||
scroll-x="1200" | |||
@update:checked-row-keys="handleCheck" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary"> | |||
新建 | |||
</n-button> | |||
<n-button type="primary"> | |||
删除 | |||
</n-button> | |||
<n-button type="primary" @click="handleModal"> 新建 </n-button> | |||
<n-popconfirm | |||
negative-text="取消" | |||
positive-text="确认" | |||
@positive-click="deleteComplex" | |||
> | |||
<template #trigger> | |||
<n-button type="primary">删除</n-button> | |||
</template> | |||
确定删除选中的数据吗? | |||
</n-popconfirm> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
<!-- 新增、编辑弹窗 --> | |||
<role-modal | |||
v-if="modalShow" | |||
v-model:visible="modalShow" | |||
:row="rowData" | |||
@done="handleSearch" | |||
/> | |||
<!-- 分配权限 --> | |||
<config-modal | |||
v-if="configModalShow" | |||
v-model:visible="configModalShow" | |||
:row="rowData" | |||
@done="handleSearch" | |||
/> | |||
</template> | |||
<script> | |||
import headSearch from '@/components/Search/index.vue' | |||
import dataTable from '@/components/DataTable/index.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import { getRoleList } from '@/api/system/role/index' | |||
import { h, ref, unref } from 'vue' | |||
import { reactive } from 'vue' | |||
import TableSwitch from '@/components/DataTable/tools/Switch.vue' | |||
import { | |||
getRoleList, | |||
deleteRole, | |||
setRoleStatus | |||
} from '@/api/system/role/index' | |||
import { h, ref, unref, toRefs, reactive } from 'vue' | |||
import table from './table.js' | |||
import info from './info.js' | |||
import RoleModal from './components/RoleModal.vue' | |||
import ConfigModal from './components/ConfigModal.vue' | |||
export default { | |||
name: 'MenuPage', | |||
components: { headSearch, dataTable }, | |||
components: { headSearch, dataTable, RoleModal, ConfigModal }, | |||
setup() { | |||
const data = reactive({ | |||
columns: [ | |||
...table.columns, | |||
{ | |||
title: '状态', | |||
key: 'status', | |||
align: 'center', | |||
width: 100, | |||
render(row) { | |||
return h(TableSwitch, { | |||
data: { id: row.id, status: row.status }, | |||
rowKey: 'status', | |||
checkedValue: 1, | |||
uncheckedValue: 2, | |||
onChange: setStatus.bind(row) | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
@@ -49,7 +90,7 @@ export default { | |||
return h(TableAction, { | |||
actions: [ | |||
{ | |||
label: '添加', | |||
label: '修改', | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
@@ -58,13 +99,25 @@ export default { | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '修改', | |||
label: '分配权限', | |||
type: 'button', | |||
props: { | |||
type: 'primary', | |||
ghost: true, | |||
onClick: configure.bind(null, row) | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '删除', | |||
type: 'popconfirm', | |||
auth: 'basic_list' | |||
auth: 'basic_list', | |||
tip: '确定删除这条数据吗?', | |||
props: { | |||
negativeText: '取消', | |||
positiveText: '确认', | |||
onPositiveClick: deleteSingle.bind(null, row.id) | |||
} | |||
} | |||
], | |||
align: 'center' | |||
@@ -72,22 +125,29 @@ export default { | |||
} | |||
} | |||
], | |||
info: ref(info) | |||
info: ref(info), | |||
modalShow: false, | |||
configModalShow: false, | |||
rowData: {} | |||
}) | |||
// 编辑 | |||
function play(row) { | |||
console.log(row) | |||
data.rowData = row | |||
data.modalShow = true | |||
} | |||
const params = ref({}) | |||
// 配置权限 | |||
function configure(row) { | |||
data.rowData = row | |||
data.configModalShow = true | |||
} | |||
const params = ref({}) | |||
const tableRef = ref() | |||
function handleSearch(data) { | |||
params.value = { | |||
...data | |||
} | |||
console.log(params.value) | |||
tableRef.value.reFetch({ ...unref(params) }) | |||
} | |||
@@ -99,13 +159,81 @@ export default { | |||
return await getRoleList(_params) | |||
} | |||
return { data, tableRef, loadDataTable, handleSearch } | |||
// 新增用户 | |||
function handleModal() { | |||
data.rowData = {} | |||
data.modalShow = true | |||
} | |||
// 选择表格数据 | |||
const selectedIds = ref([]) | |||
function handleCheck(rowKeys) { | |||
selectedIds.value = rowKeys | |||
} | |||
// 批量删除 | |||
function deleteComplex() { | |||
if (selectedIds.value.length) { | |||
deleteData(selectedIds.value) | |||
} else { | |||
$message.warning('请至少选中一条数据') | |||
} | |||
} | |||
// 单个删除数据 | |||
function deleteSingle(id) { | |||
deleteData([id]) | |||
} | |||
// 删除接口 | |||
function deleteData(data) { | |||
deleteRole(data) | |||
.then((res) => { | |||
if (res.code === 0) { | |||
handleSearch() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
.catch((e) => { | |||
console.log(e) | |||
}) | |||
} | |||
// 设置状态 | |||
function setStatus(row) { | |||
console.log(row) | |||
setRoleStatus({ id: row.data.id, status: row.value }) | |||
.then((res) => { | |||
if (res.code === 0) { | |||
handleSearch() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
.catch((e) => { | |||
console.log(e) | |||
}) | |||
} | |||
return { | |||
...toRefs(data), | |||
tableRef, | |||
loadDataTable, | |||
handleSearch, | |||
handleModal, | |||
handleCheck, | |||
selectedIds, | |||
deleteSingle, | |||
deleteComplex, | |||
deleteData, | |||
setStatus | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped lang='scss'> | |||
.n-button+.n-button{ | |||
margin-left: 10px; | |||
.n-button + .n-button { | |||
margin-left: 10px; | |||
} | |||
</style> |
@@ -6,24 +6,6 @@ const data = [ | |||
placeholder: '请输入角色名称' | |||
} | |||
} | |||
// { | |||
// label: '角色类型', | |||
// type: 'select', | |||
// key: 'op', | |||
// props: { | |||
// options: [{ | |||
// label: 11, value: 1 | |||
// }] | |||
// } | |||
// }, | |||
// { | |||
// label: '角色类型', | |||
// type: 'date', | |||
// key: 'date', | |||
// props: { | |||
// type: 'date' | |||
// } | |||
// } | |||
] | |||
export default data |
@@ -1,71 +1,28 @@ | |||
import TableImage from '@/components/DataTable/tools/Image.vue' | |||
import { h } from 'vue' | |||
const data = { | |||
columns: [ | |||
{ type: 'selection' }, | |||
{ | |||
title: '用户编号', | |||
title: '角色编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '头像', | |||
key: 'avatar', | |||
align: 'center', | |||
render(row) { | |||
return h(TableImage, { | |||
images: { | |||
width: 36, | |||
height: 36, | |||
src: row.avatar | |||
} | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '用户账号', | |||
key: 'username', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户姓名', | |||
key: 'realname', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '角色', | |||
key: 'roles', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '状态', | |||
key: 'status', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '部门', | |||
key: 'deptName', | |||
title: '角色名称', | |||
key: 'name', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
Minwidth: 160 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
width: 160 | |||
Minwidth: 160 | |||
} | |||
] | |||
} |
@@ -1,11 +1,18 @@ | |||
<template> | |||
<Modal :options="getModalOptions" @on-close="handleClose"> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-form | |||
ref="formRef" | |||
:model="form" | |||
label-placement="left" | |||
:rules="rules" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
> | |||
<n-form-item | |||
label="头像:" | |||
@@ -16,22 +23,7 @@ | |||
max:1, | |||
action: '/upload/uploadImage/demo', | |||
}" | |||
size="2" | |||
/> | |||
<!-- <n-upload | |||
action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f" | |||
:default-file-list="previewFileList" | |||
list-type="image-card" | |||
@preview="handlePreview" | |||
/> | |||
<n-modal | |||
v-model:show="showModal" | |||
preset="card" | |||
style="width: 600px" | |||
title="头像" | |||
> | |||
<img :src="form.avatar" style="width: 100%"> | |||
</n-modal> --> | |||
</n-form-item> | |||
<n-form-item label="用户编号:" path="code"> | |||
<n-input | |||
@@ -41,13 +33,6 @@ | |||
placeholder="请输入用户编号" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="所属部门:" path="deptId"> | |||
<n-select | |||
v-model:value="form.deptId" | |||
:options="deptOptions" | |||
placeholder="请选择所属部门" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="用户账号:" path="username"> | |||
<n-input | |||
v-model:value="form.username" | |||
@@ -56,25 +41,15 @@ | |||
placeholder="请输入用户账号" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="角色:" path="roleIds"> | |||
<n-select | |||
v-model:value="form.roleIds" | |||
clearable | |||
:multiple="true" | |||
:options="rolesOptions" | |||
placeholder="请选择角色" | |||
/> | |||
</n-form-item> | |||
<n-form-item | |||
v-if="form.type==2" | |||
label="驾照类型:" | |||
path="driverType" | |||
label="登录密码:" | |||
path="password" | |||
> | |||
<n-select | |||
v-model:value="form.driverType" | |||
clearable | |||
:options="[1, 2]" | |||
placeholder="请选择驾照类型" | |||
<n-input | |||
v-model:value="form.password" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请输入登录密码" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="用户姓名:" path="realname"> | |||
@@ -85,6 +60,22 @@ | |||
placeholder="请输入用户姓名" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="所属部门:" path="deptId"> | |||
<n-select | |||
v-model:value="form.deptId" | |||
:options="deptOptions" | |||
placeholder="请选择所属部门" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="角色:" path="roleIds"> | |||
<n-select | |||
v-model:value="form.roleIds" | |||
clearable | |||
:multiple="true" | |||
:options="rolesOptions" | |||
placeholder="请选择角色" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="状态" path="status"> | |||
<n-radio-group | |||
v-model:value="form.status" | |||
@@ -93,41 +84,8 @@ | |||
<n-radio :value="2">禁用</n-radio> | |||
</n-radio-group> | |||
</n-form-item> | |||
<n-form-item | |||
label="登录密码:" | |||
path="password" | |||
> | |||
<n-input | |||
v-model:value="form.password" | |||
type="password" | |||
:maxlength="20" | |||
placeholder="请输入登录密码" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="用户类型" path="type"> | |||
<n-radio-group | |||
v-model:value="form.type" | |||
> | |||
<n-radio :value="1">普通用户</n-radio> | |||
<n-radio :value="2">飞手</n-radio> | |||
</n-radio-group> | |||
</n-form-item> | |||
<n-form-item | |||
v-if="form.type==2" | |||
label="驾照编号:" | |||
path="driverCode" | |||
> | |||
<n-input | |||
v-model:value="form.driverCode" | |||
clearable | |||
:maxlength="20" | |||
placeholder="请输入驾照编号" | |||
/> | |||
</n-form-item> | |||
<n-form-item | |||
label="备注:" | |||
:label-col="{sm: {span: 3}, xs: {span: 6}}" | |||
:wrapper-col="{sm: {span: 21}, xs: {span: 18}}" | |||
> | |||
<n-input | |||
v-model:value="form.note" | |||
@@ -143,11 +101,12 @@ | |||
</template> | |||
<script> | |||
import { defineComponent, computed, onMounted, reactive } from 'vue' | |||
import { defineComponent, computed, onMounted, reactive, toRefs } from 'vue' | |||
import Modal from '@/components/Modal/index.vue' | |||
import uploadImage from '@/components/ImgUpload/index.vue' | |||
import { getDeptAll } from '@/api/system/dept/index' | |||
import { getRoleAll } from '@/api/system/role/index' | |||
import { addUser, editUser } from '@/api/system/user/index' | |||
import { dataToSelect } from '@/utils/handleData.js' | |||
export default defineComponent({ | |||
name: 'UserModal', | |||
@@ -160,22 +119,59 @@ export default defineComponent({ | |||
row: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
title: { | |||
type: String, | |||
default: '添加' | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null, | |||
onClose: null, | |||
done: null | |||
'done': null | |||
}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
form: { | |||
avatar: '/images/user/20211011/20211011151447698.jpg', | |||
code: '', | |||
deptId: null, | |||
username: '', | |||
realname: '', | |||
password: '', | |||
roleIds: [], | |||
status: 1, | |||
note: '' | |||
}, | |||
deptOptions: [], | |||
rolesOptions: [], | |||
rules: { | |||
avatar: [ | |||
{ required: true, message: '请选择头像', type: 'string', trigger: 'blur' } | |||
], | |||
code: [ | |||
{ required: true, message: '请输入编号', trigger: 'blur' } | |||
], | |||
realname: [ | |||
{ required: true, message: '请输入用户姓名', type: 'string', trigger: 'blur' } | |||
], | |||
deptId: [ | |||
{ required: true, message: '请选择部门', type: 'number', trigger: 'blur' } | |||
], | |||
status: [ | |||
{ required: true, message: '请选择状态', type: 'number', trigger: 'blur' } | |||
], | |||
roleIds: [ | |||
{ required: true, message: '请选择角色', type: 'array', trigger: 'blur' } | |||
], | |||
username: [ | |||
{ required: true, message: '请输入用户账号', type: 'string', trigger: 'blur' } | |||
] | |||
} | |||
}) | |||
const getModalOptions = computed(() => { | |||
return { | |||
title: props.title, | |||
show: props.visible | |||
title: Object.keys(props.row).length === 0 ? '添加用户' : '编辑用户', | |||
show: props.visible, | |||
form: Object.assign(data.form, props.row), | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
}) | |||
@@ -184,35 +180,16 @@ export default defineComponent({ | |||
emit('update:visible', false) | |||
} | |||
const form = reactive({ | |||
avatar: '', | |||
code: '', | |||
deptId: null, | |||
username: '', | |||
realname: '', | |||
password: '', | |||
roleIds: [], | |||
driverType: null, | |||
driverCode: '', | |||
type: 1, | |||
status: 1, | |||
note: '' | |||
}) | |||
// 获取部门列表 | |||
let deptOptions = reactive([]) | |||
async function getDeptOptions() { | |||
const res = await getDeptAll() | |||
deptOptions = dataToSelect(res.data, { label: 'name', value: 'id' }) | |||
console.log('部门选项:', deptOptions) | |||
data.deptOptions = dataToSelect(res.data, { label: 'name', value: 'id' }) | |||
} | |||
// 获取角色列表 | |||
let rolesOptions = reactive([]) | |||
async function getRoleOptions() { | |||
const res = await getRoleAll() | |||
rolesOptions = dataToSelect(res.data, { label: 'name', value: 'id' }) | |||
data.rolesOptions = dataToSelect(res.data, { label: 'name', value: 'id' }) | |||
} | |||
onMounted(() => { | |||
@@ -221,38 +198,52 @@ export default defineComponent({ | |||
}) | |||
// 上传文件 | |||
const handleUpload = ({ file, event }) => { | |||
console.log(event) | |||
form.avatar = file.url | |||
const handleUpload = ({ file }) => { | |||
console.log(file) | |||
// data.form.avatar = file.url | |||
} | |||
return { | |||
...toRefs(data), | |||
getModalOptions, | |||
handleClose, | |||
form, | |||
rules: reactive({ | |||
avatar: { | |||
required: true, | |||
trigger: 'blur', | |||
message: '请上传头像' | |||
}, | |||
code: { | |||
required: true, | |||
trigger: ['blur', 'input'], | |||
message: '请输入用户编号' | |||
}, | |||
deptId: { | |||
required: true, | |||
trigger: 'blur', | |||
message: '请选择部门' | |||
} | |||
}), | |||
handleUpload, | |||
deptOptions, | |||
rolesOptions | |||
handleUpload | |||
} | |||
}, | |||
methods: { | |||
// 表单提交 | |||
handleConfirm() { | |||
const type = Object.keys(this.row).length === 0 ? 'add' : 'edit' | |||
this.$refs.formRef.validate((errors) => { | |||
if (!errors) { | |||
if (type === 'add') { | |||
addUser(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} else if (type === 'edit') { | |||
editUser(this.form).then(res => { | |||
if (res.code === 0) { | |||
this.handleClose() | |||
this.$emit('done') | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}) | |||
} | |||
} else { | |||
$message.error('请完善必填信息') | |||
} | |||
}) | |||
} | |||
} | |||
}) | |||
</script> |
@@ -1,84 +1,57 @@ | |||
<template> | |||
<div> | |||
<n-card> | |||
<headSearch :info="info" @search="handleSearch" /> | |||
<data-table | |||
:columns="data.columns" | |||
ref="tableRef" | |||
:columns="columns" | |||
:row-key="(row) => row.id" | |||
:request="loadDataTable" | |||
size="large" | |||
@update:checked-row-keys="handleCheck" | |||
> | |||
<template #tableTitle> | |||
<n-button type="primary" @click="handleUser"> 新建 </n-button> | |||
<!-- <n-button type="primary" @click="deleteUsers"> 删除 </n-button> --> | |||
<n-button type="primary" @click="handleModal"> 新建 </n-button> | |||
<n-popconfirm | |||
negative-text="取消" | |||
positive-text="确认" | |||
@positive-click="deleteComplex" | |||
> | |||
<template #trigger> | |||
<n-button type="primary"> 删除 </n-button> | |||
</template> | |||
确认要删除选中数据吗? | |||
</n-popconfirm> | |||
</template> | |||
</data-table> | |||
</n-card> | |||
</div> | |||
<!-- 新增、编辑弹窗 --> | |||
<user-modal v-if="data.modalShow" v-model:visible="data.modalShow" :row="rowData" :title="modalTitle" /> | |||
<user-modal | |||
v-if="modalShow" | |||
v-model:visible="modalShow" | |||
:row="rowData" | |||
@done="handleSearch" | |||
/> | |||
</template> | |||
<script> | |||
import headSearch from '@/components/Search/index.vue' | |||
import dataTable from '@/components/DataTable/index.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import TableImage from '@/components/DataTable/tools/Image.vue' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
import TableSwitch from '@/components/DataTable/tools/Switch.vue' | |||
import { getUserList } from '@/api/system/user/index.js' | |||
import { h, unref, ref } from 'vue' | |||
import { reactive } from 'vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import { getUserList, resetPassword, deleteUser, setUserStatus } from '@/api/system/user/index.js' | |||
import { h, unref, ref, toRefs, reactive } from 'vue' | |||
import UserModal from './components/UserModal.vue' | |||
import info from './info.js' | |||
import table from './table.js' | |||
export default { | |||
name: 'MenuPage', | |||
components: { dataTable, UserModal }, | |||
components: { dataTable, UserModal, headSearch }, | |||
setup() { | |||
const data = reactive({ | |||
columns: [ | |||
{ | |||
title: '用户编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '头像', | |||
key: 'avatar', | |||
align: 'center', | |||
render(row) { | |||
return h(TableImage, { | |||
images: { | |||
width: 36, | |||
height: 36, | |||
src: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQiKrYt-fEfJ4SZhF9KfLLaX9f15KV6Ve1ptA&usqp=CAU' | |||
} | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '用户账号', | |||
key: 'username', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户姓名', | |||
key: 'realname', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户类型', | |||
key: 'type', | |||
align: 'center', | |||
width: 100 | |||
}, | |||
{ | |||
title: '角色', | |||
key: 'roles', | |||
align: 'center', | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.roles | |||
}) | |||
} | |||
}, | |||
...table.columns, | |||
{ | |||
title: '状态', | |||
key: 'status', | |||
@@ -86,31 +59,14 @@ export default { | |||
width: 100, | |||
render(row) { | |||
return h(TableSwitch, { | |||
data: row, | |||
data: { id: row.id, status: row.status }, | |||
rowKey: 'status', | |||
checkedValue: 1, | |||
uncheckedValue: 2, | |||
onChange: getSwitch.bind(row) | |||
onChange: setStatus.bind(row) | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '部门', | |||
key: 'deptName', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
@@ -128,10 +84,27 @@ export default { | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
{ | |||
label: '重置密码', | |||
type: 'popconfirm', | |||
auth: 'basic_list', | |||
tip: '确定要重置为123456吗?', | |||
props: { | |||
negativeText: '取消', | |||
positiveText: '确认', | |||
onPositiveClick: resetPsw.bind(null, row.id) | |||
} | |||
}, | |||
{ | |||
label: '删除', | |||
type: 'popconfirm', | |||
auth: 'basic_list' | |||
auth: 'basic_list', | |||
tip: '确定删除这条数据吗?', | |||
props: { | |||
negativeText: '取消', | |||
positiveText: '确认', | |||
onPositiveClick: deleteSingle.bind(null, row.id) | |||
} | |||
} | |||
], | |||
align: 'center' | |||
@@ -139,21 +112,26 @@ export default { | |||
} | |||
} | |||
], | |||
modalShow: false | |||
info: ref(info), | |||
modalShow: false, | |||
rowData: {} | |||
}) | |||
const modalTitle = ref('添加用户') | |||
let rowData = reactive({}) | |||
// 打开编辑弹窗 | |||
function play(row) { | |||
rowData = row | |||
modalTitle.value = '编辑用户' | |||
console.log('编辑弹窗内容:', row) | |||
data.rowData = row | |||
data.modalShow = true | |||
} | |||
const params = reactive({ | |||
name: '' | |||
}) | |||
const params = ref({}) | |||
const tableRef = ref() | |||
function handleSearch(data) { | |||
params.value = { | |||
...data | |||
} | |||
tableRef.value.reFetch({ ...unref(params) }) | |||
} | |||
const loadDataTable = async(res) => { | |||
const _params = { | |||
@@ -162,17 +140,89 @@ export default { | |||
} | |||
return await getUserList(_params) | |||
} | |||
function handleUser() { | |||
rowData = {} | |||
modalTitle.value = '添加用户' | |||
// 新增 | |||
function handleModal() { | |||
data.rowData = {} | |||
data.modalShow = true | |||
} | |||
function getSwitch(row) { | |||
console.log(row) | |||
// 选择表格数据 | |||
const selectedIds = ref([]) | |||
function handleCheck(rowKeys) { | |||
selectedIds.value = rowKeys | |||
} | |||
// 批量删除 | |||
function deleteComplex() { | |||
if (selectedIds.value.length) { | |||
deleteData(selectedIds.value) | |||
} else { | |||
$message.warning('请至少选中一条数据') | |||
} | |||
} | |||
// 单个删除数据 | |||
function deleteSingle(id) { | |||
deleteData([id]) | |||
} | |||
// 删除用户接口 | |||
function deleteData(data) { | |||
deleteUser(data).then((res) => { | |||
if (res.code === 0) { | |||
handleSearch() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} | |||
// 重置密码 | |||
function resetPsw(id) { | |||
resetPassword({ id }).then(res => { | |||
if (res.code === 0) { | |||
handleSearch() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} | |||
// 设置状态 | |||
function setStatus(row) { | |||
setUserStatus({ id: row.data.id, status: row.value }).then(res => { | |||
if (res.code === 0) { | |||
handleSearch() | |||
$message.success(res.msg) | |||
} else { | |||
$message.error(res.msg) | |||
} | |||
}).catch(e => { | |||
console.log(e) | |||
}) | |||
} | |||
return { | |||
loadDataTable, | |||
handleModal, | |||
...toRefs(data), | |||
tableRef, | |||
handleSearch, | |||
selectedIds, | |||
deleteComplex, | |||
handleCheck, | |||
deleteData, | |||
resetPsw, | |||
setStatus | |||
} | |||
}, | |||
methods: { | |||
return { data, loadDataTable, handleUser, rowData, modalTitle } | |||
} | |||
} | |||
</script> |
@@ -0,0 +1,45 @@ | |||
import { getRoleAll } from '@/api/system/role/index' | |||
import { dataToSelect } from '@/utils/handleData.js' | |||
import { ref } from 'vue' | |||
const rolesOptions = ref([]) | |||
const getRolesOption = async function() { | |||
const res = await getRoleAll() | |||
rolesOptions.value = dataToSelect(res.data, { label: 'name', value: 'id' }) | |||
} | |||
getRolesOption() | |||
const data = [ | |||
{ | |||
label: '用户账号', | |||
key: 'username', | |||
props: { | |||
placeholder: '请输入用户账号' | |||
} | |||
}, | |||
{ | |||
label: '用户姓名', | |||
key: 'realname', | |||
props: { | |||
placeholder: '请输入用户姓名' | |||
} | |||
}, | |||
{ | |||
label: '用户角色', | |||
type: 'select', | |||
key: 'roleId', | |||
props: { | |||
placeholder: '请选择用户角色', | |||
options: rolesOptions | |||
} | |||
} | |||
// { | |||
// label: '角色类型', | |||
// type: 'date', | |||
// key: 'date', | |||
// props: { | |||
// type: 'date' | |||
// } | |||
// } | |||
] | |||
export default data | |||
@@ -0,0 +1,69 @@ | |||
import { h } from 'vue' | |||
import TableImage from '@/components/DataTable/tools/Image.vue' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
const table = { | |||
columns: [ | |||
{ | |||
type: 'selection' | |||
}, | |||
{ | |||
title: '用户编号', | |||
key: 'code', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '头像', | |||
key: 'avatar', | |||
align: 'center', | |||
render(row) { | |||
return h(TableImage, { | |||
images: { | |||
width: 36, | |||
height: 36, | |||
src: row.avatar | |||
} | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '用户账号', | |||
key: 'username', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '用户姓名', | |||
key: 'realname', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '角色', | |||
key: 'roleList', | |||
align: 'center', | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.roleList, | |||
rowKey: 'name' | |||
}) | |||
} | |||
}, | |||
{ | |||
title: '部门', | |||
key: 'deptName', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '创建时间', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
}, | |||
{ | |||
title: '更新时间', | |||
key: 'updateTime', | |||
align: 'center', | |||
width: 160 | |||
} | |||
] | |||
} | |||
export default table |