Merge remote-tracking branch 'origin/master'
11 files modified
5 files added
| | |
| | | import request from '@/axios'; |
| | | |
| | | export const getList = (current, size, params, deptId) => { |
| | | export const getList = (current, size,sysType, params, deptId) => { |
| | | return request({ |
| | | url: '/blade-system/user/page', |
| | | method: 'get', |
| | |
| | | ...params, |
| | | current, |
| | | size, |
| | | sysType, |
| | | deptId, |
| | | }, |
| | | }); |
| | |
| | | @stage-change="handleStageChange" /> |
| | | <div v-if="props.showLayerControl" class="layer-control-root" :class="{ collapsed: props.rightCollapsed }"> |
| | | <div class="layer-control-wrap" ref="layerWrapRef"> |
| | | <div class="layer-control" @click="toggleLayerPanel"> |
| | | <div class="layer-control" @click.stop="toggleLayerPanel"> |
| | | <img :src="layerControlIcon" alt="图层控制" /> |
| | | </div> |
| | | <div v-if="showLayerPanel" class="layer-panel"> |
| | | <div class="panel-title">底图切换</div> |
| | | <div class="base-map-options"> |
| | | <div class="base-map-card" :class="{ active: baseLayerKey === 'base-standard' }" |
| | | @click="handleBaseLayerSelect('base-standard')"> |
| | | <img class="base-map-thumb standard" :src="dzIcon" alt=""> |
| | | <div class="base-map-label">标准地图</div> |
| | | </div> |
| | | <div class="base-map-card" :class="{ active: baseLayerKey === 'base-satellite' }" |
| | | @click="handleBaseLayerSelect('base-satellite')"> |
| | | <img class="base-map-thumb satellite" :src="yxIcon" alt=""> |
| | | <div class="base-map-label">卫星地图</div> |
| | | <transition name="layer-panel-slide"> |
| | | <div v-if="showLayerPanel" class="layer-panel"> |
| | | <div class="panel-title">图层管理</div> |
| | | <div class="panel-content"> |
| | | <el-tree ref="layerTreeRef" class="command-tree map-layer-tree" :data="layerTree" |
| | | icon="el-icon-arrow-down-bold" |
| | | show-checkbox default-expand-all node-key="key" :props="layerTreeProps" |
| | | :default-checked-keys="treeCheckedKeys" @check="handleLayerCheck" /> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="panel-title">图层管理</div> |
| | | <div class="panel-content"> |
| | | <el-tree ref="layerTreeRef" class="command-tree map-layer-tree" :data="layerTree" show-checkbox |
| | | default-expand-all node-key="key" :props="layerTreeProps" |
| | | :default-checked-keys="treeCheckedKeys" @check="handleLayerCheck" /> |
| | | </div> |
| | | </transition> |
| | | </div> |
| | | </div> |
| | | <div v-if="props.showLayerControl" class="base-layer-switch-root" :class="{ collapsed: props.rightCollapsed }"> |
| | | <div class="base-layer-switch-wrap" @mouseenter="showBaseLayerPanel = true" |
| | | @mouseleave="showBaseLayerPanel = false"> |
| | | <div class="base-layer-trigger"> |
| | | <img class="base-layer-trigger-thumb" :src="currentBaseLayer.icon" :alt="currentBaseLayer.label"> |
| | | <div class="base-layer-trigger-label">{{ currentBaseLayer.shortLabel }}</div> |
| | | </div> |
| | | <transition name="layer-panel-slide"> |
| | | <div v-if="showBaseLayerPanel" class="base-layer-panel"> |
| | | <div class="base-map-options"> |
| | | <div class="base-map-card" :class="{ active: baseLayerKey === 'base-satellite' }" |
| | | @click="handleBaseLayerSelect('base-satellite')"> |
| | | <img class="base-map-thumb" :src="yxIcon" alt=""> |
| | | <div class="base-map-label">卫星地图</div> |
| | | </div> |
| | | <div class="base-map-card" :class="{ active: baseLayerKey === 'base-standard' }" |
| | | @click="handleBaseLayerSelect('base-standard')"> |
| | | <img class="base-map-thumb" :src="dzIcon" alt=""> |
| | | <div class="base-map-label">标准地图</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </transition> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | |
| | | import * as Cesium from 'cesium' |
| | | import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue' |
| | | import { buildEllipsePositions } from '@/utils/cesium/shapeTools' |
| | |
| | | const clusterVisible = ref(false) |
| | | const countyCenterMap = new Map() |
| | | const showLayerPanel = ref(false) |
| | | const showBaseLayerPanel = ref(false) |
| | | const layerWrapRef = ref(null) |
| | | const layerTreeRef = ref(null) |
| | | const selectedDevice = ref(null) |
| | |
| | | const baseLayerKeys = ['base-standard', 'base-satellite'] |
| | | const defaultCheckedKeys = ['ja-terrain', 'admin', 'city-base'] |
| | | const baseLayerKey = ref('base-satellite') |
| | | const baseLayerMeta = { |
| | | 'base-standard': { icon: dzIcon, label: '标准地图', shortLabel: '标准' }, |
| | | 'base-satellite': { icon: yxIcon, label: '卫星地图', shortLabel: '影像' }, |
| | | } |
| | | const currentBaseLayer = computed(() => baseLayerMeta[baseLayerKey.value] || baseLayerMeta['base-satellite']) |
| | | const treeCheckedKeys = ref([...defaultCheckedKeys]) |
| | | const layerTree = ref([ |
| | | { |
| | |
| | | watch( |
| | | () => props.rightCollapsed, |
| | | isCollapsed => { |
| | | if (isCollapsed) showLayerPanel.value = false |
| | | if (!isCollapsed) return |
| | | showLayerPanel.value = false |
| | | showBaseLayerPanel.value = false |
| | | } |
| | | ) |
| | | |
| | |
| | | setDroneVisibility(!showCluster) |
| | | } |
| | | |
| | | const handleMapReady = async ({ viewer: mapViewer, publicCesium: mapPublic }) => { |
| | | const handleMapReady = async ({ viewer: mapViewer, publicCesium: mapPublic }) => { |
| | | if (mapReadyHandled) return |
| | | mapReadyHandled = true |
| | | viewer = mapViewer |
| | |
| | | updateStageDisplay(stage) |
| | | } |
| | | |
| | | const handleClickOutside = event => { |
| | | const handleLayerClickOutside = event => { |
| | | if (!showLayerPanel.value) return |
| | | const target = event.target |
| | | if (layerWrapRef.value?.contains(target)) return |
| | |
| | | } |
| | | |
| | | onMounted(() => { |
| | | document.addEventListener('click', handleClickOutside) |
| | | document.addEventListener('click', handleLayerClickOutside) |
| | | const map = mapRef.value?.getMap() |
| | | if (map?.viewer) handleMapReady(map) |
| | | }) |
| | | |
| | | onBeforeUnmount(() => { |
| | | document.removeEventListener('click', handleClickOutside) |
| | | document.removeEventListener('click', handleLayerClickOutside) |
| | | clearDeviceEntities() |
| | | clearPartitionEntities() |
| | | clearAggregationEntities() |
| | |
| | | overflow: auto; |
| | | } |
| | | |
| | | .base-map-title { |
| | | margin-bottom: 8px; |
| | | font-size: 12px; |
| | | color: #ffffff; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | |
| | | .base-map-options { |
| | | padding: 16px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, minmax(0, 1fr)); |
| | | gap: 8px; |
| | | } |
| | | .base-layer-switch-root { |
| | | position: absolute; |
| | | right: 337px; |
| | | bottom: 78px; |
| | | z-index: 11; |
| | | transition: transform 0.3s ease-in-out; |
| | | pointer-events: none; |
| | | |
| | | .base-map-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 6px; |
| | | &.collapsed { |
| | | transform: translateX(317px); |
| | | } |
| | | } |
| | | |
| | | .base-layer-switch-wrap { |
| | | position: relative; |
| | | pointer-events: auto; |
| | | } |
| | | |
| | | .base-layer-trigger { |
| | | width: 55px; |
| | | padding: 8px 0; |
| | | border-radius: 8px; |
| | | background: #191932; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 6px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .base-layer-trigger-thumb { |
| | | width: 36px; |
| | | height: 36px; |
| | | border-radius: 6px; |
| | | display: block; |
| | | // border: 2px solid #fff; |
| | | background-size: cover; |
| | | background-position: center; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .base-layer-trigger-label { |
| | | margin-top: 8px; |
| | | font-size: 12px; |
| | | line-height: 1; |
| | | color: #ffffff; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .base-layer-panel { |
| | | position: absolute; |
| | | right: calc(100% + 10px); |
| | | bottom: 0; |
| | | margin-bottom: 0; |
| | | width: 160px; |
| | | background: #191932; |
| | | border-radius: 8px; |
| | | z-index: 99; |
| | | |
| | | &::after { |
| | | content: ''; |
| | | position: absolute; |
| | | right: -10px; |
| | | top: 0; |
| | | width: 10px; |
| | | height: 100%; |
| | | background: transparent; |
| | | } |
| | | } |
| | | |
| | | .base-map-options { |
| | | padding: 8px; |
| | | display: grid; |
| | | grid-template-columns: repeat(2, minmax(0, 1fr)); |
| | | gap: 8px; |
| | | } |
| | | |
| | | .base-map-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 6px; |
| | | border-radius: 6px; |
| | | color: #d8e6ff; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | |
| | | .base-map-thumb { |
| | | width: 36px; |
| | | height: 36px; |
| | | border-radius: 6px; |
| | | color: #d8e6ff; |
| | | font-size: 12px; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | |
| | | .base-map-thumb { |
| | | width: 46px; |
| | | height: 46px; |
| | | border-radius: 4px; |
| | | background-size: cover; |
| | | background-position: center; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | &.active { |
| | | .base-map-thumb { |
| | | border: 2px solid #2ea8ff; |
| | | } |
| | | |
| | | .base-map-label { |
| | | color: #2ea8ff; |
| | | } |
| | | } |
| | | // border: 2px solid #fff; |
| | | background-size: cover; |
| | | background-position: center; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .base-map-label { |
| | | margin-top: 8px; |
| | | font-size: 12px; |
| | | line-height: 1; |
| | | color: #ffffff; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | |
| | | // &.active { |
| | | // .base-map-thumb { |
| | | // border: 2px solid #2ea8ff; |
| | | // } |
| | | |
| | | // .base-map-label { |
| | | // color: #2ea8ff; |
| | | // } |
| | | // } |
| | | } |
| | | |
| | | .layer-panel-slide-enter-active, |
| | | .layer-panel-slide-leave-active { |
| | | transition: transform 0.24s ease, opacity 0.24s ease; |
| | | transform-origin: right center; |
| | | } |
| | | |
| | | .layer-panel-slide-enter-from, |
| | | .layer-panel-slide-leave-to { |
| | | transform: translateX(24px); |
| | | opacity: 0; |
| | | } |
| | | </style> |
| | |
| | | .el-tree-node__expand-icon.is-leaf { |
| | | visibility: hidden; |
| | | } |
| | | |
| | | .el-tree-node__expand-icon.expanded { |
| | | transform: rotate(-180deg); |
| | | } |
| | | } |
| | | |
| | | .command-cascader { |
| | |
| | | parentId: '', |
| | | parentName: '', |
| | | sort: 0, |
| | | sysType: 5 |
| | | }) |
| | | |
| | | const treeProps = { |
| | |
| | | const initSearchParams = () => ({ |
| | | roleName: '', |
| | | roleAlias: '', |
| | | sysType: 5 |
| | | }) |
| | | |
| | | const searchParams = ref(initSearchParams()) |
| | |
| | | code: '', |
| | | roleId: '', |
| | | deptId: '', |
| | | sysType: 5 |
| | | }) |
| | | |
| | | const treeProps = { |
| | |
| | | deptId: '', |
| | | current: 1, |
| | | size: 10, |
| | | sysType: 5, |
| | | }) |
| | | |
| | | const searchParams = ref(initSearchParams()) |
| | |
| | | const res = await getUserList( |
| | | searchParams.value.current, |
| | | searchParams.value.size, |
| | | searchParams.value.sysType, |
| | | { |
| | | account: searchParams.value.account, |
| | | realName: searchParams.value.realName, |
| | |
| | | }); |
| | | }; |
| | | |
| | | export const getRoleListNew = (params) => { |
| | | return request({ |
| | | url: '/blade-system/role/list', |
| | | method: 'get', |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | export const getRoleList = ( params) => { |
| | | return request({ |
| | | url: '/blade-system/role/getRoleList', |
| | |
| | | import request from '@/axios'; |
| | | |
| | | export const getList = (current, size, params, deptId) => { |
| | | export const getList = (current, size, sysType, params, deptId) => { |
| | | return request({ |
| | | url: '/blade-system/user/page', |
| | | method: 'get', |
| | |
| | | ...params, |
| | | current, |
| | | size, |
| | | sysType, |
| | | deptId, |
| | | }, |
| | | }); |
| | |
| | | $search-item-symbol-bg: #fff; |
| | | $search-item-symbol-txt: #4E5969; |
| | | |
| | | .gd-input { |
| | | .gd-input, |
| | | .gd-input-text { |
| | | --bg: #{$form-bg}; |
| | | --tips: #{$form-tips}; |
| | | |
| | |
| | | > |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="标题" prop="title"> |
| | | <el-form-item label="标题" prop="title" :label-width="pxToRem(80)"> |
| | | <el-input class="gd-input" v-model="formData.title" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="提出部门" prop="proposeDeptId"> |
| | | <el-form-item label="提出部门" prop="proposeDeptId" :label-width="pxToRem(80)"> |
| | | <el-tree-select class="gd-select" popper-class="gd-tree-select-popper" |
| | | v-model="formData.proposeDeptId" node-key="id" :data="deptTree" :props="treeProps" |
| | | check-strictly clearable /> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="评分" prop="score"> |
| | | <el-form-item label="评分" prop="score" :label-width="pxToRem(80)"> |
| | | <el-input-number class="gd-input" v-model="formData.score" :min="1" :max="10" placeholder="请输入" |
| | | controls-position="right" /> |
| | | </el-form-item> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="评价内容" prop="evaluationContent"> |
| | | <el-form-item label="评价内容" prop="evaluationContent" :label-width="pxToRem(80)"> |
| | | <el-input class="gd-input-text" v-model="formData.evaluationContent" type="textarea" :rows="4" |
| | | placeholder="请输入" clearable /> |
| | | </el-form-item> |
| New file |
| | |
| | | <template> |
| | | <el-dialog class="gd-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close |
| | | :close-on-click-modal="false"> |
| | | <!-- <div class="detail-row-view" v-if="dialogReadonly">--> |
| | | <el-row class="detail-row-view" v-if="dialogReadonly"> |
| | | <el-col :span="12"> |
| | | <div class="label">角色名称</div> |
| | | <div class="val">{{ formData.roleName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">角色别名</div> |
| | | <div class="val">{{ formData.roleAlias }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">上级角色</div> |
| | | <div class="val">{{ formData.parentName || '-' }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">角色排序</div> |
| | | <div class="val">{{ formData.sort }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- </div>--> |
| | | |
| | | <el-form class="gd-dialog-form" v-else ref="formRef" :model="formData" :rules="rules" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="角色名称" prop="roleName"> |
| | | <el-input class="gd-input" v-model="formData.roleName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="角色别名" prop="roleAlias"> |
| | | <el-input class="gd-input" v-model="formData.roleAlias" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="上级角色" prop="parentId"> |
| | | <el-tree-select |
| | | class="gd-select" |
| | | popper-class="gd-tree-select-popper" |
| | | v-model="formData.parentId" |
| | | :data="roleTree" |
| | | :props="treeProps" |
| | | node-key="id" |
| | | check-strictly |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="角色排序" prop="sort"> |
| | | <el-input-number class="gd-input" v-model="formData.sort" :min="0" :controls="false" placeholder="请输入" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <el-button v-if="dialogMode != 'view'" color="#F2F3F5" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#4C34FF" v-if="!dialogReadonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 保存 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { add, getRoleTreeById, update } from '@/api/system/role' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { saveOperationLog } from '@ztzf/apis' |
| | | import { useRoute } from 'vue-router' |
| | | |
| | | const initForm = () => ({ |
| | | roleName: '', |
| | | roleAlias: '', |
| | | parentId: '', |
| | | parentName: '', |
| | | sort: 0, |
| | | sysType: 6 |
| | | }) |
| | | |
| | | const treeProps = { |
| | | label: 'title', |
| | | children: 'children', |
| | | value: 'id', |
| | | } |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) |
| | | const formData = ref(initForm()) |
| | | const visible = ref(false) |
| | | const dialogMode = ref('add') |
| | | const submitting = ref(false) |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const route = useRoute() |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') return '编辑' |
| | | if (dialogMode.value === 'view') return '查看' |
| | | return '新增' |
| | | }) |
| | | const roleTree = ref([]) |
| | | |
| | | const rules = { |
| | | roleName: fieldRules(true, 50), |
| | | roleAlias: fieldRules(true, 50), |
| | | parentId: fieldRules(false), |
| | | sort: fieldRules(true), |
| | | } |
| | | |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | if (dialogMode.value === 'edit') { |
| | | await update(formData.value) |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '角色管理'}-编辑`, |
| | | type: 1, |
| | | }) |
| | | } else { |
| | | await add(formData.value) |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '角色管理'}-新增`, |
| | | type: 1, |
| | | }) |
| | | } |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | async function loadRoleTree(roleId) { |
| | | const res = await getRoleTreeById(roleId) |
| | | roleTree.value = res?.data?.data ?? [] |
| | | } |
| | | |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | await loadRoleTree() |
| | | return |
| | | } |
| | | formData.value = { ...row } |
| | | await loadRoleTree(row?.id) |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <el-dialog |
| | | class="command-page-view-dialog" |
| | | v-model="visible" |
| | | title="角色权限配置" |
| | | append-to-body |
| | | :close-on-click-modal="false" |
| | | destroy-on-close |
| | | @closed="handleClosed" |
| | | > |
| | | <el-tabs type="border-card"> |
| | | <!-- <el-tab-pane label="无人机管控">--> |
| | | <!-- <el-tree--> |
| | | <!-- class="command-tree"--> |
| | | <!-- ref="droneControl"--> |
| | | <!-- :data="menuGrantListDroneControl"--> |
| | | <!-- show-checkbox--> |
| | | <!-- node-key="id"--> |
| | | <!-- :default-checked-keys="droneControlMenuTreeObj"--> |
| | | <!-- :props="treeProps"--> |
| | | <!-- />--> |
| | | <!-- </el-tab-pane>--> |
| | | <el-tab-pane label="任务工单"> |
| | | <el-tree |
| | | class="command-tree" |
| | | ref="workRef" |
| | | :data="menuGrantListWord" |
| | | show-checkbox |
| | | node-key="id" |
| | | :default-checked-keys="menuTreeObjWork" |
| | | :props="treeProps" |
| | | /> |
| | | </el-tab-pane> |
| | | <!-- <el-tab-pane label="移动app">--> |
| | | <!-- <el-tree--> |
| | | <!-- class="command-tree"--> |
| | | <!-- ref="treeMenuApp"--> |
| | | <!-- :data="menuGrantListApp"--> |
| | | <!-- show-checkbox--> |
| | | <!-- node-key="id"--> |
| | | <!-- :default-checked-keys="menuTreeObjApp"--> |
| | | <!-- :props="treeProps"--> |
| | | <!-- />--> |
| | | <!-- </el-tab-pane>--> |
| | | </el-tabs> |
| | | <template #footer> |
| | | <el-button color="#F2F3F5" @click="visible = false">取消</el-button> |
| | | <el-button color="#4C34FF" type="primary" @click="submit">确定</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { grant, grantTree, getRole } from '@/api/system/role' |
| | | import { saveOperationLog } from '@ztzf/apis' |
| | | import { useRoute } from 'vue-router' |
| | | |
| | | const visible = ref(false) |
| | | const roleId = ref('') |
| | | const treeProps = { |
| | | label: 'title', |
| | | value: 'key', |
| | | } |
| | | const menuGrantListApp = ref([]) |
| | | const menuGrantListDroneControl = ref([]) |
| | | const menuGrantListWord = ref([]) |
| | | const menuTreeObjApp = ref([]) |
| | | const droneControlMenuTreeObj = ref([]) |
| | | const menuTreeObjWork = ref([]) |
| | | |
| | | const treeMenuApp = ref(null) |
| | | const workRef = ref(null) |
| | | const droneControl = ref(null) |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const route = useRoute() |
| | | |
| | | function resetState() { |
| | | menuGrantListApp.value = [] |
| | | menuGrantListDroneControl.value = [] |
| | | menuGrantListWord.value = [] |
| | | menuTreeObjApp.value = [] |
| | | droneControlMenuTreeObj.value = [] |
| | | menuTreeObjWork.value = [] |
| | | } |
| | | |
| | | async function loadGrantTree(sysType, setter, keysSetter) { |
| | | const grantRes = await grantTree({ sysType }) |
| | | setter.value = grantRes?.data?.data?.menu ?? [] |
| | | const roleRes = await getRole(roleId.value) |
| | | keysSetter.value = roleRes?.data?.data?.menu ?? [] |
| | | } |
| | | |
| | | async function open({ roleId: id } = {}) { |
| | | roleId.value = id || '' |
| | | visible.value = true |
| | | resetState() |
| | | await Promise.all([ |
| | | loadGrantTree(3, menuGrantListApp, menuTreeObjApp), |
| | | loadGrantTree(5, menuGrantListDroneControl, droneControlMenuTreeObj), |
| | | loadGrantTree(6, menuGrantListWord, menuTreeObjWork), |
| | | ]) |
| | | } |
| | | |
| | | function submit() { |
| | | const menuListApp = treeMenuApp.value?.getCheckedKeys?.() ?? [] |
| | | const menuListWebWork = workRef.value?.getCheckedKeys?.() ?? [] |
| | | const menuListDroneControl = droneControl.value?.getCheckedKeys?.() ?? [] |
| | | grant( |
| | | [roleId.value], |
| | | [...menuListApp, ...menuListDroneControl, ...menuListWebWork], |
| | | [], |
| | | [] |
| | | ).then(() => { |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '角色管理'}-权限设置`, |
| | | type: 1, |
| | | }) |
| | | visible.value = false |
| | | emit('success') |
| | | }) |
| | | } |
| | | |
| | | function handleClosed() { |
| | | resetState() |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form"> |
| | | <el-form-item label="角色名称" prop="roleName"> |
| | | <el-input |
| | | class="gd-input gray" |
| | | v-model="searchParams.roleName" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="角色别名" prop="roleAlias"> |
| | | <el-input |
| | | class="gd-input gray" |
| | | v-model="searchParams.roleAlias" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item class="gd-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <el-button :icon="Plus" color="#4C34FF" type="primary" @click="handleAdd">新增</el-button> |
| | | <el-button :icon="Delete" :disabled="!selectedIds.length" @click="handleDelete()"> |
| | | 删除 |
| | | </el-button> |
| | | <el-button |
| | | :disabled="selectedIds.length !== 1" |
| | | v-if="permission.orderRole_set" |
| | | @click="handleRole" |
| | | > |
| | | 权限设置 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <div class="gd-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | | <div class="gd-table-content gd-table-content-bg"> |
| | | <el-table |
| | | class="gd-table" |
| | | :data="list" |
| | | row-key="id" |
| | | :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="roleName" show-overflow-tooltip label="角色名称" /> |
| | | <el-table-column prop="roleAlias" show-overflow-tooltip label="角色别名" /> |
| | | <el-table-column prop="sort" show-overflow-tooltip label="角色排序" /> |
| | | <el-table-column label="操作" class-name="operation-btns"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)">查看</el-link> |
| | | <el-link @click="handleEdit(row)">编辑</el-link> |
| | | <el-link v-if="permission.orderRole_set" @click="handleRole(row)">权限设置</el-link> |
| | | <el-link type="danger" @click="handleDelete(row)">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="placeholder-ele"></div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="loadList" /> |
| | | <RolePermissionDialog ref="roleDialogRef" @success="loadList" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Delete, Plus, RefreshRight, Search } from '@element-plus/icons-vue' |
| | | import { computed, onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { getRoleListNew as getRolePage, remove } from '@/api/system/role' |
| | | import { useStore } from 'vuex' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import RolePermissionDialog from './RolePermissionDialog.vue' |
| | | import { saveOperationLog } from '@ztzf/apis' |
| | | import { useRoute } from 'vue-router' |
| | | |
| | | const initSearchParams = () => ({ |
| | | roleName: '', |
| | | roleAlias: '', |
| | | sysType: 6 |
| | | }) |
| | | |
| | | const searchParams = ref(initSearchParams()) |
| | | const loading = ref(true) |
| | | const list = ref([]) |
| | | const selectedIds = ref([]) |
| | | const selectedRows = ref([]) |
| | | const queryParamsRef = ref(null) |
| | | const dialogRef = ref(null) |
| | | const roleDialogRef = ref(null) |
| | | const store = useStore() |
| | | const permission = computed(() => store.getters.permission || {}) |
| | | const route = useRoute() |
| | | |
| | | async function loadList() { |
| | | loading.value = true |
| | | try { |
| | | console.log(searchParams.value, '9999') |
| | | const res = await getRolePage(searchParams.value) |
| | | const records = res?.data?.data ?? [] |
| | | list.value = records |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | function handleSearch() { |
| | | loadList() |
| | | } |
| | | |
| | | function resetForm() { |
| | | queryParamsRef.value?.resetFields() |
| | | loadList() |
| | | } |
| | | |
| | | function handleAdd() { |
| | | dialogRef.value?.open({ mode: 'add' }) |
| | | } |
| | | |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | function handleEdit(row) { |
| | | dialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | function handleRole(row) { |
| | | const roleId = row?.id ?? selectedRows.value[0]?.id |
| | | if (!roleId) { |
| | | ElMessage.warning('只能选择一条数据') |
| | | return |
| | | } |
| | | if (selectedRows.value.length !== 1 && !row) { |
| | | ElMessage.warning('只能选择一条数据') |
| | | return |
| | | } |
| | | roleDialogRef.value?.open({ roleId }) |
| | | } |
| | | |
| | | async function handleDelete(row) { |
| | | const tips = row ? '该条' : '选中的项' |
| | | await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { |
| | | type: 'warning', |
| | | customClass: 'command-page-view-message-box', |
| | | confirmButtonClass: 'command-message-box-confirm', |
| | | cancelButtonClass: 'command-message-box-cancel', |
| | | }) |
| | | const ids = row ? row.id : selectedIds.value.join(',') |
| | | await remove(ids) |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '角色管理'}-删除`, |
| | | type: 1, |
| | | }) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | | loadList() |
| | | } |
| | | |
| | | function handleSelectionChange(rows) { |
| | | selectedIds.value = rows.map(item => item.id) |
| | | selectedRows.value = rows |
| | | } |
| | | |
| | | onMounted(() => { |
| | | loadList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <template> |
| | | <el-dialog class="gd-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close |
| | | :close-on-click-modal="false"> |
| | | <!-- <div class="detail-row-view" v-if="dialogReadonly">--> |
| | | <el-row class="detail-row-view" v-if="dialogReadonly"> |
| | | <el-col :span="12"> |
| | | <div class="label">登录账号</div> |
| | | <div class="val">{{ formData.account }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">用户姓名</div> |
| | | <div class="val">{{ formData.realName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">手机号</div> |
| | | <div class="val">{{ formData.phone }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">电子邮箱</div> |
| | | <div class="val">{{ formData.email }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">用户性别</div> |
| | | <div class="val">{{ getSexLabel(formData.sex) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">用户生日</div> |
| | | <div class="val">{{ formData.birthday }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">所属角色</div> |
| | | <div class="val">{{ formData.roleName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">所属部门</div> |
| | | <div class="val">{{ formData.deptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">用户编号</div> |
| | | <div class="val">{{ formData.code }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="label">账号状态</div> |
| | | <div class="val">{{ formData.statusName }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- </div>--> |
| | | |
| | | <el-form class="gd-dialog-form" v-else ref="formRef" :model="formData" :rules="rules" label-width="110px"> |
| | | <div class="detail-title">基础信息</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="登录账号" prop="account"> |
| | | <el-input class="gd-input" v-model="formData.account" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="dialogMode === 'add'"> |
| | | <el-form-item label="密码" prop="password"> |
| | | <el-input |
| | | class="gd-input" |
| | | v-model="formData.password" |
| | | type="password" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | show-password |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="dialogMode === 'add'"> |
| | | <el-form-item label="确认密码" prop="password2"> |
| | | <el-input |
| | | class="gd-input" |
| | | v-model="formData.password2" |
| | | type="password" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | show-password |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <div class="detail-title">详细信息</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="用户姓名" prop="realName"> |
| | | <el-input class="gd-input" v-model="formData.realName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="手机号" prop="phone"> |
| | | <el-input class="gd-input" v-model="formData.phone" maxlength="20" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="电子邮箱" prop="email"> |
| | | <el-input class="gd-input" v-model="formData.email" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="用户性别" prop="sex"> |
| | | <el-select class="gd-select" popper-class="gd-select-popper" v-model="formData.sex" placeholder="请选择" clearable> |
| | | <el-option label="男" :value="1" /> |
| | | <el-option label="女" :value="2" /> |
| | | <el-option label="未知" :value="3" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="用户生日" prop="birthday"> |
| | | <el-date-picker |
| | | class="gd-date-picker" |
| | | popper-class="" |
| | | v-model="formData.birthday" |
| | | type="datetime" |
| | | placeholder="请选择" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <div class="detail-title">职责信息</div> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="用户编号" prop="code"> |
| | | <el-input class="gd-input" v-model="formData.code" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="所属角色" prop="roleId"> |
| | | <el-tree-select |
| | | class="gd-select" |
| | | popper-class="gd-tree-select-popper" |
| | | v-model="formData.roleId" |
| | | :data="roleTree" |
| | | :props="treeProps" |
| | | node-key="id" |
| | | check-strictly |
| | | clearable |
| | | placeholder="请选择" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="所属部门" prop="deptId"> |
| | | <el-tree-select |
| | | class="gd-select" |
| | | popper-class="gd-tree-select-popper" |
| | | v-model="formData.deptId" |
| | | :data="deptTree" |
| | | :props="deptTreeSelectProps" |
| | | node-key="id" |
| | | check-strictly |
| | | clearable |
| | | placeholder="请选择" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <el-button v-if="dialogMode != 'view'" color="#F2F3F5" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button color="#4C34FF" v-if="!dialogReadonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 保存 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, onMounted, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { add, getUser, update } from '@/api/system/user' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import { getRoleTree } from '@/api/system/role' |
| | | import func from '@/utils/func' |
| | | import { saveOperationLog } from '@ztzf/apis' |
| | | import { useRoute } from 'vue-router' |
| | | |
| | | const initForm = () => ({ |
| | | account: '', |
| | | password: '', |
| | | password2: '', |
| | | realName: '', |
| | | phone: '', |
| | | email: '', |
| | | sex: null, |
| | | birthday: '', |
| | | code: '', |
| | | roleId: '', |
| | | deptId: '', |
| | | sysType: 6 |
| | | }) |
| | | |
| | | const treeProps = { |
| | | label: 'title', |
| | | children: 'children', |
| | | } |
| | | const deptTreeSelectProps = { |
| | | label: 'name', |
| | | value: 'id', |
| | | children: 'children', |
| | | } |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) |
| | | const formData = ref(initForm()) |
| | | const visible = ref(false) |
| | | const dialogMode = ref('add') |
| | | const submitting = ref(false) |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') return '编辑' |
| | | if (dialogMode.value === 'view') return '查看' |
| | | return '新增' |
| | | }) |
| | | const roleTree = ref([]) |
| | | const deptTree = ref([]) |
| | | const route = useRoute() |
| | | |
| | | const validatePass = (rule, value, callback) => { |
| | | if (value === '') { |
| | | callback(new Error('请输入密码')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | const validatePass2 = (rule, value, callback) => { |
| | | if (value === '') { |
| | | callback(new Error('请再次输入密码')) |
| | | } else if (value !== formData.value.password) { |
| | | callback(new Error('两次输入密码不一致')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | |
| | | const rules = { |
| | | account: [{ required: true, message: '请输入登录账号', trigger: 'blur' }], |
| | | password: [{ required: true, validator: validatePass, trigger: 'blur' }], |
| | | password2: [{ required: true, validator: validatePass2, trigger: 'blur' }], |
| | | realName: [ |
| | | { required: true, message: '请输入用户姓名', trigger: 'blur' }, |
| | | { min: 2, max: 50, message: '姓名长度在 2 到 50 个字符', trigger: 'blur' }, |
| | | ], |
| | | roleId: [{ required: true, message: '请选择所属角色', trigger: 'change' }], |
| | | deptId: [{ required: true, message: '请选择所属部门', trigger: 'change' }], |
| | | } |
| | | |
| | | function getSexLabel(sex) { |
| | | const map = { 1: '男', 2: '女', 3: '未知' } |
| | | return map[sex] || '' |
| | | } |
| | | |
| | | async function getRoleTreeData() { |
| | | const res = await getRoleTree('000000') |
| | | roleTree.value = res.data.data |
| | | } |
| | | |
| | | async function getDeptTreeData() { |
| | | const res = await getDeptTree('000000') |
| | | deptTree.value = res.data.data |
| | | } |
| | | |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | const submitData = { ...formData.value } |
| | | submitData.roleId = func.toStr(submitData.roleId) |
| | | submitData.name = submitData.realName |
| | | if (dialogMode.value === 'add') { |
| | | await add(submitData) |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '用户管理'}-新增`, |
| | | type: 1 |
| | | }) |
| | | } else { |
| | | await update(submitData) |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '用户管理'}-编辑`, |
| | | type: 1 |
| | | }) |
| | | } |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await getUser(formData.value.id) |
| | | const data = res?.data?.data ?? {} |
| | | if (data.roleId) { |
| | | data.roleId = func.split(data.roleId)[0] || data.roleId |
| | | } |
| | | formData.value = data |
| | | } |
| | | |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | return |
| | | } |
| | | formData.value = { id: row.id } |
| | | await loadDetail() |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getRoleTreeData() |
| | | getDeptTreeData() |
| | | }) |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.el-select) { |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.el-date-editor) { |
| | | width: 100%; |
| | | } |
| | | |
| | | :deep(.el-tree-select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form"> |
| | | <el-form-item label="登录账号" prop="account"> |
| | | <el-input |
| | | class="gd-input gray" |
| | | v-model="searchParams.account" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="用户姓名" prop="realName"> |
| | | <el-input |
| | | class="gd-input gray" |
| | | v-model="searchParams.realName" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="所属部门" prop="deptId"> |
| | | <el-tree-select |
| | | class="gd-select gray" |
| | | popper-class="gd-select-popper" |
| | | v-model="searchParams.deptId" |
| | | :data="deptTree" |
| | | :props="treeProps" |
| | | node-key="id" |
| | | check-strictly |
| | | clearable |
| | | @change="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item class="gd-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <el-button v-if="permission.orderUser_add" :icon="Plus" color="#4C34FF" type="primary" @click="handleAdd"> |
| | | 新增 |
| | | </el-button> |
| | | <el-button |
| | | v-if="permission.orderUser_remove" |
| | | :icon="Delete" |
| | | :disabled="!selectedIds.length" |
| | | @click="handleDelete()" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <div class="gd-table-container" v-loading="loading"> |
| | | <div class="gd-table-content gd-table-content-bg"> |
| | | <el-table class="gd-table" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="46" /> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="account" show-overflow-tooltip label="登录账号" /> |
| | | <el-table-column prop="realName" show-overflow-tooltip label="用户姓名" /> |
| | | <el-table-column prop="roleName" show-overflow-tooltip label="所属角色" /> |
| | | <el-table-column prop="deptName" show-overflow-tooltip label="所属部门" /> |
| | | <el-table-column prop="phone" show-overflow-tooltip width="120" label="手机号" /> |
| | | <el-table-column label="操作" class-name="operation-btns" width="180"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)">查看</el-link> |
| | | <el-link v-if="permission.orderUser_edit" @click="handleEdit(row)">编辑</el-link> |
| | | <el-link v-if="permission.orderUser_remove" type="danger" @click="handleDelete(row)">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="gd-pagination-parent"> |
| | | <el-pagination |
| | | popper-class="gd-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Delete, Plus, RefreshRight, Search } from '@element-plus/icons-vue' |
| | | import { computed, onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import { getList as getUserList, remove } from '@/api/system/user' |
| | | import { useStore } from 'vuex' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { saveOperationLog } from '@ztzf/apis' |
| | | import { useRoute } from 'vue-router' |
| | | |
| | | const initSearchParams = () => ({ |
| | | account: '', |
| | | realName: '', |
| | | deptId: '', |
| | | current: 1, |
| | | size: 10, |
| | | sysType: 6 |
| | | }) |
| | | |
| | | const searchParams = ref(initSearchParams()) |
| | | const loading = ref(true) |
| | | const list = ref([]) |
| | | const total = ref(0) |
| | | const selectedIds = ref([]) |
| | | const queryParamsRef = ref(null) |
| | | const dialogRef = ref(null) |
| | | const deptTree = ref([]) |
| | | const treeProps = { |
| | | label: 'name', |
| | | children: 'children', |
| | | } |
| | | const store = useStore() |
| | | const permission = computed(() => store.getters.permission || {}) |
| | | const route = useRoute() |
| | | |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await getUserList( |
| | | searchParams.value.current, |
| | | searchParams.value.size, |
| | | searchParams.value.sysType, |
| | | { |
| | | account: searchParams.value.account, |
| | | realName: searchParams.value.realName, |
| | | }, |
| | | searchParams.value.deptId |
| | | ) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | function handleSearch() { |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | function resetForm() { |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | searchParams.value.deptId = '' |
| | | getList() |
| | | } |
| | | |
| | | function handleAdd() { |
| | | dialogRef.value?.open({ mode: 'add' }) |
| | | } |
| | | |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | function handleEdit(row) { |
| | | dialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | async function handleDelete(row) { |
| | | const tips = row ? '该条' : '选中的项' |
| | | await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { |
| | | type: 'warning', |
| | | customClass: 'command-page-view-message-box', |
| | | confirmButtonClass: 'command-message-box-confirm', |
| | | cancelButtonClass: 'command-message-box-cancel', |
| | | }) |
| | | const ids = row ? row.id : selectedIds.value.join(',') |
| | | await remove(ids) |
| | | saveOperationLog({ |
| | | requestUri: route.path, |
| | | title: `${route.name || '用户管理'}-删除`, |
| | | type: 1 |
| | | }) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | | getList() |
| | | } |
| | | |
| | | function handleSelectionChange(rows) { |
| | | selectedIds.value = rows.map(item => item.id) |
| | | } |
| | | |
| | | function getDeptTreeList() { |
| | | getDeptTree().then(res => { |
| | | deptTree.value = res?.data?.data ?? [] |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | getDeptTreeList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |