指标列表

This commit is contained in:
仲么了
2024-01-15 16:15:24 +08:00
parent 646af778e9
commit 0feebcd5ba
12 changed files with 505 additions and 127 deletions

View File

@@ -0,0 +1,23 @@
import createAxios from '@/utils/request'
// 查询指标
export const queryStatistical = (id:string) => {
let form = new FormData()
form.append('id', id)
return createAxios({
url: '/system-boot/csstatisticalset/queryStatistical',
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: form
})
}
// 绑定指标
export const addStatistical = (params:any) => {
return createAxios({
url: '/system-boot/csstatisticalset/addStatistical',
method: 'post',
data: params
})
}

View File

@@ -0,0 +1,14 @@
import createAxios from '@/utils/request'
export const deleteStatistical = (id) => {
let form = new FormData()
form.append('id', id)
return createAxios({
url: '/system-boot/dic/delete',
method: 'DELETE',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: form
})
}

View File

@@ -1,4 +1,5 @@
import createAxios from '@/utils/request'
// 字典树接口
export function queryByCode(code: string) {
let form = new FormData()
@@ -40,3 +41,23 @@ export function queryByid(id: string) {
data: form
})
}
//新增字典树数据
export const addDictTree = (data: any) => {
return createAxios({
url: '/system-boot/dictTree/add',
method: 'post',
data: data
})
}
// 编辑统计指标配置项
export const updateStatistical = (data) => {
return createAxios({
url: '/system-boot/dic/update',
method: 'PUT',
data: data
})
}

View File

@@ -47,7 +47,7 @@ export default class TableStore {
this.isWebPaging = options.isWebPaging || false
this.method = options.method || 'GET'
this.table.column = options.column
this.showPage = options.showPage || true
this.showPage = options.showPage === false ? false : true
this.table.publicHeight = options.publicHeight || 0
this.table.resetCallback = options.resetCallback || null
this.table.loadCallback = options.loadCallback || null

View File

@@ -2,10 +2,10 @@
<div class="default-main">
<TableHeader>
<template v-slot:operation>
<el-button :icon="Plus" type="primary" @click="addMenu">添加</el-button>
<el-button :icon="Plus" type="primary" @click="addMenu">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" :pagination="false" />
<Table ref="tableRef" />
<popupForm ref="popupRef"></popupForm>
</div>
</template>
@@ -26,6 +26,7 @@ const tableRef = ref()
const popupRef = ref()
const navTabs = useNavTabs()
const tableStore = new TableStore({
showPage: false,
url: '/user-boot/function/functionTree',
column: [
{ title: '菜单名称', field: 'title', align: 'left', treeNode: true },

View File

@@ -35,7 +35,7 @@ const tableStore = new TableStore({
buttons: [
{
name: 'edit',
text: '波形分析',
title: '波形分析',
type: 'primary',
icon: 'el-icon-DataLine',
render: 'tipButton',

View File

@@ -0,0 +1,87 @@
<template>
<el-dialog class='cn-operate-dialog' v-model='dialogVisible' :title='title'>
<el-scrollbar>
<el-form :inline='false' :model='form' label-width='120px'>
<el-form-item label='名称'>
<el-input v-model='form.name' placeholder='请输入名称' />
</el-form-item>
<el-form-item label='编码'>
<el-input v-model='form.code' placeholder='请输入编码' />
</el-form-item>
<el-form-item label='备注'>
<el-input v-model='form.remark' placeholder='请输入备注' />
</el-form-item>
<el-form-item label='排序'>
<el-input-number v-model='form.sort' :min='0' />
</el-form-item>
</el-form>
</el-scrollbar>
<template #footer>
<span class='dialog-footer'>
<el-button @click='dialogVisible = false'>取消</el-button>
<el-button type='primary' @click='submit'>确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { addDictTree, updateStatistical } from '@/api/system-boot/dictTree'
import { ElMessage } from 'element-plus'
const emits = defineEmits<{
(e: 'over'): void
}>()
defineOptions({
name: 'govern/setting/statisticalType/add'
})
const tableStore = inject('tableStore') as TableStore
const form = reactive({
name: '',
code: '',
remark: '',
sort: 0,
pid: '',
id: ''
})
const dialogVisible = ref(false)
const title = ref('新增菜单')
const open = (text: string, data?: anyObj) => {
title.value = text
for (let key in form) {
form[key] = data ? data[key] : ''
}
dialogVisible.value = true
}
const submit = async () => {
// 非空校验
for (let key in form) {
if (key != 'pid' && key != 'id' && key != 'sort') {
if (!form[key]) {
ElMessage.warning('请填写完整信息')
return
}
}
}
if (form.id) {
await updateStatistical(form).then(res => {
ElMessage.success('编辑成功')
})
} else {
if (!form.pid) {
form.pid = tableStore.table.params.pid
}
await addDictTree(form).then(res => {
ElMessage.success('新增成功')
})
}
emits('over')
dialogVisible.value = false
}
defineExpose({ open })
</script>

View File

@@ -0,0 +1,295 @@
<template>
<el-dialog class='cn-operate-dialog statistical-type-binding' v-model='dialogVisible' title='绑定指标'>
<el-scrollbar style='padding-right: 0'>
<div class='box'>
<div class='box-left'>
<el-cascader-panel
v-model='fromDataValue'
:props='{
multiple: true
}'
:options='fromData'
></el-cascader-panel>
</div>
<div class='box-center'>
<el-button type='primary' icon='el-icon-Plus' @click='newGroup'>新建分组</el-button>
<el-popover v-model='popoverVisible' placement='right' width='400' trigger='click'
popper-style='width:auto'>
<div class='statistical-type-binding-button-group'>
<el-button
type='primary'
style='margin-left: 0'
v-for='item in toData'
@click='leftCheckChange(item)'
>
{{ item.label }}
</el-button>
</div>
<div v-if='toData.length === 0'>请先创建分组</div>
<template #reference>
<el-button style='margin-left: 0' class='mt20' type='primary' icon='el-icon-ArrowRight'>
向右
</el-button>
</template>
</el-popover>
<el-button
style='margin-left: 0'
icon='el-icon-ArrowLeft'
class='mt20'
type='primary'
@click='rightCheckChange'
>
向左
</el-button>
</div>
<div class='box-right'>
<el-cascader-panel
v-model='toDataValue'
:props='{
multiple: true
}'
:options='toData'
>
<template #default='{ node, data }'>
<div style='display: flex; align-items: center'>
<div class='hide-txt'>{{ data.label }}</div>
<template v-if='!node.isLeaf'>
<div class='ml5'>({{ data.children.length }})</div>
<div style='flex: 1'></div>
<i
class='el-icon-delete ml10'
style='cursor: pointer'
@click='deleteStatistical(data)'
></i>
</template>
</div>
</template>
</el-cascader-panel>
</div>
</div>
</el-scrollbar>
<template #footer>
<span class='dialog-footer'>
<el-button @click='dialogVisible = false'>取消</el-button>
<el-button type='primary' @click='submit'>确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import { ref, inject } from 'vue'
import { ElMessage } from 'element-plus'
import { queryStatistical } from '@/api/system-boot/csstatisticalset'
defineOptions({
name: 'govern/setting/statisticalType/binding'
})
const dialogVisible = ref(false)
const popoverVisible = ref(false)
const fromData = ref<treeData[]>([])
const fromDataValue = ref<treeData[]>([])
const toData = ref<treeData[]>([])
const toDataValue = ref<treeData[]>([])
// 左侧源数据选中事件
const leftCheckChange = (e: any) => {
if (fromDataValue.value.length === 0) {
return ElMessage.warning('请先选择数据')
}
let arr: any[] = []
fromDataValue.value.forEach(item1 => {
fromData.value.forEach(item2 => {
if (item2.value === item1[0]) {
item2.children = item2.children.filter((item3, index) => {
if (item3.value === item1[1]) {
arr.push(item3)
return false
} else {
return true
}
})
}
})
})
if (e.value) {
toData.value.forEach(item => {
if (item.value === e.value) {
item.children.push(...arr)
}
})
} else {
toData.value.push(...arr)
}
// fromDataValue.value = []
popoverVisible.value = false
}
// 右侧目标数据选中事件
const rightCheckChange = () => {
console.log(toDataValue.value)
if (toDataValue.value.length === 0) {
return ElMessage.warning('请先选择数据')
}
let arr: any[] = []
toDataValue.value.forEach(item1 => {
if (item1.length === 1) {
toData.value = toData.value.filter(item2 => {
if (item2.value === item1[0]) {
arr.push(item2)
return false
} else {
return true
}
})
} else {
toData.value.forEach(item2 => {
if (item2.value === item1[0]) {
item2.children = item2.children.filter((item3, index) => {
if (item3.value === item1[1]) {
arr.push(item3)
return false
} else {
return true
}
})
}
})
}
})
fromData.value.forEach(item1 => {
arr.forEach(item2 => {
if (item2.pid === item1.value) {
item1.children.push(item2)
}
})
})
}
const deleteStatistical = (data: any) => {
if (data.children.length) {
return ElMessage.warning('该分组下有指标,不能删除')
}
// $confirm.value('确定删除该分组吗?', '提示', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// deleteStatistical(data.value).then(res => {
// if (res.code == 'A0000') {
// $message.value.success('删除成功')
// toData.value = toData.value.filter(item => item.value !== data.value)
// } else {
// $message.value.error(res.msg)
// }
// })
// })
}
const newGroup = () => {
}
const open = (id: string) => {
dialogVisible.value = true
queryStatistical(id).then(res => {
fromData.value = []
fromDataValue.value = []
toData.value = []
toDataValue.value = []
res.data.unSelectedList.forEach((item: any) => {
const obj = {
id: item.dataType,
value: item.dataType,
pid: 0,
label: item.dataTypeName,
children: [] as any[]
}
item.eleEpdPqdVOS.forEach((item2: any) => {
const obj2 = {
id: item2.id,
pid: item.dataType,
value: item2.id,
label: item2.phase === 'M' ? item2.showName : item2.phase + '相' + item2.showName
}
if (item2.showName) {
obj.children.push(obj2)
}
})
fromData.value.push(obj)
})
res.data.selectedList.forEach((item: any) => {
const obj = {
id: item.dataType,
value: item.dataType,
pid: 0,
label: item.dataTypeName,
children: [] as any[]
}
item.eleEpdPqdVOS.forEach((item2: any) => {
const obj2 = {
id: item2.id,
pid: item2.dataType,
value: item2.id,
label: item2.phase === 'M' ? item2.showName : item2.phase + '相' + item2.showName
}
if (item2.showName) {
obj.children.push(obj2)
}
})
toData.value.push(obj)
})
})
}
const submit = async () => {
dialogVisible.value = false
}
defineExpose({ open })
</script>
<style lang='scss'>
.statistical-type-binding-button-group {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
}
.statistical-type-binding {
.box {
display: flex;
width: 1000px;
height: calc(60vh - 95px);
margin: 0 auto;
text-align: left;
.box-center {
display: flex;
align-items: center;
width: 100px;
padding-top: 20px;
margin: 0 20px;
flex-direction: column;
}
.box-right,
.box-left {
height: 100%;
overflow: hidden;
flex: 1;
.el-cascader-menu{
padding-right: 0;
.el-scrollbar__wrap{
height: 100%;
}
}
.el-cascader-panel {
height: 100%;
.el-cascader-menu__list {
height: 100% !important;
}
}
}
}
}
</style>

View File

@@ -1,41 +1,55 @@
<template>
<div class="default-main">
<div class='default-main'>
<TableHeader>
<template v-slot:operation>
<el-button :icon="Plus" type="primary" @click="addMenu">添加</el-button>
<el-button :icon='Plus' type='primary' @click='addMenu'>新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" :pagination="false" />
<popupForm ref="popupRef"></popupForm>
<Table ref='tableRef' />
<PopupBinding ref='bindingRef'></PopupBinding>
<PopupAdd ref='addRef' @over='init'></PopupAdd>
</div>
</template>
<script setup lang="ts">
<script setup lang='ts'>
import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import popupForm from './popupForm.vue'
import { useNavTabs } from '@/stores/navTabs'
import { delMenu } from '@/api/systerm'
import PopupBinding from './binding.vue'
import PopupAdd from './add.vue'
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
import { deleteStatistical } from '@/api/system-boot/dic'
defineOptions({
name: 'govern/setting/statisticalType'
})
const tableRef = ref()
const popupRef = ref()
const navTabs = useNavTabs()
const bindingRef = ref()
const addRef = ref()
const tableStore = new TableStore({
url: '/user-boot/function/functionTree',
showPage: false,
url: '/system-boot/dictTree/query',
method: 'POST',
column: [
{ title: '序号', type: 'seq', width: 60 },
{ title: '统计类型', field: 'title' },
{ title: '统计类型', field: 'name' },
{
title: '操作',
align: 'center',
width: '130',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '绑定指标',
type: 'primary',
icon: 'el-icon-Connection',
render: 'tipButton',
click: row => {
bindingRef.value.open(row.id)
}
},
{
name: 'edit',
title: '编辑',
@@ -43,7 +57,7 @@ const tableStore = new TableStore({
icon: 'el-icon-EditPen',
render: 'tipButton',
click: row => {
popupRef.value.open('编辑菜单', row)
addRef.value.open('编辑', row)
}
},
{
@@ -59,8 +73,8 @@ const tableStore = new TableStore({
title: '确定删除该菜单吗?'
},
click: row => {
delMenu(row.id).then(() => {
tableStore.index()
deleteStatistical(row.id).then(() => {
init()
})
}
}
@@ -81,14 +95,30 @@ const tableStore = new TableStore({
}
})
provide('tableStore', tableStore)
const init = () => {
tableStore.table.loading = true
queryByCode('Statistical_Type').then(res => {
tableStore.table.params.pid = res.data.id
queryCsDictTree(res.data.id).then(res => {
tableStore.table.data = res.data
tableStore.table.loading = false
})
})
}
onMounted(() => {
tableStore.table.ref = tableRef.value
tableStore.index()
tableStore.table.loading = false
init()
})
const addMenu = () => {
console.log(popupRef)
popupRef.value.open('新增菜单')
console.log(bindingRef)
addRef.value.open('新增菜单', {
sort: tableStore.table.data.length ? tableStore.table.data[tableStore.table.data.length - 1].sort + 1 : 1,
code: '',
pid: '',
id: '',
remark: '',
name: ''
})
}
</script>

View File

@@ -1,103 +0,0 @@
<template>
<el-dialog class='cn-operate-dialog' v-model='dialogVisible' :title='title'>
<el-scrollbar>
<el-form :inline='false' :model='form' label-width='120px'>
<el-form-item label='上级菜单'>
<el-cascader
v-model='form.pid'
:options='tableStore.table.data'
:props='cascaderProps'
style='width: 100%'
/>
</el-form-item>
<el-form-item label='菜单名称'>
<el-input v-model='form.name' placeholder='请输入菜单名称' />
</el-form-item>
<el-form-item label='图标'>
<IconSelector v-model='form.icon' placeholder='请选择图标' />
</el-form-item>
<el-form-item label='菜单路由'>
<el-input v-model='form.path' placeholder='请输入菜单名称' />
</el-form-item>
<el-form-item label='组件路径'>
<el-input v-model='form.routeName' placeholder='请输入组件路径,如/src/views/dashboard/index.vue' />
</el-form-item>
<el-form-item label='排序'>
<el-input-number v-model='form.sort' :min='0' />
</el-form-item>
<el-form-item label='菜单描述'>
<el-input v-model='form.remark' :rows='2' type='textarea' placeholder='请输入描述' />
</el-form-item>
</el-form>
</el-scrollbar>
<template #footer>
<span class='dialog-footer'>
<el-button @click='dialogVisible = false'>取消</el-button>
<el-button type='primary' @click='submit'>确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import IconSelector from '@/components/baInput/components/iconSelector.vue'
import { updateMenu, addMenu } from '@/api/systerm'
const tableStore = inject('tableStore') as TableStore
const cascaderProps = {
label: 'title',
value: 'id'
}
const form: any = reactive({
code: '',
icon: '',
id: '',
name: '',
path: '',
pid: '0',
remark: '',
routeName: '',
sort: 0,
type: 0
})
const dialogVisible = ref(false)
const title = ref('新增菜单')
const open = (text: string, data?: anyObj) => {
console.log(data)
title.value = text
if (data) {
for (let key in form) {
form[key] = data[key]
}
form.path = data.routePath
form.name = data.title
} else {
// 重置表单
for (let key in form) {
form[key] = ''
}
form.pid = '0'
form.sort = 0
form.type = 0
}
dialogVisible.value = true
}
const submit = async () => {
if (form.id) {
await updateMenu(form)
} else {
form.code = 'menu'
let obj = JSON.parse(JSON.stringify(form))
delete obj.id
await addMenu(obj)
}
tableStore.index()
dialogVisible.value = false
}
defineExpose({ open })
</script>

View File

@@ -2,6 +2,7 @@
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"suppressImplicitAnyIndexErrors": true,
"module": "esnext",
"moduleResolution": "node",
"removeComments": false,

9
types/global.d.ts vendored
View File

@@ -13,6 +13,15 @@ interface anyObj {
[key: string]: any
}
interface treeData {
id?: string
value?: string
name?: string
label?: string
children: treeData[]
[key: string]: any
}
interface TableDefaultData<T = any> {
list: T
remark: string