mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-10-14 14:11:10 +00:00
feat 用户操作
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
validate-trigger="['blur', 'change']"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
|
@@ -13,6 +13,7 @@
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
validate-trigger="['blur', 'change']"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
|
60
src/views/baseapi/log/login/LoginLog.api.ts
Normal file
60
src/views/baseapi/log/login/LoginLog.api.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { defHttp } from '@/utils/http/axios'
|
||||
import { PageResult, Result } from '#/axios'
|
||||
import { BaseEntity } from '#/web'
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
export const page = (params) => {
|
||||
return defHttp.get<Result<PageResult<LoginLog>>>({
|
||||
url: '/log/login/page',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单条
|
||||
*/
|
||||
export const get = (id) => {
|
||||
return defHttp.get<Result<LoginLog>>({
|
||||
url: '/log/login/findById',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 清除指定天数之前的日志
|
||||
*/
|
||||
export const deleteByDay = (deleteDay) => {
|
||||
return defHttp.delete<Result>({
|
||||
url: '/log/login/deleteByDay',
|
||||
params: { deleteDay },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 登陆日志
|
||||
*/
|
||||
export interface LoginLog extends BaseEntity {
|
||||
// 用户id
|
||||
userId: number
|
||||
// 用户名称
|
||||
account: string
|
||||
// 登录成功状态
|
||||
login: boolean
|
||||
// 终端
|
||||
client: string
|
||||
// 登录方式
|
||||
loginType: string
|
||||
// 登录IP地址
|
||||
ip: string
|
||||
// 登录地点
|
||||
loginLocation: string
|
||||
// 操作系统
|
||||
os: string
|
||||
// 浏览器类型
|
||||
browser: string
|
||||
// 提示消息
|
||||
msg: string
|
||||
// 访问时间
|
||||
loginTime: string
|
||||
}
|
68
src/views/baseapi/log/login/LoginLogInfo.vue
Normal file
68
src/views/baseapi/log/login/LoginLogInfo.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<basic-modal
|
||||
v-bind="$attrs"
|
||||
:loading="confirmLoading"
|
||||
width="50%"
|
||||
title="查看"
|
||||
:open="visible"
|
||||
@cancel="visible = false"
|
||||
>
|
||||
<description :column="2" :data="data" :schema="schema" />
|
||||
<template #footer>
|
||||
<a-button key="cancel" @click="visible = false">取消</a-button>
|
||||
</template>
|
||||
</basic-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Description, DescItem } from '@/components/Description'
|
||||
import { get, LoginLog } from './LoginLog.api'
|
||||
|
||||
import BasicModal from '@/components/Modal/src/BasicModal.vue'
|
||||
import { findOneByField } from '@/utils/dataUtil'
|
||||
import { Client, findAll } from '@/views/iam/client/Client.api'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
onMounted(() => {
|
||||
initClients()
|
||||
})
|
||||
|
||||
let clients = ref<Client[]>([])
|
||||
let data = ref<LoginLog>()
|
||||
let visible = ref(false)
|
||||
let confirmLoading = ref(false)
|
||||
let schema = [
|
||||
{ field: 'account', label: '登录账号' },
|
||||
{ field: 'login', label: '登录成功状态', render: (curVal) => (curVal ? '成功' : '失败') },
|
||||
{ field: 'client', label: '登录终端', render: (curVal) => getClient(curVal) },
|
||||
{ field: 'ip', label: '登录IP地址' },
|
||||
{ field: 'browser', label: '浏览器类型' },
|
||||
{ field: 'os', label: '操作系统' },
|
||||
{ field: 'msg', label: '提示消息' },
|
||||
{ field: 'loginTime', label: '访问时间' },
|
||||
] as DescItem[]
|
||||
|
||||
function show(id) {
|
||||
visible.value = true
|
||||
confirmLoading.value = true
|
||||
get(id).then((res) => {
|
||||
data.value = res.data
|
||||
confirmLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
async function initClients() {
|
||||
const { data } = await findAll()
|
||||
clients.value = data
|
||||
}
|
||||
|
||||
// 获取终端信息
|
||||
function getClient(code) {
|
||||
return findOneByField(clients.value, code, 'code')?.['name']
|
||||
}
|
||||
defineExpose({
|
||||
show,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
185
src/views/baseapi/log/login/LoginLogList.vue
Normal file
185
src/views/baseapi/log/login/LoginLogList.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query
|
||||
:query-params="model.queryParam"
|
||||
:fields="fields"
|
||||
@query="queryPage"
|
||||
@reset="resetQueryParams"
|
||||
/>
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }">
|
||||
<template #buttons>
|
||||
<a-space>
|
||||
<a-select
|
||||
style="width: 180px"
|
||||
v-model:value="deleteDay"
|
||||
:options="deleteDays"
|
||||
allow-clear
|
||||
placeholder="清除多久前的日志"
|
||||
/>
|
||||
<a-button v-if="deleteDay" @click="deleteLogs" type="primary">清理</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
|
||||
<vxe-column type="seq" width="60" />
|
||||
<vxe-column field="userId" title="用户id" />
|
||||
<vxe-column field="account" title="用户名称" />
|
||||
<vxe-column field="login" title="登录成功状态">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.login" color="green">成功</a-tag>
|
||||
<a-tag v-else color="red">失败</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="client" title="终端">
|
||||
<template #default="{ row }">
|
||||
{{ getClient(row.client) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="ip" title="登录IP地址" />
|
||||
<vxe-column field="os" title="操作系统" />
|
||||
<vxe-column field="browser" title="浏览器类型" />
|
||||
<vxe-column field="msg" title="提示消息" />
|
||||
<vxe-column field="loginTime" title="访问时间" />
|
||||
<vxe-column fixed="right" width="60" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<span>
|
||||
<a href="javascript:" @click="show(row)">查看</a>
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<LoginLogInfo :clients="clients" :login-types="loginTypes" ref="loginLogInfo" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { deleteByDay, page } from './LoginLog.api'
|
||||
import useTablePage from '@/hooks/bootx/useTablePage'
|
||||
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { QueryField } from '@/components/Bootx/Query/Query'
|
||||
import { Client, findAll as findClients } from '@/views/iam/client/Client.api'
|
||||
import { dropdownTranslate, findOneByField } from '@/utils/dataUtil'
|
||||
import LoginLogInfo from './LoginLogInfo.vue'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
|
||||
// 使用hooks
|
||||
const {
|
||||
handleTableChange,
|
||||
pageQueryResHandel,
|
||||
resetQueryParams,
|
||||
pagination,
|
||||
pages,
|
||||
model,
|
||||
loading,
|
||||
} = useTablePage(queryPage)
|
||||
const { notification, createMessage, createConfirm } = useMessage()
|
||||
|
||||
let clients = ref<Client[]>()
|
||||
const deleteDay = ref<number | undefined>(undefined)
|
||||
|
||||
const xTable = ref<VxeTableInstance>()
|
||||
const xToolbar = ref<VxeToolbarInstance>()
|
||||
const loginLogInfo = ref<any>()
|
||||
|
||||
// 删除条件
|
||||
let deleteDays = ref<LabeledValue[]>([
|
||||
{ label: '3天之前', value: '3' },
|
||||
{ label: '7天之前', value: '7' },
|
||||
{ label: '30天之前', value: '30' },
|
||||
{ label: '60天之前', value: '60' },
|
||||
{ label: '90天之前', value: '90' },
|
||||
{ label: '180天之前', value: '180' },
|
||||
{ label: '365天之前', value: '365' },
|
||||
])
|
||||
// 查询条件
|
||||
const fields = computed(() => {
|
||||
return [
|
||||
{ field: 'code', type: 'string', name: '账号', placeholder: '请输入账号名称' },
|
||||
{
|
||||
field: 'client',
|
||||
type: 'list',
|
||||
name: '终端',
|
||||
placeholder: '请选择终端',
|
||||
selectList: dropdownTranslate(clients, 'name', 'code'),
|
||||
},
|
||||
] as QueryField[]
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
initClientAndLoginType()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化 终端列表和登录方式列表
|
||||
*/
|
||||
function initClientAndLoginType() {
|
||||
findClients().then(({ data }) => {
|
||||
clients.value = data
|
||||
})
|
||||
}
|
||||
|
||||
function vxeBind() {
|
||||
xTable.value?.connect(xToolbar.value as VxeToolbarInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
page({
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
}).then(({ data }) => {
|
||||
pageQueryResHandel(data)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
function show(record) {
|
||||
loginLogInfo.value.show(record.id)
|
||||
}
|
||||
/**
|
||||
* 获取终端信息
|
||||
*/
|
||||
function getClient(code) {
|
||||
return findOneByField(clients, code, 'code')?.['name']
|
||||
}
|
||||
/**
|
||||
* 清理日志
|
||||
*/
|
||||
function deleteLogs() {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '警告',
|
||||
content: '是否清除指定日期前的日志,该操作不可撤回',
|
||||
onOk: async () => {
|
||||
createMessage.info('清理日志中...')
|
||||
deleteByDay(deleteDay).then(() => {
|
||||
createMessage.success('清理日志成功')
|
||||
queryPage()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
67
src/views/baseapi/log/operate/OperateLog.api.ts
Normal file
67
src/views/baseapi/log/operate/OperateLog.api.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { defHttp } from '@/utils/http/axios'
|
||||
import { PageResult, Result } from '#/axios'
|
||||
import { BaseEntity } from '#/web'
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
export const page = (params) => {
|
||||
return defHttp.get<Result<PageResult<OperateLog>>>({
|
||||
url: '/log/operate/page',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单条
|
||||
*/
|
||||
export const get = (id) => {
|
||||
return defHttp.get<Result<OperateLog>>({
|
||||
url: '/log/operate/findById',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定天数之前的日志
|
||||
*/
|
||||
export const deleteByDay = (deleteDay) => {
|
||||
return defHttp.delete<Result>({
|
||||
url: '/log/operate/deleteByDay',
|
||||
params: { deleteDay },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作日志
|
||||
*/
|
||||
export interface OperateLog extends BaseEntity {
|
||||
// 操作模块
|
||||
title?: string
|
||||
// 操作人员id
|
||||
operateId?: number
|
||||
// 操作人员账号
|
||||
username?: string
|
||||
// 业务类型
|
||||
businessType?: string
|
||||
// 请求方法
|
||||
method?: string
|
||||
// 请求方式
|
||||
requestMethod?: string
|
||||
// 请求url
|
||||
operateUrl?: string
|
||||
// 操作ip
|
||||
operateIp?: string
|
||||
// 操作地点
|
||||
operateLocation?: string
|
||||
// 请求参数
|
||||
operateParam?: string
|
||||
// 返回参数
|
||||
operateReturn?: string
|
||||
// 是否成功
|
||||
success?: boolean
|
||||
// 错误提示
|
||||
errorMsg?: string
|
||||
// 操作时间
|
||||
operateTime?: string
|
||||
}
|
64
src/views/baseapi/log/operate/OperateLogInfo.vue
Normal file
64
src/views/baseapi/log/operate/OperateLogInfo.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<basic-modal
|
||||
v-bind="$attrs"
|
||||
:loading="confirmLoading"
|
||||
width="50%"
|
||||
title="查看"
|
||||
:open="visible"
|
||||
@cancel="visible = false"
|
||||
>
|
||||
<description :column="2" :data="data" :schema="schema" />
|
||||
<template #footer>
|
||||
<a-space>
|
||||
<a-button key="cancel" @click="visible = false">取消</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</basic-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { get, OperateLog } from './OperateLog.api'
|
||||
import { BasicModal } from '@/components/Modal'
|
||||
import { DescItem, Description } from '@/components/Description'
|
||||
import { useDict } from '@/hooks/bootx/useDict'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { dictConvert } = useDict()
|
||||
|
||||
let data = ref<OperateLog>({})
|
||||
let visible = ref(false)
|
||||
let confirmLoading = ref(false)
|
||||
let schema = [
|
||||
{ field: 'id', label: '主键' },
|
||||
{ field: 'username', label: '操作人员账号' },
|
||||
{ field: 'title', label: '操作模块' },
|
||||
{
|
||||
field: 'client',
|
||||
label: '业务类型',
|
||||
render: (businessType) => dictConvert('LogBusinessType', businessType),
|
||||
},
|
||||
{ field: 'requestMethod', label: '请求方式' },
|
||||
{ field: 'operateUrl', label: '请求url' },
|
||||
{ field: 'method', label: '操作方法' },
|
||||
{ field: 'success', label: '操作状态', render: (success) => (success ? '成功' : '失败') },
|
||||
{ field: 'errorMsg', label: '提示消息' },
|
||||
{ field: 'operateParam', label: '请求参数' },
|
||||
{ field: 'operateReturn', label: '响应参数' },
|
||||
{ field: 'operateTime', label: '操作时间' },
|
||||
] as DescItem[]
|
||||
|
||||
function show(id) {
|
||||
visible.value = true
|
||||
confirmLoading.value = true
|
||||
get(id).then((res) => {
|
||||
data.value = res.data
|
||||
confirmLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
158
src/views/baseapi/log/operate/OperateLogList.vue
Normal file
158
src/views/baseapi/log/operate/OperateLogList.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query
|
||||
:query-params="model.queryParam"
|
||||
:fields="fields"
|
||||
@query="queryPage"
|
||||
@reset="resetQueryParams"
|
||||
/>
|
||||
</div>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar ref="xToolbar" custom :refresh="{ queryMethod: queryPage }">
|
||||
<template #buttons>
|
||||
<a-space>
|
||||
<a-select
|
||||
style="width: 180px"
|
||||
v-model:value="deleteDay"
|
||||
:options="deleteDays"
|
||||
allow-clear
|
||||
placeholder="清除多久前的日志"
|
||||
/>
|
||||
<a-button v-if="deleteDay" @click="deleteLogs" type="primary">清理</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
|
||||
<vxe-column type="seq" width="60" />
|
||||
<vxe-column field="operateId" title="操作人员id" />
|
||||
<vxe-column field="username" title="操作人员账号" />
|
||||
<vxe-column field="title" title="操作模块" />
|
||||
<vxe-column field="success" title="是否成功">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.success" color="green">成功</a-tag>
|
||||
<a-tag v-else color="red">失败</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="businessType" title="业务类型">
|
||||
<template #default="{ row }">
|
||||
{{ dictConvert('LogBusinessType', row.businessType) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="operateIp" title="操作ip" />
|
||||
<vxe-column field="errorMsg" title="错误提示" />
|
||||
<vxe-column field="operateTime" title="操作时间" />
|
||||
<vxe-column fixed="right" width="60" :showOverflow="false" title="操作">
|
||||
<template #default="{ row }">
|
||||
<span>
|
||||
<a href="javascript:" @click="show(row)">查看</a>
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<OperateLogEdit ref="operateLogEdit" @ok="queryPage" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { page, deleteByDay } from './OperateLog.api'
|
||||
import useTablePage from '@/hooks/bootx/useTablePage'
|
||||
import OperateLogEdit from './OperateLogInfo.vue'
|
||||
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { QueryField } from '@/components/Bootx/Query/Query'
|
||||
import { useDict } from '@/hooks/bootx/useDict'
|
||||
import { LabeledValue } from 'ant-design-vue/lib/select'
|
||||
|
||||
// 使用hooks
|
||||
const {
|
||||
handleTableChange,
|
||||
pageQueryResHandel,
|
||||
resetQueryParams,
|
||||
pagination,
|
||||
pages,
|
||||
model,
|
||||
loading,
|
||||
} = useTablePage(queryPage)
|
||||
const { createMessage, createConfirm } = useMessage()
|
||||
const { dictConvert } = useDict()
|
||||
|
||||
const deleteDay = ref<any>(undefined)
|
||||
// 删除条件
|
||||
let deleteDays = ref<LabeledValue[]>([
|
||||
{ label: '3天之前', value: '3' },
|
||||
{ label: '7天之前', value: '7' },
|
||||
{ label: '30天之前', value: '30' },
|
||||
{ label: '60天之前', value: '60' },
|
||||
{ label: '90天之前', value: '90' },
|
||||
{ label: '180天之前', value: '180' },
|
||||
{ label: '365天之前', value: '365' },
|
||||
])
|
||||
// 查询条件
|
||||
const fields = [
|
||||
{ field: 'title', type: 'string', name: '操作模块', placeholder: '请输入操作模块' },
|
||||
{ field: 'username', type: 'string', name: '账号', placeholder: '请输入账号名称' },
|
||||
] as QueryField[]
|
||||
|
||||
const xTable = ref<VxeTableInstance>()
|
||||
const xToolbar = ref<VxeToolbarInstance>()
|
||||
const operateLogEdit = ref<any>()
|
||||
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
queryPage()
|
||||
})
|
||||
function vxeBind() {
|
||||
xTable.value?.connect(xToolbar.value as VxeToolbarInstance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
function queryPage() {
|
||||
loading.value = true
|
||||
page({
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
}).then(({ data }) => {
|
||||
pageQueryResHandel(data)
|
||||
})
|
||||
return Promise.resolve()
|
||||
}
|
||||
/**
|
||||
* 查看
|
||||
*/
|
||||
function show(record) {
|
||||
operateLogEdit.value.show(record.id)
|
||||
}
|
||||
/**
|
||||
* 清理日志
|
||||
*/
|
||||
function deleteLogs() {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '警告',
|
||||
content: '是否清除指定日期前的日志,该操作不可撤回',
|
||||
onOk: async () => {
|
||||
createMessage.info('清理日志中...')
|
||||
deleteByDay(deleteDay).then(() => {
|
||||
createMessage.success('清理日志成功')
|
||||
queryPage()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
@@ -13,6 +13,7 @@
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
validate-trigger="['blur', 'change']"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
|
@@ -56,7 +56,7 @@ export const del = (id) => {
|
||||
* 查询全部
|
||||
*/
|
||||
export const findAll = () => {
|
||||
return defHttp.get<Result<Array<Client>>>({
|
||||
return defHttp.get<Result<Client[]>>({
|
||||
url: '/client/findAll',
|
||||
})
|
||||
}
|
||||
|
@@ -21,7 +21,11 @@
|
||||
<a-input v-model:value="form.id" :disabled="showable" />
|
||||
</a-form-item>
|
||||
<a-form-item label="编码" validate-first name="code">
|
||||
<a-input v-model:value="form.code" :disabled="showable" placeholder="请输入编码" />
|
||||
<a-input
|
||||
v-model:value="form.code"
|
||||
:disabled="showable || form.internal"
|
||||
placeholder="请输入编码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" validate-first name="name">
|
||||
<a-input v-model:value="form.name" :disabled="showable" placeholder="请输入名称" />
|
||||
|
@@ -12,6 +12,7 @@
|
||||
class="small-from-item"
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
validate-trigger="['blur', 'change']"
|
||||
:rules="rules"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
|
@@ -13,6 +13,7 @@
|
||||
ref="formRef"
|
||||
class="small-from-item"
|
||||
:model="form"
|
||||
validate-trigger="['blur', 'change']"
|
||||
:rules="rules"
|
||||
:labelCol="labelCol"
|
||||
:wrapperCol="wrapperCol"
|
||||
|
@@ -99,7 +99,7 @@ export interface Role extends BaseEntity {
|
||||
// 编码
|
||||
code?: string
|
||||
// 父ID
|
||||
pid?: number
|
||||
pid?: string
|
||||
// 名称
|
||||
name?: string
|
||||
// 是否系统内置
|
||||
|
@@ -19,7 +19,7 @@
|
||||
:checkable="true"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
:auto-expand-parent="true"
|
||||
:tree-data="treeData"
|
||||
@check="onCheck"
|
||||
@expand="onExpand"
|
||||
@@ -81,7 +81,6 @@
|
||||
let expandedKeys = ref<string[]>([])
|
||||
// 被选中的key
|
||||
let checkedKeys = ref<string[]>([])
|
||||
let autoExpandParent = ref(false)
|
||||
//权限码树信息
|
||||
let treeData = ref<Tree[]>([])
|
||||
let treeList = ref<PermCodeTree[]>([])
|
||||
@@ -182,7 +181,7 @@
|
||||
expandedKeys.value = treeList.value
|
||||
.map((node) => {
|
||||
if (
|
||||
searchName &&
|
||||
searchName.value &&
|
||||
node.pid &&
|
||||
XEUtils.toValueString(node.name)?.toLowerCase()?.indexOf(value) > -1
|
||||
) {
|
||||
@@ -219,7 +218,6 @@
|
||||
*/
|
||||
function onExpand(keys) {
|
||||
expandedKeys.value = keys
|
||||
autoExpandParent.value = false
|
||||
}
|
||||
/**
|
||||
* 点击复选框触发
|
||||
|
@@ -12,6 +12,7 @@
|
||||
class="small-from-item"
|
||||
:model="form"
|
||||
ref="formRef"
|
||||
validate-trigger="['blur', 'change']"
|
||||
:rules="rules"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
|
@@ -20,7 +20,7 @@
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
:checkStrictly="checkStrictly"
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
:auto-expand-parent="false"
|
||||
:tree-data="treeData"
|
||||
@check="onCheck"
|
||||
@expand="onExpand"
|
||||
@@ -94,7 +94,6 @@
|
||||
let expandedKeys = ref<string[]>([])
|
||||
// 被选中的key
|
||||
let checkedKeys = ref<string[]>([])
|
||||
let autoExpandParent = ref(false)
|
||||
//菜单树信息
|
||||
let treeData = ref<Tree[]>([])
|
||||
let treeList = ref<MenuTree[]>([])
|
||||
@@ -208,7 +207,7 @@
|
||||
expandedKeys.value = treeList.value
|
||||
.map((node) => {
|
||||
if (
|
||||
searchName &&
|
||||
searchName.value &&
|
||||
node.pid &&
|
||||
XEUtils.toValueString(node.title).toLowerCase().indexOf(value) > -1
|
||||
) {
|
||||
@@ -245,7 +244,6 @@
|
||||
*/
|
||||
function onExpand(keys) {
|
||||
expandedKeys.value = keys
|
||||
autoExpandParent.value = false
|
||||
}
|
||||
/**
|
||||
* 点击复选框触发
|
||||
|
@@ -19,7 +19,7 @@
|
||||
:checkable="true"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
:auto-expand-parent="true"
|
||||
:tree-data="treeData"
|
||||
@check="onCheck"
|
||||
@expand="onExpand"
|
||||
@@ -91,7 +91,6 @@
|
||||
let expandedKeys = ref<string[]>([])
|
||||
// 被选中的key
|
||||
let checkedKeys = ref<string[]>([])
|
||||
let autoExpandParent = ref(false)
|
||||
//请求路径树信息
|
||||
let treeData = ref<Tree[]>([])
|
||||
let treeList = ref<PermPathTree[]>([])
|
||||
@@ -205,7 +204,7 @@
|
||||
expandedKeys.value = treeList.value
|
||||
.map((node) => {
|
||||
if (
|
||||
searchName &&
|
||||
searchName.value &&
|
||||
node.pid &&
|
||||
XEUtils.toValueString(node.title).toLowerCase().indexOf(value) > -1
|
||||
) {
|
||||
@@ -213,7 +212,6 @@
|
||||
}
|
||||
})
|
||||
.filter((item, i, self) => item && self.indexOf(item) === i) as string[]
|
||||
console.log(expandedKeys.value)
|
||||
}
|
||||
/**
|
||||
* 渲染搜索项目数据开始段
|
||||
@@ -243,8 +241,6 @@
|
||||
*/
|
||||
function onExpand(keys) {
|
||||
expandedKeys.value = keys
|
||||
console.log(expandedKeys)
|
||||
autoExpandParent.value = false
|
||||
}
|
||||
/**
|
||||
* 点击复选框触发
|
||||
|
@@ -56,7 +56,7 @@ export function findAll() {
|
||||
export function restartPassword(userId, newPassword) {
|
||||
return defHttp.post({
|
||||
url: '/user/admin/restartPassword',
|
||||
params: { userId, newPassword },
|
||||
data: { userId, newPassword },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -66,8 +66,7 @@ export function restartPassword(userId, newPassword) {
|
||||
export function restartPasswordBatch(userIds, newPassword) {
|
||||
return defHttp.post({
|
||||
url: '/user/admin/restartPasswordBatch',
|
||||
data: userIds,
|
||||
params: { newPassword },
|
||||
data: { userIds, newPassword },
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -5,20 +5,20 @@ import { Role } from '@/views/iam/role/Role.api'
|
||||
/**
|
||||
* 获取用户拥有角色id集合
|
||||
*/
|
||||
export function getRoleIds(id) {
|
||||
export function getRoleIds(userId) {
|
||||
return defHttp.get<Result<string[]>>({
|
||||
url: `/user/role/findRoleIdsByUser`,
|
||||
params: { id },
|
||||
params: { userId },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户拥有角色集合
|
||||
*/
|
||||
export function getRoles(id) {
|
||||
export function getRoles(userId) {
|
||||
return defHttp.get<Result<Role[]>>({
|
||||
url: `/user/role/findRolesByUser`,
|
||||
params: { id },
|
||||
params: { userId },
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -22,12 +22,12 @@
|
||||
<a-menu-item>
|
||||
<a @click="assignRolesBatch()">角色分配</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a @click="lockUserConfirmBatch(true)">锁定账号</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a @click="lockUserConfirmBatch(false)">解锁账号</a>
|
||||
</a-menu-item>
|
||||
<!-- <a-menu-item>-->
|
||||
<!-- <a @click="lockUserConfirmBatch(true)">锁定账号</a>-->
|
||||
<!-- </a-menu-item>-->
|
||||
<!-- <a-menu-item>-->
|
||||
<!-- <a @click="lockUserConfirmBatch(false)">解锁账号</a>-->
|
||||
<!-- </a-menu-item>-->
|
||||
<a-menu-item>
|
||||
<a @click="resetPwdBatch()">重置密码</a>
|
||||
</a-menu-item>
|
||||
@@ -74,12 +74,6 @@
|
||||
<a-menu-item>
|
||||
<a-link @click="assignRoles(row)">角色分配</a-link>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-link @click="assignDept(row)">部门分配</a-link>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-link @click="assignDataScope(row)">数据角色分配</a-link>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a-link @click="resetPwd(row)">重置密码</a-link>
|
||||
</a-menu-item>
|
||||
@@ -108,6 +102,8 @@
|
||||
<UserAdd ref="userAdd" @ok="queryPage" />
|
||||
<UserEdit ref="userEdit" @ok="queryPage" />
|
||||
<UserShow ref="userShow" />
|
||||
<UserRoleAssign ref="userRoleAssign" />
|
||||
<UserResetPwd ref="userResetPwd" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -125,7 +121,9 @@
|
||||
import UserAdd from './UserAdd.vue'
|
||||
import UserEdit from './UserEdit.vue'
|
||||
import UserShow from './UserShow.vue'
|
||||
import ALink from "@/components/Link/Link.vue";
|
||||
import UserResetPwd from './UserResetPwd.vue'
|
||||
import UserRoleAssign from './role/UserRoleAssign.vue'
|
||||
import ALink from '@/components/Link/Link.vue'
|
||||
|
||||
// 使用hooks
|
||||
const {
|
||||
@@ -152,13 +150,11 @@
|
||||
let userEdit = ref<any>()
|
||||
let userShow = ref<any>()
|
||||
let userRoleAssign = ref<any>()
|
||||
let userRoleAssignBatch = ref<any>()
|
||||
let userDataScopeAssign = ref<any>()
|
||||
let userDataScopeAssignBatch = ref<any>()
|
||||
let userDeptAssign = ref<any>()
|
||||
let userDeptAssignBatch = ref<any>()
|
||||
let userResetPwd = ref<any>()
|
||||
let userResetPwdBatch = ref<any>()
|
||||
|
||||
onMounted(() => {
|
||||
vxeBind()
|
||||
@@ -235,30 +231,12 @@
|
||||
}
|
||||
// 分配角色
|
||||
function assignRoles(record) {
|
||||
userRoleAssign.value.init(record)
|
||||
userRoleAssign.value.init(false, record.id)
|
||||
}
|
||||
// 批量分配角色
|
||||
function assignRolesBatch() {
|
||||
const userIds = xTable.value?.getCheckboxRecords().map((o) => o.id)
|
||||
userRoleAssignBatch.value.init(userIds)
|
||||
}
|
||||
// 分配数据权限
|
||||
function assignDataScope(record) {
|
||||
userDataScopeAssign.value.init(record)
|
||||
}
|
||||
// 批量分配数据权限
|
||||
function assignDataScopeBatch() {
|
||||
const userIds = xTable.value?.getCheckboxRecords().map((o) => o.id)
|
||||
userDataScopeAssignBatch.value.init(userIds)
|
||||
}
|
||||
// 分配部门
|
||||
function assignDept(record) {
|
||||
userDeptAssign.value.init(record.id)
|
||||
}
|
||||
// 批量分配部门
|
||||
function assignDeptBatch() {
|
||||
const userIds = xTable.value?.getCheckboxRecords().map((o) => o.id)
|
||||
userDeptAssignBatch.value.init(userIds)
|
||||
userRoleAssign.value.init(true, userIds)
|
||||
}
|
||||
function add() {
|
||||
userAdd.value.init()
|
||||
@@ -279,14 +257,14 @@
|
||||
* 重置密码
|
||||
*/
|
||||
function resetPwd(record) {
|
||||
userResetPwd.value.init(record.id)
|
||||
userResetPwd.value.init(false, record.id)
|
||||
}
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
function resetPwdBatch() {
|
||||
const userIds = xTable.value?.getCheckboxRecords().map((o) => o.id)
|
||||
userResetPwdBatch.value.init(userIds)
|
||||
userResetPwd.value.init(true,userIds)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
87
src/views/iam/user/UserResetPwd.vue
Normal file
87
src/views/iam/user/UserResetPwd.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<basic-modal
|
||||
v-bind="$attrs"
|
||||
title="重置密码"
|
||||
:width="modalWidth"
|
||||
:open="visible"
|
||||
:confirmLoading="confirmLoading"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
:validate-trigger="['blur', 'change']"
|
||||
:label-col="labelCol"
|
||||
:wrapper-col="wrapperCol"
|
||||
>
|
||||
<a-form-item name="newPassword" label="重置密码">
|
||||
<a-input-password v-model:value="form.newPassword" placeholder="请输入密码" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</basic-modal>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import BasicModal from '@/components/Modal/src/BasicModal.vue'
|
||||
import useFormEdit from '@/hooks/bootx/useFormEdit'
|
||||
import { restartPassword, restartPasswordBatch } from './User.api'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { Rule } from 'ant-design-vue/lib/form'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { handleCancel, labelCol, wrapperCol, modalWidth, confirmLoading, visible } = useFormEdit()
|
||||
const { createConfirm, createMessage } = useMessage()
|
||||
|
||||
// 用户id
|
||||
const userId = ref('')
|
||||
// 用户ids
|
||||
const userIds = ref<string[]>([])
|
||||
|
||||
const batch = ref(false)
|
||||
let form = ref<any>({
|
||||
newPassword: '',
|
||||
})
|
||||
let formRef = ref<any>()
|
||||
|
||||
const rules = {
|
||||
newPassword: [{ required: true, message: '重置密码不得为空' }],
|
||||
} as Record<string, Rule[]>
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
function init(batch: boolean, userIdOrIds: string | string[]) {
|
||||
visible.value = true
|
||||
if (!batch) {
|
||||
userId.value = userIdOrIds as string
|
||||
} else {
|
||||
userIds.value = userIdOrIds as never[]
|
||||
}
|
||||
}
|
||||
|
||||
function handleOk() {
|
||||
formRef.value?.validate().then(async () => {
|
||||
createConfirm({
|
||||
iconType: 'info',
|
||||
title: '警告',
|
||||
content: '是否重置用户的密码',
|
||||
onOk: async () => {
|
||||
confirmLoading.value = true
|
||||
if (batch.value) {
|
||||
await restartPasswordBatch(userIds.value, form.value.newPassword)
|
||||
} else {
|
||||
await restartPassword(userId.value, form.value.newPassword)
|
||||
}
|
||||
createMessage.success('保存成功')
|
||||
handleCancel()
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
defineExpose({ init })
|
||||
</script>
|
||||
<style scoped lang="less"></style>
|
269
src/views/iam/user/role/UserRoleAssign.vue
Normal file
269
src/views/iam/user/role/UserRoleAssign.vue
Normal file
@@ -0,0 +1,269 @@
|
||||
<template>
|
||||
<basic-drawer
|
||||
showFooter
|
||||
v-bind="$attrs"
|
||||
:title="modal.title"
|
||||
width="40%"
|
||||
:open="modal.visible"
|
||||
@close="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="modal.loading">
|
||||
<a-input
|
||||
style="margin-bottom: 8px"
|
||||
placeholder="筛选"
|
||||
allowClear
|
||||
v-model:value="modal.searchName"
|
||||
@change="search"
|
||||
/>
|
||||
<a-tree
|
||||
:checkable="true"
|
||||
:checkStrictly="true"
|
||||
v-model:checkedKeys="modal.checkedKeys"
|
||||
v-model:expandedKeys="modal.expandedKeys"
|
||||
:auto-expand-parent="true"
|
||||
:tree-data="modal.treeData"
|
||||
@check="onCheck"
|
||||
@expand="onExpand"
|
||||
>
|
||||
<template #title="{ title }">
|
||||
<span v-if="title?.toLowerCase()?.indexOf(modal.searchName.toLowerCase()) > -1">
|
||||
{{ searchRenderStart(title, modal.searchName) }}
|
||||
<span style="color: #f50">
|
||||
{{ searchRenderMiddle(title, modal.searchName) }}
|
||||
</span>
|
||||
{{ searchRenderEnd(title, modal.searchName) }}
|
||||
</span>
|
||||
<span v-else>{{ title }}</span>
|
||||
</template>
|
||||
</a-tree>
|
||||
</a-spin>
|
||||
<template #footer>
|
||||
<a-dropdown style="margin-left: 5px" :trigger="['click']" placement="top">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="checkALL">全部勾选</a-menu-item>
|
||||
<a-menu-item key="2" @click="cancelCheckALL">取消全选</a-menu-item>
|
||||
<a-menu-item key="3" @click="expandAll">展开所有</a-menu-item>
|
||||
<a-menu-item key="4" @click="closeAll">合并所有</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button post-icon="ant-design:up-outlined"> 操作 </a-button>
|
||||
</a-dropdown>
|
||||
<a-button @click="modal.visible = false" style="margin-right: 0.8rem">取消</a-button>
|
||||
<a-button
|
||||
@click="handleSubmit()"
|
||||
type="primary"
|
||||
:loading="modal.loading"
|
||||
style="margin-right: 0.8rem"
|
||||
>保存</a-button
|
||||
>
|
||||
</template>
|
||||
</basic-drawer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { BasicDrawer } from '@/components/Drawer'
|
||||
import { reactive } from 'vue'
|
||||
import { Tree, treeDataTranslate } from '@/utils/dataUtil'
|
||||
import XEUtils from 'xe-utils'
|
||||
import { RoleTree, tree as roleTree } from '@/views/iam/role/Role.api'
|
||||
import { addUserRole, addUserRoleBatch, getRoleIds } from '@/views/iam/user/UserAssign.api'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
|
||||
const { createConfirm, createMessage } = useMessage()
|
||||
const modal = reactive({
|
||||
title: '角色分配',
|
||||
visible: false,
|
||||
batch: false,
|
||||
loading: false,
|
||||
searchName: '',
|
||||
// 所有的key
|
||||
allTreeKeys: [] as string[],
|
||||
// 展开的key
|
||||
expandedKeys: [] as string[],
|
||||
// 被选中的key
|
||||
checkedKeys: [] as string[],
|
||||
// 后台获取的角色树
|
||||
treeData: [] as Tree[],
|
||||
// 转换后的树数据
|
||||
treeList: [] as RoleTree[],
|
||||
// 用户id
|
||||
userId: '',
|
||||
// 用户ids
|
||||
userIds: [],
|
||||
// 角色Ids
|
||||
roleIds: [],
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
async function init(batch: boolean, userIdOrIds: string | string[]) {
|
||||
modal.visible = true
|
||||
modal.batch = batch
|
||||
modal.loading = true
|
||||
// 初始化角色树
|
||||
await initRoles()
|
||||
if (!batch) {
|
||||
modal.userId = userIdOrIds as string
|
||||
// 初始化分配角色
|
||||
await initAssign()
|
||||
} else {
|
||||
modal.userIds = userIdOrIds as never[]
|
||||
}
|
||||
modal.loading = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化菜单
|
||||
*/
|
||||
async function initRoles() {
|
||||
modal.searchName = ''
|
||||
modal.expandedKeys = []
|
||||
// 角色树
|
||||
await roleTree().then((res) => {
|
||||
modal.treeData = treeDataTranslate(res.data, 'id', 'name')
|
||||
generateTreeList(res.data)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化权限码分配信息
|
||||
*/
|
||||
async function initAssign() {
|
||||
// 当前用户已经选择的角色Id
|
||||
await getRoleIds(modal.userId).then((res) => {
|
||||
modal.checkedKeys = res.data
|
||||
})
|
||||
// 选中的的key值
|
||||
modal.allTreeKeys = modal.treeList.map((item) => item.id) as string[]
|
||||
}
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
function handleSubmit() {
|
||||
createConfirm({
|
||||
iconType: 'info',
|
||||
title: '警告',
|
||||
content: '是否要保存角色分配信息',
|
||||
onOk: async () => {
|
||||
modal.loading = true
|
||||
if (modal.batch) {
|
||||
await addUserRoleBatch({
|
||||
userIds: modal.userIds,
|
||||
roleIds: modal.checkedKeys,
|
||||
})
|
||||
} else {
|
||||
await addUserRole({
|
||||
userId: modal.userId,
|
||||
roleIds: modal.checkedKeys,
|
||||
})
|
||||
}
|
||||
createMessage.success('保存成功')
|
||||
modal.loading = false
|
||||
modal.visible = false
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
function handleCancel() {
|
||||
modal.visible = false
|
||||
}
|
||||
/**
|
||||
* 树数据铺平
|
||||
*/
|
||||
function generateTreeList(treeData) {
|
||||
if (!treeData) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < treeData.length; i++) {
|
||||
const node = treeData[i]
|
||||
modal.treeList.push(node)
|
||||
if (node.children) {
|
||||
generateTreeList(node.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
function search() {
|
||||
const value = XEUtils.toValueString(modal.searchName).toLowerCase()
|
||||
modal.expandedKeys = modal.treeList
|
||||
.map((node) => {
|
||||
if (
|
||||
modal.searchName &&
|
||||
node.pid &&
|
||||
XEUtils.toValueString(node.name)?.toLowerCase()?.indexOf(value) > -1
|
||||
) {
|
||||
return node.pid
|
||||
}
|
||||
})
|
||||
.filter((item, i, self) => item && self.indexOf(item) === i) as string[]
|
||||
}
|
||||
/**
|
||||
* 渲染搜索项目数据开始段
|
||||
*/
|
||||
function searchRenderStart(title, searchName) {
|
||||
return title.substring(0, title.toLowerCase().indexOf(searchName.toLowerCase()))
|
||||
}
|
||||
/**
|
||||
* 渲染搜索项目数据中间段
|
||||
*/
|
||||
function searchRenderMiddle(title, searchName) {
|
||||
return title.substring(
|
||||
title.toLowerCase().indexOf(searchName.toLowerCase()),
|
||||
title.toLowerCase().indexOf(searchName.toLowerCase()) + searchName.length,
|
||||
)
|
||||
}
|
||||
/**
|
||||
* 渲染搜索项目数据结束段
|
||||
*/
|
||||
function searchRenderEnd(title, searchName) {
|
||||
return title.substring(
|
||||
title.toLowerCase().indexOf(searchName.toLowerCase()) + searchName.length,
|
||||
)
|
||||
}
|
||||
/**
|
||||
* 展开/收起节点时触发
|
||||
*/
|
||||
function onExpand(keys) {
|
||||
modal.expandedKeys = keys
|
||||
}
|
||||
/**
|
||||
* 点击复选框触发
|
||||
*/
|
||||
function onCheck(key) {
|
||||
modal.checkedKeys = key.checked
|
||||
}
|
||||
/**
|
||||
* 展开全部
|
||||
*/
|
||||
function expandAll() {
|
||||
modal.expandedKeys = modal.allTreeKeys
|
||||
}
|
||||
/**
|
||||
* 合并全部
|
||||
*/
|
||||
function closeAll() {
|
||||
modal.expandedKeys = []
|
||||
}
|
||||
/**
|
||||
* 全选
|
||||
*/
|
||||
function checkALL() {
|
||||
modal.checkedKeys = modal.allTreeKeys
|
||||
}
|
||||
/**
|
||||
* 全不选
|
||||
*/
|
||||
function cancelCheckALL() {
|
||||
modal.checkedKeys = []
|
||||
}
|
||||
|
||||
defineExpose({ init })
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
Reference in New Issue
Block a user