You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

380 lines
10 KiB

<template>
<div claas="origin-wrapper" v-if="!show">
<page-title title="资源管理"/>
<div class="ns-table-wrapper">
<div class="ns-table">
<a-row type="flex" class="ns-table-main">
<a-col flex="180px">
<ns-table-header
:headerActions="headerActions"
:tableTitle="tableTitle">
<template #header="data">
<slot name="header" v-bind="data || {}"></slot>
</template>
</ns-table-header>
<div class="type-tree-wrapper">
<div class="tree-top-header">
<div class="tree-node-content-wrapper" :class="{'selected': allSelected}" @click="onAllSelect">全部资源</div>
</div>
<a-tree v-model:expandedKeys="expandedKeys" :tree-data="treeData" v-model:selectedKeys="selectedKeys"
@expand="onExpand" @select="onTreeSelect">
</a-tree>
</div>
</a-col>
<a-col flex="auto">
<!-- {{ formConfig }} -->
<ns-view-list-table v-bind="getTableBindValues" :model="data" rowKey="code" ref="tableRef">
<template #bodyCell="{ record, column }">
<template v-if="column.dataIndex === 'tableAction'">
<ns-table-action
:data="record"
:searchData="{}"
:columnActions="record && getColumnActions(record)" />
</template>
</template>
</ns-view-list-table>
</a-col>
</a-row>
</div>
</div>
</div>
<div v-if="show" class="frame-wrapper" style="height: 100%">
<iframe :src="src" id="frame" height="100%" width="100%" ></iframe>
</div>
</template>
<script lang="ts">
import {computed, defineComponent, nextTick, ref, unref} from "vue";
import {Skeleton} from "ant-design-vue";
import {tableProps} from "../../lib/component/table/props";
import {http} from "../../lib/util";
import {PlusCircleOutlined, EditOutlined, DeleteOutlined} from "@ant-design/icons-vue";
import {useParams} from "../../lib/use";
import {RequestParams} from "../../lib/component/table/table";
import { isArray} from "lodash-es";
import {NsModal} from "../../lib/component";
import {APP} from "/@/router/index.ts";
import NsCustomListTable from './custom-list-table.vue'
import NsTableAction from '/nerv-lib/component/table/table-action.vue';
import { useRouter } from "vue-router";
import Cookie from "js-cookie";
export default defineComponent({
name: 'TreeAndTableList',
components: {
Skeleton,
PlusCircleOutlined,
EditOutlined,
DeleteOutlined,
NsCustomListTable,
'ns-table-action': NsTableAction
},
props: {
...tableProps,
title: String,
tableTitle: Function,
showTitle: {
type: Boolean,
default: true,
},
resultField: String
},
setup: (props, {attrs, emit}) => {
let allSelected = ref(true);
const expandedKeys = ref(['1', '2'])
const { getParams } = useParams();
const treeParamsRef = ref({});
const selectedKeys = ref([]);
const tableRef = ref();
// let loadingTable = ref<boolean>(false);
let loadingTree = ref<boolean>(false);
const router = useRouter();
let show = ref(false);
let src = ref('');
let frameRef = ref(null);
const headerActions = [
{
label: '创建资源',
name: 'resourceAdd',
type: 'primary',
route: 'add',
}
]
const handleAction = (action, record, reload)=>{
const mode = action?.mode;
if(mode === 'api') {
NsModal.confirm({
title: '警告',
content: '确定执行该操作吗',
okText: '确认',
cancelText: '取消',
onOk: function () {
http.post(`/api/${APP}/objs/Resources/Operator`, {
RM_UUID: record.RM_UUID,
typeCode: record.typeCode,
actionApi: action['actionApi']
}).then(res=>{
reload();
})
},
});
}
if(mode === 'page') {
// action['pageAddr'] = 'http://100.68.2.97:4200/nervui-mock-ra/mr/instance/manage';
const template = action['pageAddr'];
if(template.indexOf('$') !== -1) { // 模版参数值替换
action['pageAddr'] = template.replace(/\$(\w+)\b/g, function (match, key) {
return record[key.trim()] ? record[key.trim()] : match;
});
}
src.value = `${action['pageAddr']}?nervsid=${Cookie.get('nervsid')}`;
show.value = true;
nextTick(() => {
load(record, action['name']);
})
}
}
function handleMsg(e) {
const frame = frameRef.value;
const data = e?.data;
if(data) {
if(data.type === 'back') {
window.removeEventListener('message', handleMsg);
show.value = false;
}
if(data.type === 'successBack') {
window.removeEventListener('message', handleMsg);
router.push({name:'resource', path: '/rm/resourceManage/list'});
}
}
}
function load(record, actionName) {
frameRef.value = document.getElementById('frame');
console.log(frameRef.value)
const frame = frameRef.value;
let msg = {
type: 'style',
mode: 'page',
routerPath: actionName,
showLayout: false,
data: { pageParams: {}}
}
if(['manage', 'edit'].includes(actionName)) {
msg['data'] = {
pageParams: {
ID: record['RM_UUID'],
pageTitle: record['alias']
}
}
}
if(frame) {
frame.onload = function (e) {
frame.contentWindow?.postMessage(msg, src.value );
}
window.addEventListener('message', handleMsg);
}
}
const getColumnActions =(record)=>{
if(isArray(record?.actions)) {
record?.actions.forEach(action => {
action['openPermission'] = true;
action['handle'] = (record, name, {reload, action}) =>{
handleAction(action, record, reload );
}
})
} else {
record['actions'] = [];
}
return record;
}
const tableConfig = ref(
{
// title: '资源管理',
showTitle: false,
api: `/api/${APP}/objs/Resources`,
formConfig: {},
rowSelection: null,
resultField: 'data',
columns: [
{
title: '名称',
dataIndex: 'alias',
},
{
title: '类型',
dataIndex: 'typeAlias',
},
{
title: '项目',
dataIndex: 'projectName',
},
{
title: '状态',
dataIndex: 'status',
transform: {
pipe: 'state',
statusField: (record: object) => {
return record.status;
},
// textField: (record: object) => {
// return record.statusInCN;
// },
messageField: 'reason',
},
},
],
columnActions: {
title: '操作',
width: 100,
actions: [],
},
rowKey: 'id'
}
)
// 右侧树形结构
const treeData = ref([])
const data = []
// 树形结构添加
let typeSchema = ref([]);
const typeData = ref({});
function onTreeSelect(selectedKeys: never[],
e: {
selected: boolean;
selectedNodes: { props: { dataRef: any } }[];
node: any;
event: any;
})
{
allSelected.value = false;
const dataRef = e.selectedNodes[0];
treeParamsRef.value = getParams(dataRef, {typeClassCode: 'code'});
console.log(treeParamsRef.value)
unref(tableRef).nsTableRef.treeParamsRef = {
...treeParamsRef.value
}
unref(tableRef).nsTableRef.formElRef.triggerSubmit();
}
const getTableBindValues = computed(() => {
const { params, dynamicParams } = props;
return {
...props,
...tableConfig.value
};
});
return {
treeData,
expandedKeys,
typeSchema,
typeData,
onTreeSelect,
getTableBindValues,
headerActions,
data,
allSelected,
selectedKeys,
tableRef,
loadingTree,
getColumnActions,
show,
src
};
},
mounted() {
this.getDataTree();
},
methods: {
// 转换树结构数据
transferTree(data) {
if( isArray(data) && data.length > 0) {
data.forEach(it=>{
it['title'] = it['alias'];
it['key']=it['code'];
if(it['children'] ) {
this.transferTree(it['children']);
}
})
} else {
return;
}
},
getDataTree() {
http.get(`/api/${APP}/objs/ManageResourceTypeClasses`).then(res => {
this.transferTree(res)
this.treeData = res;
this.loadingTree = false;
}).catch( ()=>{
this.loadingTree = false;
})
},
onAllSelect() {
this.allSelected = !this.allSelected;
this.selectedKeys = [];
this.tableRef.nsTableRef.treeParamsRef = {};
this.tableRef.nsTableRef.formElRef.triggerSubmit();
}
},
});
</script>
<style lang="less" scoped>
.ns-table-main {
flex-wrap: nowrap;
}
:deep(.ns-table-header) {
min-width: unset;
.ant-btn {
margin-left: 0 !important;
}
}
.ns-table-wrapper {
margin: 0 24px;
}
.type-tree-wrapper {
color: rgba(0, 0, 0, 0.65);
border-right: 1px solid rgba(0, 0, 0, 0.08);
height: 800px;
overflow-y: auto;
.tree-top-header {
display: flex;
justify-content: space-between;
cursor: pointer;
margin-bottom: 4px;
.tree-node-content-wrapper {
padding: 0 4px;
&.selected {
background-color: rgba(0, 172, 255, 0.1);
color: #00acff;
}
}
}
}
:deep(.ant-tree ) {
color: rgba(0, 0, 0, 0.65);
.ant-tree-node-content-wrapper.ant-tree-node-selected {
background-color: rgba(0, 172, 255, 0.1);
color: #00acff
}
}
// iframe 样式
#frame {
border: 0;
}
</style>