Merge branch 'feature/show-page' of https://ptdata-gitlab.shiyue.com/workbench/y-code into feature/new-sys

This commit is contained in:
sy2084
2024-07-17 23:20:47 +08:00
11 changed files with 876 additions and 99 deletions

View File

@@ -1,4 +1,4 @@
import { get } from '@/utils/request';
import { get } from "@/utils/request";
export interface UserInfoType {
alias: string;
@@ -15,8 +15,20 @@ export interface UserInfoType {
username: string;
}
export const getUserInfo = () => get<UserInfoType>({
url: '/api/home/grade',
});
interface DropListItem {
label: string;
value: string | number;
mark: string;
}
export const logout = () => get({ url: '/api/common/logout' });
export const getUserInfo = () =>
get<UserInfoType>({
url: "/api/home/grade",
});
export const logout = () => get({ url: "/api/common/logout" });
export const getProjectDrop = () =>
get<DropListItem[]>({
url: "/api/v1/project/get-project-drop",
});

View File

@@ -1,28 +0,0 @@
import { get, post } from "@/utils/request";
// 预览
export function preview({ modularId, fieldIds, page, perPage, filter }) {
return post({
url: "api/v1/preview/view",
data: {
modular_id: modularId,
field_ids: fieldIds,
page,
per_page: perPage,
filter,
},
});
}
// 查看视图
export function searchInfo({ previewId, page, perPage, filter }) {
return get({
url: `/api/v1/preview/info`,
params: {
preview_id: previewId,
page,
per_page: perPage,
filter,
},
});
}

21
src/api/preview/index.ts Normal file
View File

@@ -0,0 +1,21 @@
import { post } from "@/utils/request";
interface PreviewItemParams {
previewId: string | number;
filter?: string | [];
page?: number;
perPage?: number;
}
// 查看视图
export function searchInfo(data: PreviewItemParams) {
return post({
url: `/api/v1/preview/info`,
data: {
preview_id: data.previewId,
filter: data.filter,
page: data.page,
per_page: data.perPage,
},
});
}

View File

@@ -1,12 +1,14 @@
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
import './global.less';
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
import "./global.less";
import VueGridLayout from "vue-grid-layout"; // 引入layout
const app = createApp(App);
app.use(VueGridLayout);
app.use(createPinia());
app.use(router);
app.mount('#app');
app.mount("#app");

View File

@@ -1,7 +1,11 @@
import Layout from '@/layout/index.vue';
import { HomeOutlined, BarChartOutlined } from '@ant-design/icons-vue';
import { h } from 'vue';
import type { VNode, RendererNode, RendererElement } from 'vue';
import Layout from "@/layout/index.vue";
import {
HomeOutlined,
BarChartOutlined,
AppstoreOutlined,
} from "@ant-design/icons-vue";
import { h } from "vue";
import type { VNode, RendererNode, RendererElement } from "vue";
export interface RouteType {
path: string;
@@ -11,70 +15,96 @@ export interface RouteType {
isMenu?: boolean;
redirect?: string;
children: RouteType[];
icon?: () => VNode<RendererNode, RendererElement, {
[key: string]: any;
}>
icon?: () => VNode<
RendererNode,
RendererElement,
{
[key: string]: any;
}
>;
}
const routeList: RouteType[] = [
{
path: '/',
name: 'layout',
path: "/",
name: "layout",
component: Layout,
meta: { title: '首页' },
meta: { title: "首页" },
children: [
{
path: '',
name: '-',
path: "",
name: "-",
meta: {},
children: [],
redirect: '/config-manage/project-cfg',
redirect: "/config-manage/project-cfg",
},
{
path: '/config-manage',
name: 'config-manage',
path: "/config-manage",
name: "config-manage",
isMenu: true,
meta: { title: '配置管理' },
meta: { title: "配置管理" },
icon: () => h(HomeOutlined),
children: [
{
path: 'project-cfg',
name: 'project-cfg',
component: () => import('@/views/config-manage/project-cfg/index.vue'),
meta: { title: '项目配置' },
path: "project-cfg",
name: "project-cfg",
component: () =>
import("@/views/config-manage/project-cfg/index.vue"),
meta: { title: "项目配置" },
isMenu: true,
children: [],
},
{
path: 'module-cfg',
name: 'module-cfg',
component: () => import('@/views/config-manage/module-cfg/index.vue'),
meta: { title: '数据来源配置' },
path: "module-cfg",
name: "module-cfg",
component: () =>
import("@/views/config-manage/module-cfg/index.vue"),
meta: { title: "数据来源配置" },
isMenu: true,
children: [],
},
],
},
{
path: '/view-all-manage',
name: 'view-all-manage',
path: "/view-all-manage",
name: "view-all-manage",
isMenu: true,
meta: { title: '视图管理' },
meta: { title: "视图管理" },
icon: () => h(BarChartOutlined),
children: [
{
path: 'view-list',
name: 'view-list',
component: () => import('@/views/view-all-manage/view-list/index.vue'),
meta: { title: '视图列表' },
path: "view-list",
name: "view-list",
component: () =>
import("@/views/view-all-manage/view-list/index.vue"),
meta: { title: "视图列表" },
isMenu: true,
children: [],
},
{
path: 'create-view',
name: 'create-view',
component: () => import('@/views/view-all-manage/create-view/index.vue'),
meta: { title: '创建视图' },
path: "create-view",
name: "create-view",
component: () =>
import("@/views/view-all-manage/create-view/index.vue"),
meta: { title: "创建视图" },
isMenu: true,
children: [],
},
],
},
{
path: "/page-show-info",
name: "page-show-info",
isMenu: true,
meta: { title: "视图预览" },
icon: () => h(AppstoreOutlined),
children: [
{
path: "page-info",
name: "page-info",
component: () =>
import("@/views/page-show-info/page-info/index,.vue"),
meta: { title: "页面展示" },
isMenu: true,
children: [],
},

View File

@@ -0,0 +1,330 @@
<template>
<div class="page-view-wrapp">
<div class="project">
<span>项目: </span>
<a-select
style="min-width: 120px"
placeholder="请选择项目"
v-model:value="projectVal"
:options="projectOptions"
@change="handleProjectChange"
></a-select>
</div>
<div>
<grid-layout
v-if="isDraggable"
:layout.sync="layoutList"
:col-num="2"
:is-draggable="true"
:is-resizable="false"
:is-mirrored="false"
:vertical-compact="true"
:use-css-transforms="true"
>
<grid-item
v-for="(item, index) in layoutList"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:key="item.i"
drag-allow-from=".vue-draggable-handle"
drag-ignore-from=".no-drag"
>
<div class="view-box view-draggable">
<div class="vue-draggable-handle"><BarsOutlined /></div>
<div class="content no-drag">
<a-spin :spinning="ids[index].loading">
<div class="card-content">
<y-table
v-if="item.data.type === VIEW_TYPE.TABLE"
:filter-config="item.data.filter"
:data-list="item.data.data"
:column-config="item.data.header"
:total="item.data.count"
:title="item.data.preview_name"
@toFilt="
(params?:object) => {
handleSingle(ids[index], params);
}
"
></y-table>
<y-chart
v-if="item.data.type === VIEW_TYPE.CHART"
:chartCfg="item.data.config"
:title="item.data.preview_name"
:filter-config="item.data.filter"
@toFilt="
(params?:object) => {
handleSingle(ids[index], params);
}
"
></y-chart>
</div>
</a-spin>
</div>
</div>
</grid-item>
</grid-layout>
<a-row v-else :gutter="[16, 16]">
<a-col v-for="(item, index) in layoutList" :span="24">
<a-spin :spinning="item.loading">
<div>
<div class="view-box">
<div class="content">
<div class="card-content">
<y-table
v-if="item.data.type === VIEW_TYPE.TABLE"
:filter-config="item.data.filter"
:data-list="item.data.data"
:column-config="item.data.header"
:total="item.data.count"
:title="item.data.preview_name"
@toFilt="
(params?:object) => {
console.log('xxxx',params)
handleSingle(ids[index], params,);
}
"
></y-table>
<y-chart
v-if="item.data.type === VIEW_TYPE.CHART"
:chartCfg="item.data.config"
:title="item.data.preview_name"
:filter-config="item.data.filter"
@toFilt="
(params?:object) => {
handleSingle(ids[index], params);
}
"
></y-chart>
</div>
</div>
</div>
</div>
</a-spin>
</a-col>
</a-row>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, shallowRef, computed, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { BarsOutlined } from "@ant-design/icons-vue";
// utils
import PLimit from "p-limit";
// api
import { searchInfo } from "@/api/preview/index";
import { getProjectDrop } from "@/api/common";
import { getPageInfo } from "./service";
import type { SelectProps } from "ant-design-vue";
import { Item } from "ant-design-vue/es/menu";
interface ItemDetail {
id: number | string;
data: any;
loading: boolean;
}
interface Item {
id: number | string;
data: any;
loading: boolean;
}
interface Option extends SelectProps {
mark: string;
}
const VIEW_TYPE = {
TABLE: "table",
CHART: "chart",
};
const SEARCH_TYPE = {
SEARCH: "search",
INIT: "init",
};
// hooks
const route = useRoute();
const router = useRouter();
const projectTag = shallowRef();
const projectVal = shallowRef();
const pageId = shallowRef(route.query.pageId);
const projectOptions = shallowRef<Option[]>();
const isDraggable = false;
const layoutList = computed(() => {
return ids.value.map((item, index) => {
// 当前是第几行
const row = Math.floor(index / 2);
// 当前是第几列ji
const col = index % 2;
return {
i: item?.id,
x: col,
y: row,
w: 1,
h: 3,
minH: 3,
...item,
};
});
});
const ids = ref<Item[]>([]);
const pLimit = PLimit(2);
onMounted(() => {
getProjectList();
});
const handleSingle = (info: ItemDetail, otherParams?: object) => {
getSinglePreview({ info, otherParams, type: SEARCH_TYPE.SEARCH });
};
const handleProjectChange = (value: string | number, option: Option) => {
projectTag.value = option.mark;
router.replace({
path: route.path,
query: {
projectTag: projectTag.value,
...route.query,
},
});
getPageInfoData();
};
// 请求
// 获取项目下拉
const getProjectList = () => {
getProjectDrop()
.then((res) => {
if (res.code === 200) {
projectOptions.value = res.data;
projectTag.value = res.data[0].mark;
projectVal.value = res.data[0].value;
getPageInfoData();
}
})
.catch(() => {
projectOptions.value = [];
})
.finally(() => {});
};
// 单个视图请求
const getSinglePreview = (data: {
info: ItemDetail;
otherParams?: object;
type?: string;
}) => {
const { info, otherParams, type } = data;
info.loading = true;
const params = { previewId: info.id, page: 1, perPage: 20, ...otherParams };
searchInfo(params)
.then((res) => {
if (res.code === 200) {
const data = res.data;
if (type === SEARCH_TYPE.SEARCH) {
// 只更新数据
switch (data.type) {
case VIEW_TYPE.TABLE:
info.data.data = data.data;
info.data.count = data.count;
break;
case VIEW_TYPE:
info.data.config = data.config;
break;
default:
break;
}
} else {
info.data = res.data;
}
}
})
.finally(() => {
info.loading = false;
});
};
// 获取页面信息所有的id
const getPageInfoData = () => {
getPageInfo({ mark: projectTag.value, page_id: pageId.value ?? "-1" })
.then((res) => {
if (res.code === 200) {
ids.value = res.data?.map((item: any) => {
return {
id: item.preview_id,
data: item,
loading: false,
};
});
getAllCardsData();
}
})
.finally(() => {});
};
const fetchFn = (delay: number, info: ItemDetail) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(info);
getSinglePreview({ info, type: SEARCH_TYPE.INIT });
}, delay);
});
};
const getAllCardsData = async () => {
let listDB = [];
for (let i in ids.value) {
listDB.push(pLimit(() => fetchFn(i === "0" ? 200 : 1000, ids.value[i])));
}
await Promise.all(listDB);
//此处的listDB就是最后整合的数据
};
</script>
<style lang="less" scoped>
.view-box {
height: 100%;
width: 100%;
min-height: 350px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 4px;
transition: all 0.3s;
&:hover {
box-shadow: 0 0 20px 0 #0a103205, 0 14px 40px 0 #0a103208,
0 20px 60px 0 #0a10320d;
}
.content {
padding: 10px;
}
}
.project {
margin-bottom: 10px;
}
.view-draggable {
height: auto;
min-height: 450px;
}
.vue-draggable-handle {
padding: 0 8px 8px 0;
border-radius: 10px;
cursor: pointer;
}
.vue-grid-item {
height: auto;
}
</style>

View File

@@ -0,0 +1,10 @@
import { get, post } from "@/utils/request";
interface PageInfoParams {
mark: string;
page_id: number | string;
}
export const getPageInfo = (data: PageInfoParams) =>
get({
url: "/api/v1/preview/get-preview-info",
params: data,
});