This commit is contained in:
liang.chao 2025-11-27 10:27:41 +08:00
parent 13f9bd6af7
commit e62fcc16f5
3 changed files with 522 additions and 0 deletions

View File

@ -0,0 +1,25 @@
import request from '@/axios';
// 获取左侧树列表接口
export function getLeftTreeListAPI(id) {
let data = {
id: id
};
return request({
url: '/blade-system/file/share/listAll',
method: 'POST',
data: data,
})
}
// 获取数据列表接口
export function getListDataSetAPI(id) {
let data = {
dataClassifyId: id
};
return request({
url: '/blade-system/file/share/list',
method: 'POST',
data: data,
})
}

View File

@ -0,0 +1,267 @@
<template>
<el-row class="full-height">
<!-- 左侧树 -->
<el-col :span="5" class="left-panel">
<div class="box">
<el-scrollbar>
<basic-container>
<avue-tree
:option="treeOption"
:data="treeData"
@node-click="nodeClick"
/>
</basic-container>
</el-scrollbar>
</div>
</el-col>
<!-- 右侧表格 -->
<el-col :span="19" class="right-panel">
<basic-container class="right-basic">
<avue-crud
:option="option"
v-model="form"
:search.sync="search"
:data="data"
:table-loading="loading"
ref="crud"
@search-change="searchChange"
@search-reset="searchReset"
@refresh-change="refreshChange"
>
<!-- 自定义操作列 -->
<template #operate="{ row }">
<el-button type="primary" size="mini" plain @click="shareRow(row)">
<i class="el-icon-share"></i>分享
</el-button>
</template>
</avue-crud>
</basic-container>
</el-col>
</el-row>
<Share
v-if="shareDialogVisible"
:rowData="shareRowData"
title="分享接口"
:width="1000"
:height="1000"
@closeDialog="shareDialogVisible = false"
/>
</template>
<script>
import Share from "./share1.vue";
import { getLeftTreeListAPI, getListDataSetAPI } from "@/api/data-collect/file-share-manage";
export default {
name: "DataSetManage",
components: {
Share
},
data() {
return {
loading: false,
form: {},
search: { keyword: "" },
data: [],
rawData: [],
option: {
height: "calc(100vh - 280px)",
border: true,
index: true,
tip: false,
searchShow: true,
addBtn: false,
editBtn: false,
delBtn: false,
viewBtn: false,
selection: false,
columnBtn: true, // Avue
menu: false, // Avue
searchMenuSpan: 6, //
column: [
{
label: "请输入名称",
prop: "keyword",
search: true,
type: "input",
placeholder: "请输入名称",
hide: true,
searchLabelWidth: 100, //
}
]
},
treeDeptId: "0",
treeData: [],
treeOption: {
nodeKey: "id",
menu: false,
addBtn: false,
props: { label: "title", children: "children" }
},
shareDialogVisible: false,
shareRowData: null,
};
},
mounted() {
this.loadFullTree();
this.loadDatasetNoPaging();
},
methods: {
//
loadFullTree() {
getLeftTreeListAPI(0)
.then(res => {
const rows = res.data.rows || [];
const formatted = rows.map(item => ({
id: item.code,
title: item.name,
children: (item.kyDataClassifyList || []).map(c => ({
id: c.id.toString(),
title: c.dataTypeName
}))
}));
this.treeData = [
{ id: "-1", title: "数据汇集管理", children: formatted }
];
})
.catch(err => {
console.error("加载左树失败", err);
this.treeData = [];
});
},
nodeClick(node) {
this.treeDeptId = node.id;
this.loadDatasetNoPaging();
},
//
async loadDatasetNoPaging() {
this.loading = true;
try {
const res = await getListDataSetAPI(this.treeDeptId);
const row = res.data?.rows?.[0];
let arr = [];
if (!row || !row.dataJson) {
this.setColumnsEmpty();
this.rawData = [];
this.data = [];
return;
}
try {
arr = JSON.parse(row.dataJson);
} catch {
arr = JSON.parse(row.dataJson.replace(/\r\n/g, "").replace(/\n/g, ""));
}
if (!Array.isArray(arr) || arr.length < 1) {
this.setColumnsEmpty();
this.rawData = [];
this.data = [];
return;
}
const header = arr[0];
const content = arr.slice(1);
const columns = Object.keys(header)
.filter(k => k !== "id")
.map(k => ({
label: header[k],
prop: k,
minWidth: 140,
showOverflowTooltip: true,
overHidden: true
}));
// + +
this.option.column = [
this.option.column[0], //
...columns,
{
label: "操作",
prop: "operate",
width: 100,
fixed: "right",
type: "slot"
}
];
this.rawData = content;
this.data = [...content];
} catch (err) {
console.error("加载数据失败", err);
this.setColumnsEmpty();
this.rawData = [];
this.data = [];
} finally {
this.loading = false;
}
},
// +
setColumnsEmpty() {
this.option.column = [
this.option.column[0],
{
label: "操作",
prop: "operate",
width: 100,
fixed: "right",
type: "slot"
}
];
},
searchChange(params, done) {
const keyword = (params.keyword || "").toString().trim().toLowerCase();
if (!keyword) {
this.data = [...this.rawData];
done && done();
return;
}
this.data = this.rawData.filter(row =>
Object.keys(row).some(k => k !== "id" && String(row[k] || "").toLowerCase().includes(keyword))
);
done && done();
},
searchReset() {
this.search.keyword = "";
this.data = [...this.rawData];
},
refreshChange() {
this.data = [...this.rawData];
},
shareRow(row) {
this.shareRowData = row;
this.shareDialogVisible = true; //
}
}
};
</script>
<style>
.box {
height: 800px;
}
.el-scrollbar {
height: 100%;
}
.box .el-scrollbar__wrap {
overflow: scroll;
}
</style>

View File

@ -0,0 +1,230 @@
<!-- 小型弹窗 -->
<template>
<el-dialog
class="l-dialog"
:class="lDialog"
:title="title"
v-model="dialogVisible"
:show-close="true"
:close-on-click-modal="false"
@close="handleClose"
:append-to-body="true"
:width="computedWidth"
>
<div>
<!-- 文档式表格 -->
<div class="dialog-content">
<div class="doc-wrap">
<table class="doc-table">
<tbody>
<tr>
<th>名称</th>
<td>获取{{ rowData?.selectedNodeName }}文件接口</td>
</tr>
<tr>
<th>描述</th>
<td>依据ID获取{{ rowData?.selectedNodeName }}文件</td>
</tr>
<tr>
<th>URL</th>
<td>
/api/blade-system/data/Collect/queryById?id={{
rowData?.selectedNodeId
}}&jsonId={{ rowData?.jsonId }}
</td>
</tr>
<tr>
<th>HTTP请求方式</th>
<td>GET</td>
</tr>
<tr>
<th>请求参数</th>
<td>
<table class="inner-table">
<thead>
<tr>
<th>参数名称</th>
<th>必选</th>
<th>类型及范围</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>true</td>
<td>字符串</td>
<td>/</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<th>返回结果</th>
<td>
<pre class="code">{{ resultJson }}</pre> <!-- v-text 插值更安全 -->
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button class="clear-btn" @click="handleClose" :disabled="disabled">
取消
</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
// Vue 3 Options API
export default {
name: 'Share',
// emits
emits: ['closeDialog'],
// props
props: {
width: {
type: [Number, String],
default: 500
},
title: {
type: String,
default: '分享接口'
},
disabled: {
type: Boolean,
default: false
},
rowData: {
type: Object,
default: () => ({})
}
},
data() {
return {
dialogVisible: true,
resultJson: ''
};
},
computed: {
// class width
lDialog() {
return this.width > 500 ? 'w700' : 'w500';
},
// el-dialog width
computedWidth() {
return typeof this.width === 'number' ? `${this.width}px` : this.width;
}
},
created() {
this.initFormData();
},
methods: {
initFormData() {
if (this.rowData) {
let payload = this.rowData.data ?? this.rowData;
try {
this.resultJson = JSON.stringify(
payload,
(key, value) => {
if (
key === 'selectedNodeName' ||
key === 'selectedNodeId' ||
key === 'jsonId'
) {
return undefined;
}
return value;
},
2
);
} catch (e) {
this.resultJson = String(payload);
}
}
},
handleClose() {
this.dialogVisible = false;
this.$emit('closeDialog');
}
}
};
</script>
<style scoped>
/* 使用 :deep() 替代 ::v-deepVue 3 推荐) */
.w700 :deep(.el-dialog) {
width: 700px;
}
.w500 :deep(.el-dialog) {
width: 500px;
}
/* 其他样式保持不变 */
.w500 :deep(.el-dialog__header),
.w700 :deep(.el-dialog__header) {
.el-dialog__title {
font-size: 16px;
}
}
.doc-wrap {
margin-top: 8px;
}
.doc-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.doc-table th,
.doc-table td {
border: 1px solid #dcdfe6;
padding: 8px 10px;
vertical-align: top;
}
.doc-table th {
width: 120px;
background: #f5f7fa;
color: #303133;
text-align: right;
}
.doc-table .inner-table {
width: 100%;
border-collapse: collapse;
}
.doc-table .inner-table th,
.doc-table .inner-table td {
border: 1px solid #e4e7ed;
padding: 6px 8px;
text-align: left;
}
.code {
background: #f8f8f8;
border: 1px solid #ebeef5;
padding: 8px;
border-radius: 4px;
white-space: pre-wrap;
word-break: break-all;
}
.dialog-content {
max-height: calc(80vh - 100px); /* 预留标题和 footer 空间 */
overflow-y: auto;
}
</style>