Merge branch 'feature/new-sys' into 'master'
悦码项目首次上线 See merge request workbench/y-code!12
This commit is contained in:
commit
7247ee9c13
@ -4,3 +4,5 @@ VITE_NODE_ENV = pre
|
|||||||
VITE_OA_BASEURL = https://oa-pre.shiyue.com
|
VITE_OA_BASEURL = https://oa-pre.shiyue.com
|
||||||
|
|
||||||
VITE_YCODE_BASEURL = https://custom-chart-pre-api.shiyue.com
|
VITE_YCODE_BASEURL = https://custom-chart-pre-api.shiyue.com
|
||||||
|
|
||||||
|
VITE_YCODE_BASEURL_FRONT = https://custom-chart.shiyue.com
|
||||||
|
@ -3,3 +3,5 @@ VITE_NODE_ENV = prod
|
|||||||
VITE_OA_BASEURL = https://oa.shiyuegame.com
|
VITE_OA_BASEURL = https://oa.shiyuegame.com
|
||||||
|
|
||||||
VITE_YCODE_BASEURL = https://custom-chart-api.shiyuegame.com
|
VITE_YCODE_BASEURL = https://custom-chart-api.shiyuegame.com
|
||||||
|
|
||||||
|
VITE_YCODE_BASEURL_FRONT = https://custom-chart.shiyuegame.com
|
||||||
|
@ -3,3 +3,5 @@ VITE_NODE_ENV = pre
|
|||||||
VITE_OA_BASEURL = https://oa-pre.shiyue.com
|
VITE_OA_BASEURL = https://oa-pre.shiyue.com
|
||||||
|
|
||||||
VITE_YCODE_BASEURL = https://custom-chart-pre-api.shiyue.com
|
VITE_YCODE_BASEURL = https://custom-chart-pre-api.shiyue.com
|
||||||
|
|
||||||
|
VITE_YCODE_BASEURL_FRONT = https://custom-chart.shiyue.com
|
||||||
|
@ -12,7 +12,7 @@ module.exports = {
|
|||||||
ecmaVersion: 'latest',
|
ecmaVersion: 'latest',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
semi: 2,
|
semi: 0,
|
||||||
'vue/multi-word-component-names': 0,
|
'vue/multi-word-component-names': 0,
|
||||||
indent: [
|
indent: [
|
||||||
2, 2, {
|
2, 2, {
|
||||||
|
10
components.d.ts
vendored
10
components.d.ts
vendored
@ -12,9 +12,9 @@ declare module 'vue' {
|
|||||||
AButton: typeof import('ant-design-vue/es')['Button']
|
AButton: typeof import('ant-design-vue/es')['Button']
|
||||||
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
||||||
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
||||||
|
ACol: typeof import('ant-design-vue/es')['Col']
|
||||||
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
|
AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
|
||||||
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
|
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
|
||||||
AEmpty: typeof import('ant-design-vue/es')['Empty']
|
|
||||||
AFloatButton: typeof import('ant-design-vue/es')['FloatButton']
|
AFloatButton: typeof import('ant-design-vue/es')['FloatButton']
|
||||||
AForm: typeof import('ant-design-vue/es')['Form']
|
AForm: typeof import('ant-design-vue/es')['Form']
|
||||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||||
@ -25,14 +25,18 @@ declare module 'vue' {
|
|||||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||||
APagination: typeof import('ant-design-vue/es')['Pagination']
|
APagination: typeof import('ant-design-vue/es')['Pagination']
|
||||||
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
||||||
|
ARadio: typeof import('ant-design-vue/es')['Radio']
|
||||||
|
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
|
||||||
|
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
||||||
|
ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
|
||||||
|
ARow: typeof import('ant-design-vue/es')['Row']
|
||||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
|
||||||
ASpace: typeof import('ant-design-vue/es')['Space']
|
ASpace: typeof import('ant-design-vue/es')['Space']
|
||||||
|
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||||
ATable: typeof import('ant-design-vue/es')['Table']
|
ATable: typeof import('ant-design-vue/es')['Table']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
Table: typeof import('./src/components/common/table.vue')['default']
|
|
||||||
YChart: typeof import('./src/components/common/y-chart.vue')['default']
|
YChart: typeof import('./src/components/common/y-chart.vue')['default']
|
||||||
YTable: typeof import('./src/components/common/y-table.vue')['default']
|
YTable: typeof import('./src/components/common/y-table.vue')['default']
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<title>悦码后台</title>
|
<title>悦码后台</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="y-code-app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
801
package-lock.json
generated
801
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -4,7 +4,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --mode staging",
|
"dev": "cross-env DEV_ENV=development vite --mode staging",
|
||||||
|
"pro": "cross-env DEV_ENV=development vite --mode production",
|
||||||
"build:pre": "vite build --mode staging",
|
"build:pre": "vite build --mode staging",
|
||||||
"build:pro": "vite build --mode production",
|
"build:pro": "vite build --mode production",
|
||||||
"type-check": "vue-tsc --build --force",
|
"type-check": "vue-tsc --build --force",
|
||||||
@ -15,10 +16,14 @@
|
|||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"ant-design-vue": "^4.1.2",
|
"ant-design-vue": "^4.1.2",
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.6.7",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"p-limit": "^6.1.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.4.15",
|
||||||
"vue-router": "^4.2.5"
|
"vue-grid-layout": "^3.0.0-beta1",
|
||||||
|
"vue-router": "^4.2.5",
|
||||||
|
"yargs-parser": "^21.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.3.3",
|
"@rushstack/eslint-patch": "^1.3.3",
|
||||||
@ -35,6 +40,7 @@
|
|||||||
"typescript": "~5.3.0",
|
"typescript": "~5.3.0",
|
||||||
"unplugin-vue-components": "^0.26.0",
|
"unplugin-vue-components": "^0.26.0",
|
||||||
"vite": "^5.0.11",
|
"vite": "^5.0.11",
|
||||||
|
"vite-plugin-qiankun": "^1.0.15",
|
||||||
"vue-tsc": "^1.8.27"
|
"vue-tsc": "^1.8.27"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { get } from '@/utils/request';
|
import { get } from "@/utils/request";
|
||||||
|
|
||||||
export interface UserInfoType {
|
export interface UserInfoType {
|
||||||
alias: string;
|
alias: string;
|
||||||
@ -15,8 +15,20 @@ export interface UserInfoType {
|
|||||||
username: string;
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserInfo = () => get<UserInfoType>({
|
interface DropListItem {
|
||||||
url: '/api/home/grade',
|
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",
|
||||||
|
});
|
||||||
|
@ -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
21
src/api/preview/index.ts
Normal 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,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
@ -1,34 +1,120 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chart-show-box">
|
<div class="chart-show-box">
|
||||||
<div class="switch-type">
|
<div class="chart-name">
|
||||||
|
<div class="title">{{ title }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-header">
|
||||||
|
<div class="chart-filter">
|
||||||
|
<div v-for="(item, index) in filterConfig" :key="index" class="filter-item">
|
||||||
|
<div>
|
||||||
|
<a-radio-group v-model:value="dateType" button-style="solid">
|
||||||
|
<a-radio-button value="day">日</a-radio-button>
|
||||||
|
<a-radio-button value="week">周</a-radio-button>
|
||||||
|
<a-radio-button value="month">月</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-range-picker v-if="item.type === 'time'" class="date-item" v-model:value="filterData[item.name]" :picker="rangePicker" @change="toFilt" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<a-radio-group v-model:value="chartType">
|
<a-radio-group v-model:value="chartType">
|
||||||
<a-radio-button value="line">折线图</a-radio-button>
|
<a-radio-button value="line">折线图</a-radio-button>
|
||||||
<a-radio-button value="bar">柱状图</a-radio-button>
|
<a-radio-button value="bar">柱状图</a-radio-button>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-wrap">
|
<div class="chart-wrap">
|
||||||
<Column v-if="chartType === 'bar'" />
|
<Column v-if="chartType === 'bar'" :config="currentChart" />
|
||||||
|
<Line v-if="chartType === 'line'" :config="currentChart" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { computed, ref, watch } from "vue";
|
||||||
import Line from "@/plugins/antv-g2plot/line.vue";
|
import Line from "@/plugins/antv-g2plot/line.vue";
|
||||||
import Column from "@/plugins/antv-g2plot/column.vue";
|
import Column from "@/plugins/antv-g2plot/column.vue";
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
chartCfg: {
|
chartCfg: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
filterConfig: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const emit = defineEmits(["toFilt"]);
|
||||||
|
|
||||||
const chartType = ref("line");
|
const chartType = ref("line");
|
||||||
|
const dateType = ref("day");
|
||||||
|
const filterData = ref({
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const rangePicker = computed(() => {
|
||||||
|
switch(dateType.value) {
|
||||||
|
case 'week':
|
||||||
|
return 'week';
|
||||||
|
case 'month':
|
||||||
|
return 'month';
|
||||||
|
default:
|
||||||
|
return 'date';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentChart = computed(() => {
|
||||||
|
return props.chartCfg[chartType.value];
|
||||||
|
})
|
||||||
|
|
||||||
|
const toFilt = () => {
|
||||||
|
const cloneFilter = _.cloneDeep(props.filterConfig);
|
||||||
|
const filter = cloneFilter
|
||||||
|
.filter((item) => {
|
||||||
|
return filterData.value[item.name] !== undefined && filterData.value[item.name] !== null;
|
||||||
|
})
|
||||||
|
.map((item) => {
|
||||||
|
return item.type === 'time' ? {
|
||||||
|
name: item.name,
|
||||||
|
type: item.type,
|
||||||
|
start_time: filterData.value[item.name][0].format('YYYY-MM-DD'),
|
||||||
|
end_time: filterData.value[item.name][1].format('YYYY-MM-DD'),
|
||||||
|
date_type: dateType.value,
|
||||||
|
} : {
|
||||||
|
name: item.name,
|
||||||
|
type: item.type,
|
||||||
|
value: filterData.value[item.name],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
emit('toFilt', {
|
||||||
|
filter,
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.chart-wrap {
|
.chart-wrap {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-name {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-item {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="y-table-container">
|
<div class="y-table-container">
|
||||||
|
<div class="y-table-name">
|
||||||
|
<div class="title">{{ title }}</div>
|
||||||
|
</div>
|
||||||
<div class="y-table-filter">
|
<div class="y-table-filter">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in filterConfig"
|
v-for="(item, index) in filterConfig"
|
||||||
@ -16,13 +19,14 @@
|
|||||||
@change="toFilt"
|
@change="toFilt"
|
||||||
></a-select>
|
></a-select>
|
||||||
<a-input
|
<a-input
|
||||||
v-if="item.type === 'text'"
|
v-else-if="item.type === 'text'"
|
||||||
class="input-item"
|
class="input-item"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
allow-clear
|
allow-clear
|
||||||
v-model:value="filterData[item.name]"
|
v-model:value="filterData[item.name]"
|
||||||
@change="toFilt"
|
@change="toFilt"
|
||||||
/>
|
/>
|
||||||
|
<a-range-picker v-else-if="item.type === 'time'" class="date-item" v-model:value="filterData[item.name]" @change="toFilt" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="y-table-content">
|
<div class="y-table-content">
|
||||||
@ -30,6 +34,7 @@
|
|||||||
:columns="columnConfig"
|
:columns="columnConfig"
|
||||||
:data-source="dataList"
|
:data-source="dataList"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
|
:scroll="{ x: 1000, y: `calc(100vh - 280px)` }"
|
||||||
size="small"
|
size="small"
|
||||||
bordered
|
bordered
|
||||||
></a-table>
|
></a-table>
|
||||||
@ -68,8 +73,12 @@ const props = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const emit = defineEmits(["handleFilt"]);
|
const emit = defineEmits(["toFilt"]);
|
||||||
|
|
||||||
const filterData = ref({});
|
const filterData = ref({});
|
||||||
|
|
||||||
@ -78,25 +87,19 @@ const pageState = reactive({
|
|||||||
perPage: 20,
|
perPage: 20,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.filterConfig,
|
|
||||||
(newVal) => {
|
|
||||||
console.log("newVal", newVal);
|
|
||||||
|
|
||||||
newVal.forEach((item) => {
|
|
||||||
filterData.value[item.name] = undefined;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const getData = () => {
|
const getData = () => {
|
||||||
const cloneFilter = _.cloneDeep(props.filterConfig);
|
const cloneFilter = _.cloneDeep(props.filterConfig);
|
||||||
const filter = cloneFilter
|
const filter = cloneFilter
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
return filterData.value[item.name] !== undefined;
|
return filterData.value[item.name] !== undefined && filterData.value[item.name] !== null;
|
||||||
})
|
})
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
return {
|
return item.type === 'time' && filterData.value[item.name] ? {
|
||||||
|
name: item.name,
|
||||||
|
type: item.type,
|
||||||
|
start_time: filterData.value[item.name][0].format('YYYY-MM-DD'),
|
||||||
|
end_time: filterData.value[item.name][1].format('YYYY-MM-DD'),
|
||||||
|
} : {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
value: filterData.value[item.name],
|
value: filterData.value[item.name],
|
||||||
@ -119,6 +122,13 @@ const pageChange = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.y-table-name {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
.y-table-filter {
|
.y-table-filter {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@ -126,14 +136,19 @@ const pageChange = () => {
|
|||||||
.filter-item {
|
.filter-item {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.input-item {
|
.input-item {
|
||||||
width: 180px;
|
width: 180px;
|
||||||
}
|
}
|
||||||
|
.date-item {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
.y-table-content {
|
.y-table-content {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
.pagination-box {
|
.pagination-box {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useUserInfoStore } from "@/stores/useUserInfoStore";
|
import { useUserInfoStore } from "@/stores/useUserInfoStore";
|
||||||
import { onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import Header from "./components/Header.vue";
|
import Header from "./components/Header.vue";
|
||||||
import Sider from "./components/Sider.vue";
|
import Sider from "./components/Sider.vue";
|
||||||
import {
|
import {
|
||||||
@ -9,6 +9,11 @@ import {
|
|||||||
FullscreenExitOutlined,
|
FullscreenExitOutlined,
|
||||||
} from "@ant-design/icons-vue";
|
} from "@ant-design/icons-vue";
|
||||||
import { useEventListener } from "@vueuse/core";
|
import { useEventListener } from "@vueuse/core";
|
||||||
|
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
|
||||||
|
|
||||||
|
const __POWERED_BY_QIANKUN__ = computed(() => {
|
||||||
|
return qiankunWindow.__POWERED_BY_QIANKUN__ || window.proxy?.__POWERED_BY_QIANKUN__
|
||||||
|
})
|
||||||
|
|
||||||
// const userInfoStore = useUserInfoStore();
|
// const userInfoStore = useUserInfoStore();
|
||||||
const isCollapsed = ref(false);
|
const isCollapsed = ref(false);
|
||||||
@ -34,7 +39,7 @@ const handleExitFullscreen = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="root">
|
<section v-if="!__POWERED_BY_QIANKUN__" class="root">
|
||||||
<section
|
<section
|
||||||
class="left-aside"
|
class="left-aside"
|
||||||
:class="{ 'left-aside-collapsed': isCollapsed }"
|
:class="{ 'left-aside-collapsed': isCollapsed }"
|
||||||
@ -68,6 +73,7 @@ const handleExitFullscreen = () => {
|
|||||||
</a-float-button>
|
</a-float-button>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
<router-view v-else />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
61
src/main.ts
61
src/main.ts
@ -1,12 +1,55 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp } from "vue";
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from "pinia";
|
||||||
import App from './App.vue';
|
import App from "./App.vue";
|
||||||
import router from './router';
|
import { createProjectRouter } from './router'
|
||||||
import './global.less';
|
import "./global.less";
|
||||||
|
import VueGridLayout from "vue-grid-layout"; // 引入layout
|
||||||
|
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
|
||||||
|
|
||||||
const app = createApp(App);
|
let app
|
||||||
|
function render(props: Object = {}) {
|
||||||
|
app = createApp(App);
|
||||||
|
const router = createProjectRouter(props.base)
|
||||||
|
app.use(router)
|
||||||
|
app.use(VueGridLayout);
|
||||||
|
app.use(createPinia())
|
||||||
|
app.mount("#y-code-app")
|
||||||
|
// const getContainer = () => {
|
||||||
|
// props.container ? props.container.querySelector('#y-code-container') : document.getElementById('y-code-container')
|
||||||
|
// }
|
||||||
|
// const container = getContainer()
|
||||||
|
// if (container) {
|
||||||
|
// app.mount(container)
|
||||||
|
// } else {
|
||||||
|
// window.addEventListener("DOMContentLoaded", () => {
|
||||||
|
// app.mount(getContainer())
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
app.use(createPinia());
|
const __POWERED_BY_QIANKUN__ = qiankunWindow.__POWERED_BY_QIANKUN__ || window.proxy?.__POWERED_BY_QIANKUN__
|
||||||
app.use(router);
|
|
||||||
|
if (__POWERED_BY_QIANKUN__) {
|
||||||
|
renderWithQiankun({
|
||||||
|
bootstrap() {
|
||||||
|
console.log('bootstrap')
|
||||||
|
return Promise.resolve()
|
||||||
|
},
|
||||||
|
mount(props) {
|
||||||
|
console.log('mount')
|
||||||
|
render(props)
|
||||||
|
return Promise.resolve()
|
||||||
|
},
|
||||||
|
unmount() {
|
||||||
|
console.log('unmount')
|
||||||
|
if (app) {
|
||||||
|
app.unmount()
|
||||||
|
}
|
||||||
|
return Promise.resolve()
|
||||||
|
},
|
||||||
|
update() {},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
render()
|
||||||
|
}
|
||||||
|
|
||||||
app.mount('#app');
|
|
||||||
|
@ -22,5 +22,5 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { container } = useChart(Column, props.config);
|
const { container } = useChart(Column, props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import { Line } from "@antv/g2plot";
|
import { Line } from "@antv/g2plot";
|
||||||
// hooks
|
// hooks
|
||||||
import useChart from "./useChart";
|
import useChart from "./useChart";
|
||||||
@ -22,5 +23,5 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { container } = useChart(Line, props.config);
|
const { container } = useChart(Line, props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -22,5 +22,5 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { container } = useChart(Pie, props.config);
|
const { container } = useChart(Pie, props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
|
||||||
export default function useChart(ChartClass, config) {
|
export default function useChart(ChartClass, props) {
|
||||||
const chart = ref(null); // 表格实例
|
const chart = ref(null); // 表格实例
|
||||||
const chartOptions = ref(null); // 图表配置
|
const chartOptions = ref(null); // 图表配置
|
||||||
const container = ref(null); // 渲染图表元素
|
const container = ref(null); // 渲染图表元素
|
||||||
const { onReady, onEvent } = config;
|
const { onReady, onEvent } = props.config;
|
||||||
|
|
||||||
// 全局事件侦听器
|
// 全局事件侦听器
|
||||||
let handler;
|
let handler;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
chartOptions.value = _.cloneDeep(config);
|
chartOptions.value = _.cloneDeep(props.config);
|
||||||
|
|
||||||
// 实例化图表
|
// 实例化图表
|
||||||
const chartInstance = new ChartClass(container.value, { ...config });
|
const chartInstance = new ChartClass(container.value, { ...props.config });
|
||||||
chartInstance.toDataURL = (type, encoderOptions) => {
|
chartInstance.toDataURL = (type, encoderOptions) => {
|
||||||
return toDataURL(type, encoderOptions);
|
return toDataURL(type, encoderOptions);
|
||||||
};
|
};
|
||||||
@ -46,7 +46,7 @@ export default function useChart(ChartClass, config) {
|
|||||||
|
|
||||||
// 配置更改时更新图表
|
// 配置更改时更新图表
|
||||||
watch(
|
watch(
|
||||||
() => config,
|
() => props.config,
|
||||||
(config) => {
|
(config) => {
|
||||||
const newConfig = _.cloneDeep(config);
|
const newConfig = _.cloneDeep(config);
|
||||||
chartOptions.value = newConfig;
|
chartOptions.value = newConfig;
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory, type Router } from 'vue-router';
|
||||||
import { titleGuard } from './guards';
|
import { titleGuard } from './guards';
|
||||||
import routeList from './routes';
|
import routeList from './routes';
|
||||||
|
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
|
||||||
|
|
||||||
const router = createRouter({
|
let router: Router | null = null
|
||||||
history: createWebHistory(''),
|
export const createProjectRouter = (base = '') => {
|
||||||
|
const __POWERED_BY_QIANKUN__ = qiankunWindow.__POWERED_BY_QIANKUN__ || window.proxy?.__POWERED_BY_QIANKUN__
|
||||||
|
router = createRouter({
|
||||||
|
history: createWebHistory(base || (__POWERED_BY_QIANKUN__ ? '/y-code-app/' : '')),
|
||||||
routes: routeList,
|
routes: routeList,
|
||||||
});
|
})
|
||||||
|
|
||||||
// 全局前置守卫
|
// 全局前置守卫
|
||||||
router.beforeEach(titleGuard);
|
router.beforeEach(titleGuard)
|
||||||
|
return router
|
||||||
|
}
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import Layout from '@/layout/index.vue';
|
import Layout from "@/layout/index.vue";
|
||||||
import { HomeOutlined, BarChartOutlined } from '@ant-design/icons-vue';
|
import {
|
||||||
import { h } from 'vue';
|
HomeOutlined,
|
||||||
import type { VNode, RendererNode, RendererElement } from 'vue';
|
BarChartOutlined,
|
||||||
|
AppstoreOutlined,
|
||||||
|
} from "@ant-design/icons-vue";
|
||||||
|
import { h } from "vue";
|
||||||
|
import type { VNode, RendererNode, RendererElement } from "vue";
|
||||||
|
|
||||||
export interface RouteType {
|
export interface RouteType {
|
||||||
path: string;
|
path: string;
|
||||||
@ -11,70 +15,96 @@ export interface RouteType {
|
|||||||
isMenu?: boolean;
|
isMenu?: boolean;
|
||||||
redirect?: string;
|
redirect?: string;
|
||||||
children: RouteType[];
|
children: RouteType[];
|
||||||
icon?: () => VNode<RendererNode, RendererElement, {
|
icon?: () => VNode<
|
||||||
|
RendererNode,
|
||||||
|
RendererElement,
|
||||||
|
{
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}>
|
}
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const routeList: RouteType[] = [
|
const routeList: RouteType[] = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: "/",
|
||||||
name: 'layout',
|
name: "layout",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
meta: { title: '首页' },
|
meta: { title: "首页" },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: "",
|
||||||
name: '-',
|
name: "-",
|
||||||
meta: {},
|
meta: {},
|
||||||
children: [],
|
children: [],
|
||||||
redirect: '/config-manage/project-cfg',
|
redirect: "/config-manage/project-cfg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/config-manage',
|
path: "/config-manage",
|
||||||
name: 'config-manage',
|
name: "config-manage",
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
meta: { title: '配置管理' },
|
meta: { title: "配置管理" },
|
||||||
icon: () => h(HomeOutlined),
|
icon: () => h(HomeOutlined),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'project-cfg',
|
path: "project-cfg",
|
||||||
name: 'project-cfg',
|
name: "project-cfg",
|
||||||
component: () => import('@/views/config-manage/project-cfg/index.vue'),
|
component: () =>
|
||||||
meta: { title: '项目配置' },
|
import("@/views/config-manage/project-cfg/index.vue"),
|
||||||
|
meta: { title: "项目配置" },
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'module-cfg',
|
path: "module-cfg",
|
||||||
name: 'module-cfg',
|
name: "module-cfg",
|
||||||
component: () => import('@/views/config-manage/module-cfg/index.vue'),
|
component: () =>
|
||||||
meta: { title: '数据表配置' },
|
import("@/views/config-manage/module-cfg/index.vue"),
|
||||||
|
meta: { title: "数据来源配置" },
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/view-all-manage',
|
path: "/view-all-manage",
|
||||||
name: 'view-all-manage',
|
name: "view-all-manage",
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
meta: { title: '视图管理' },
|
meta: { title: "视图管理" },
|
||||||
icon: () => h(BarChartOutlined),
|
icon: () => h(BarChartOutlined),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'view-list',
|
path: "view-list",
|
||||||
name: 'view-list',
|
name: "view-list",
|
||||||
component: () => import('@/views/view-all-manage/view-list/index.vue'),
|
component: () =>
|
||||||
meta: { title: '视图列表' },
|
import("@/views/view-all-manage/view-list/index.vue"),
|
||||||
|
meta: { title: "视图列表" },
|
||||||
isMenu: true,
|
isMenu: true,
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'create-view',
|
path: "create-view",
|
||||||
name: 'create-view',
|
name: "create-view",
|
||||||
component: () => import('@/views/view-all-manage/create-view/index.vue'),
|
component: () =>
|
||||||
meta: { title: '创建视图' },
|
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,
|
isMenu: true,
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
@ -12,11 +12,12 @@
|
|||||||
placeholder="请选择所属项目"
|
placeholder="请选择所属项目"
|
||||||
v-model:value="formData.project_id"
|
v-model:value="formData.project_id"
|
||||||
:options="projectSelect"
|
:options="projectSelect"
|
||||||
|
@change="toGetDbTable"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="数据表名称" name="modular_name">
|
<a-form-item label="数据来源" name="modular_name">
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="请输入数据表名称"
|
placeholder="请输入数据来源"
|
||||||
v-model:value="formData.modular_name"
|
v-model:value="formData.modular_name"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -27,26 +28,90 @@
|
|||||||
:unCheckedValue="0"
|
:unCheckedValue="0"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="展示类型" name="show_type_id">
|
<a-form-item label="数据源类型" name="original_type">
|
||||||
<a-select
|
<a-radio-group v-model:value="formData.original_type">
|
||||||
placeholder="请选择展示类型"
|
<a-radio :value="1">自定义</a-radio>
|
||||||
v-model:value="formData.show_type_id"
|
<a-radio :value="2">指定表</a-radio>
|
||||||
:options="showTypes"
|
</a-radio-group>
|
||||||
/>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="sql数据源" name="original_sql">
|
<a-form-item
|
||||||
|
v-if="formData.original_type === 1"
|
||||||
|
label="sql数据源"
|
||||||
|
name="original_sql"
|
||||||
|
>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="请输入sql数据源"
|
placeholder="请输入sql数据源"
|
||||||
v-model:value="formData.original_sql"
|
v-model:value="formData.original_sql"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
v-if="formData.original_type === 2"
|
||||||
|
label="数据表"
|
||||||
|
name="table"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
placeholder="请先选择项目再选择数据表"
|
||||||
|
v-model:value="formData.table"
|
||||||
|
:options="tableTypes"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库特殊配置" name="is_other_database">
|
||||||
|
<a-switch
|
||||||
|
v-model:checked="formData.is_other_database"
|
||||||
|
:checkedValue="1"
|
||||||
|
:unCheckedValue="0"
|
||||||
|
@change="isOtherChange"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<template v-if="formData.is_other_database">
|
||||||
|
<a-form-item label="数据库驱动" name="drive_type">
|
||||||
|
<a-radio-group v-model:value="formData.drive_type">
|
||||||
|
<a-radio :value="1">MySQL</a-radio>
|
||||||
|
<a-radio :value="2">Click House</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库地址" name="database_address">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入数据库地址"
|
||||||
|
v-model:value="formData.database_address"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库端口" name="database_port">
|
||||||
|
<a-input-number
|
||||||
|
placeholder="请输入数据库端口"
|
||||||
|
v-model:value="formData.database_port"
|
||||||
|
style="width: 200px"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库名称" name="database_name">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入数据库名称"
|
||||||
|
v-model:value="formData.database_name"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库用户" name="database_username">
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入数据库用户"
|
||||||
|
v-model:value="formData.database_username"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库密码" name="database_password">
|
||||||
|
<a-space>
|
||||||
|
<a-input
|
||||||
|
placeholder="请输入数据库密码"
|
||||||
|
v-model:value="formData.database_password"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { getShowTypeSelect } from "@/views/config-manage/module-cfg/service";
|
import { getDbTableSelect } from "@/views/config-manage/module-cfg/service";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
open: {
|
open: {
|
||||||
@ -70,20 +135,31 @@ const props = defineProps({
|
|||||||
const emit = defineEmits(["ok"]);
|
const emit = defineEmits(["ok"]);
|
||||||
const formRules = ref({
|
const formRules = ref({
|
||||||
modular_name: [
|
modular_name: [
|
||||||
{ required: true, message: "请输入数据表名称", trigger: "submit" },
|
{ required: true, message: "请输入数据来源", trigger: "submit" },
|
||||||
],
|
],
|
||||||
show_type_id: [{ required: true, message: "请选择", trigger: "submit" }],
|
// show_type_id: [{ required: true, message: "请选择", trigger: "submit" }],
|
||||||
|
original_type: [{ required: true, message: "请选择", trigger: "submit" }],
|
||||||
original_sql: [{ required: true, message: "请输入", trigger: "submit" }],
|
original_sql: [{ required: true, message: "请输入", trigger: "submit" }],
|
||||||
|
table: [{ required: true, message: "请选择", trigger: "submit" }],
|
||||||
});
|
});
|
||||||
|
|
||||||
const showTypes = ref([]);
|
const tableTypes = ref([]);
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
project_id: undefined,
|
project_id: undefined,
|
||||||
modular_name: undefined,
|
modular_name: undefined,
|
||||||
is_show: 0,
|
is_show: 0,
|
||||||
show_type_id: undefined,
|
original_type: 1, // 1 - 自定义,2 - 指定表
|
||||||
|
// show_type_id: undefined,
|
||||||
original_sql: undefined,
|
original_sql: undefined,
|
||||||
|
table: undefined,
|
||||||
|
is_other_database: 0,
|
||||||
|
drive_type: 1,
|
||||||
|
database_address: undefined,
|
||||||
|
database_port: undefined,
|
||||||
|
database_name: undefined,
|
||||||
|
database_username: undefined,
|
||||||
|
database_password: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -97,30 +173,53 @@ watch(
|
|||||||
project_id: newVal.project_id,
|
project_id: newVal.project_id,
|
||||||
modular_name: newVal.modular_name,
|
modular_name: newVal.modular_name,
|
||||||
is_show: newVal.is_show,
|
is_show: newVal.is_show,
|
||||||
show_type_id: newVal.show_type_id,
|
original_type: newVal.original_type,
|
||||||
|
// show_type_id: newVal.show_type_id,
|
||||||
original_sql: newVal.original_sql,
|
original_sql: newVal.original_sql,
|
||||||
|
table: newVal.table,
|
||||||
|
drive_type: newVal.drive_type,
|
||||||
|
is_other_database: newVal.is_other_database,
|
||||||
|
database_address: newVal.database_address,
|
||||||
|
database_port: newVal.database_port,
|
||||||
|
database_name: newVal.database_name,
|
||||||
|
database_username: newVal.database_username,
|
||||||
|
database_password: newVal.database_password,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
const toGetDbTable = () => {
|
||||||
toGetShowType();
|
getDbTableSelect({ projectId: formData.value.project_id }).then((res) => {
|
||||||
});
|
tableTypes.value = res.data;
|
||||||
|
|
||||||
const toGetShowType = () => {
|
|
||||||
getShowTypeSelect().then((res) => {
|
|
||||||
showTypes.value = res.data;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isOtherChange = (val) => {
|
||||||
|
formData.value.drive_type = val ? 1 : undefined
|
||||||
|
formData.value.database_address = undefined
|
||||||
|
formData.value.database_port = undefined
|
||||||
|
formData.value.database_name = undefined
|
||||||
|
formData.value.database_username = undefined
|
||||||
|
formData.value.database_password = undefined
|
||||||
|
}
|
||||||
|
|
||||||
const resetFormData = () => {
|
const resetFormData = () => {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
project_id: undefined,
|
project_id: undefined,
|
||||||
modular_name: undefined,
|
modular_name: undefined,
|
||||||
is_show: 0,
|
is_show: 0,
|
||||||
show_type_id: undefined,
|
original_type: 1, // 1 - 自定义,2 - 指定表
|
||||||
|
// show_type_id: undefined,
|
||||||
original_sql: undefined,
|
original_sql: undefined,
|
||||||
|
table: undefined,
|
||||||
|
is_other_database: 0,
|
||||||
|
drive_type: undefined,
|
||||||
|
database_address: undefined,
|
||||||
|
database_port: undefined,
|
||||||
|
database_name: undefined,
|
||||||
|
database_username: undefined,
|
||||||
|
database_password: undefined,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,18 +34,33 @@
|
|||||||
<a-input
|
<a-input
|
||||||
v-if="editableData[record.field_id]"
|
v-if="editableData[record.field_id]"
|
||||||
v-model:value="record[column.dataIndex]"
|
v-model:value="record[column.dataIndex]"
|
||||||
|
allow-clear
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
/>
|
/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ record[column.dataIndex] }}
|
{{ record[column.dataIndex] }}
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.dataIndex === 'field_numerical_name'">
|
||||||
|
<a-select
|
||||||
|
v-if="editableData[record.field_id]"
|
||||||
|
v-model:value="record.field_numerical_type_id"
|
||||||
|
:options="fieldNumTypeSel"
|
||||||
|
placeholder="请选择"
|
||||||
|
allow-clear
|
||||||
|
style="width: 160px">
|
||||||
|
</a-select>
|
||||||
|
<template v-else>
|
||||||
|
{{ record.field_numerical_name }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
<template v-if="column.dataIndex === 'field_type_name'">
|
<template v-if="column.dataIndex === 'field_type_name'">
|
||||||
<a-select
|
<a-select
|
||||||
v-if="editableData[record.field_id]"
|
v-if="editableData[record.field_id]"
|
||||||
v-model:value="record.field_type_id"
|
v-model:value="record.field_type_id"
|
||||||
:options="fieldTypeSel"
|
:options="fieldTypeSel"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
|
allow-clear
|
||||||
style="width: 160px"
|
style="width: 160px"
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
@ -64,6 +79,19 @@
|
|||||||
{{ record.is_search ? "是" : "否" }}
|
{{ record.is_search ? "是" : "否" }}
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="column.dataIndex === 'original_type'">
|
||||||
|
<a-select
|
||||||
|
v-if="editableData[record.field_id]"
|
||||||
|
placeholder="请选择"
|
||||||
|
v-model:value="record.original_type"
|
||||||
|
:options="originalTypes"
|
||||||
|
allow-clear
|
||||||
|
>
|
||||||
|
</a-select>
|
||||||
|
<template v-else>
|
||||||
|
{{ record.original_type_name }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
<template v-if="column.dataIndex === 'action'">
|
<template v-if="column.dataIndex === 'action'">
|
||||||
<a-space v-if="editableData[record.field_id]">
|
<a-space v-if="editableData[record.field_id]">
|
||||||
<a-button type="primary" size="small" @click="handleSave(record)"
|
<a-button type="primary" size="small" @click="handleSave(record)"
|
||||||
@ -93,9 +121,10 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref, watch } from "vue";
|
import { onMounted, reactive, ref, watch } from "vue";
|
||||||
import { viewCfgCols } from "@/views/config-manage/module-cfg/config";
|
import { viewCfgCols, originalTypes } from "@/views/config-manage/module-cfg/config";
|
||||||
import {
|
import {
|
||||||
getFieldTypeSelect,
|
getFieldTypeSelect,
|
||||||
|
getFieldNumSelect,
|
||||||
getFieldList,
|
getFieldList,
|
||||||
// deleteField,
|
// deleteField,
|
||||||
saveField,
|
saveField,
|
||||||
@ -117,6 +146,7 @@ const listLoading = ref(false);
|
|||||||
const fieldName = ref("");
|
const fieldName = ref("");
|
||||||
const dataList = ref([]);
|
const dataList = ref([]);
|
||||||
const fieldTypeSel = ref([]);
|
const fieldTypeSel = ref([]);
|
||||||
|
const fieldNumTypeSel = ref([]);
|
||||||
const pageState = reactive({
|
const pageState = reactive({
|
||||||
page: 1,
|
page: 1,
|
||||||
perPage: 20,
|
perPage: 20,
|
||||||
@ -135,15 +165,23 @@ watch(
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
toGetFieldTypes();
|
toGetFieldTypes();
|
||||||
|
toGetFieldNumSelect();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 字段类型下拉
|
// 字段搜索类型下拉
|
||||||
const toGetFieldTypes = () => {
|
const toGetFieldTypes = () => {
|
||||||
getFieldTypeSelect().then((res) => {
|
getFieldTypeSelect().then((res) => {
|
||||||
fieldTypeSel.value = res.data;
|
fieldTypeSel.value = res.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 字段类型下拉
|
||||||
|
const toGetFieldNumSelect = () => {
|
||||||
|
getFieldNumSelect().then((res) => {
|
||||||
|
fieldNumTypeSel.value = res.data;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
// 字段列表
|
// 字段列表
|
||||||
const toGetList = () => {
|
const toGetList = () => {
|
||||||
listLoading.value = true;
|
listLoading.value = true;
|
||||||
@ -172,9 +210,11 @@ const addField = () => {
|
|||||||
field_id: new Date().getTime() + "",
|
field_id: new Date().getTime() + "",
|
||||||
field_title: undefined,
|
field_title: undefined,
|
||||||
field_name: undefined,
|
field_name: undefined,
|
||||||
|
field_numerical_type_id: undefined,
|
||||||
is_search: 0,
|
is_search: 0,
|
||||||
field_type_id: undefined,
|
field_type_id: undefined,
|
||||||
belong_to_table: undefined,
|
belong_to_table: undefined,
|
||||||
|
original_type: undefined,
|
||||||
original_sql: undefined,
|
original_sql: undefined,
|
||||||
sort: 0,
|
sort: 0,
|
||||||
};
|
};
|
||||||
@ -200,21 +240,38 @@ const handleCancel = (record) => {
|
|||||||
|
|
||||||
const handleSave = (record) => {
|
const handleSave = (record) => {
|
||||||
const params = {
|
const params = {
|
||||||
field_id: record.field_id,
|
|
||||||
field_title: record.field_title,
|
|
||||||
field_name: record.field_name,
|
|
||||||
is_search: record.is_search,
|
is_search: record.is_search,
|
||||||
field_type_id: record.field_type_id,
|
field_type_id: record.field_type_id,
|
||||||
belong_to_table: record.belong_to_table,
|
|
||||||
original_sql: record.original_sql,
|
|
||||||
modular_id: props.modularId,
|
modular_id: props.modularId,
|
||||||
};
|
};
|
||||||
if (typeof params.field_id === "string") {
|
// 检验必填参数
|
||||||
// 新建
|
const validateFields = [
|
||||||
delete params.field_id;
|
{ field: 'field_title', msg: "请填写字段标题" },
|
||||||
|
{ field: 'field_name', msg: "请填写字段名称" },
|
||||||
|
{ field: 'field_numerical_type_id', msg: "请选择字段类型" },
|
||||||
|
{ field: 'belong_to_table', msg: "请填写关联表" },
|
||||||
|
{ field: 'original_type', msg: '请选择数据源类型' },
|
||||||
|
{ field: 'original_sql', msg: "请填写sql数据源" },
|
||||||
|
]
|
||||||
|
for(let i = 0; i < validateFields.length; i++) {
|
||||||
|
const curr = validateFields[i];
|
||||||
|
if (!record[curr.field]) {
|
||||||
|
message.error(curr.msg);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
params[curr.field] = record[curr.field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (record.is_search && !record.field_type_id) {
|
||||||
|
message.error("请选择搜索类型");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是编辑操作
|
||||||
|
if (typeof record.field_id === "number") {
|
||||||
params.field_id = record.field_id;
|
params.field_id = record.field_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveField(params).then(() => {
|
saveField(params).then(() => {
|
||||||
delete editableData[record.field_id];
|
delete editableData[record.field_id];
|
||||||
message.success("保存成功");
|
message.success("保存成功");
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
export const moduleCfgCols = [
|
export const moduleCfgCols = [
|
||||||
{ dataIndex: 'modular_id', title: '编号', align: 'center'},
|
{ dataIndex: 'modular_id', title: '编号', align: 'center'},
|
||||||
{ dataIndex: 'modular_name', title: '数据表名称', align: 'center'},
|
{ dataIndex: 'modular_name', title: '数据来源名称', align: 'center'},
|
||||||
{ dataIndex: 'project_name', title: '项目名称', align: 'center'},
|
{ dataIndex: 'project_name', title: '项目名称', align: 'center'},
|
||||||
{ dataIndex: 'is_show', title: '展示状态', align: 'center'},
|
{ dataIndex: 'is_show', title: '展示状态', align: 'center'},
|
||||||
{ dataIndex: 'show_type_handle', title: '展示类型', align: 'center'},
|
{ dataIndex: 'original_type_handle', title: '数据源类型', align: 'center'},
|
||||||
// { dataIndex: 'sort', title: '排序', align: 'center'},
|
// { dataIndex: 'sort', title: '排序', align: 'center'},
|
||||||
{ dataIndex: 'action', title: '操作', align: 'center'},
|
{ dataIndex: 'action', title: '操作', align: 'center'},
|
||||||
];
|
];
|
||||||
@ -11,10 +11,17 @@ export const moduleCfgCols = [
|
|||||||
export const viewCfgCols = [
|
export const viewCfgCols = [
|
||||||
{ dataIndex: 'field_name', title: '字段名称', align: 'center'},
|
{ dataIndex: 'field_name', title: '字段名称', align: 'center'},
|
||||||
{ dataIndex: 'field_title', title: '字段标题', align: 'center'},
|
{ dataIndex: 'field_title', title: '字段标题', align: 'center'},
|
||||||
{ dataIndex: 'field_type_name', title: '字段类型', align: 'center'},
|
{ dataIndex: 'field_numerical_name', title: '字段类型', align: 'center'},
|
||||||
|
{ dataIndex: 'field_type_name', title: '搜索类型', align: 'center'},
|
||||||
{ dataIndex: 'is_search', title: '是否可搜索', align: 'center'},
|
{ dataIndex: 'is_search', title: '是否可搜索', align: 'center'},
|
||||||
{ dataIndex: 'sort', title: '排序', align: 'center'},
|
{ dataIndex: 'sort', title: '排序', align: 'center'},
|
||||||
{ dataIndex: 'belong_to_table', title: '所属表名称', align: 'center'},
|
{ dataIndex: 'belong_to_table', title: '所属表名称', align: 'center'},
|
||||||
{ dataIndex: 'original_sql', title: 'sql数据源', align: 'center'},
|
{ dataIndex: 'original_type', title: '数据源类型', align: 'center'},
|
||||||
|
{ dataIndex: 'original_sql', title: '数据源', align: 'center', width: 400},
|
||||||
{ dataIndex: 'action', title: '操作', align: 'center'},
|
{ dataIndex: 'action', title: '操作', align: 'center'},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const originalTypes = [
|
||||||
|
{ label: 'sql', value: 1 },
|
||||||
|
{ label: 'json', value: 2 },
|
||||||
|
]
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<a-space>
|
<a-space>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="modularName"
|
v-model:value="modularName"
|
||||||
placeholder="请输入数据表名称"
|
placeholder="请输入数据来源名称"
|
||||||
allow-clear
|
allow-clear
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
@change="search"
|
@change="search"
|
||||||
|
@ -54,20 +54,30 @@ export function getProjectSelect() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 展示类型下拉
|
// 数据表源下拉
|
||||||
export function getShowTypeSelect() {
|
export function getDbTableSelect({ projectId }) {
|
||||||
return get({
|
return get({
|
||||||
url: `/api/v1/modular/get-show-type-drop`,
|
url: `/api/v1/modular/get-database-table-drop`,
|
||||||
|
params: {
|
||||||
|
project_id: projectId,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字段类型下拉
|
// 字段搜索类型下拉
|
||||||
export function getFieldTypeSelect() {
|
export function getFieldTypeSelect() {
|
||||||
return get({
|
return get({
|
||||||
url: `/api/v1/field/get-field-type-drop`,
|
url: `/api/v1/field/get-field-type-drop`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 字段类型下拉
|
||||||
|
export function getFieldNumSelect() {
|
||||||
|
return get({
|
||||||
|
url: `/api/v1/field/get-field-numerical-type-drop`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 获取字段列表
|
// 获取字段列表
|
||||||
export function getFieldList({ modularId, fieldName, page, perPage }) {
|
export function getFieldList({ modularId, fieldName, page, perPage }) {
|
||||||
return get({
|
return get({
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="项目标识" name="mark">
|
<a-form-item label="项目标识" name="mark">
|
||||||
<a-input placeholder="请输入项目标识,例如:oa" />
|
<a-input placeholder="请输入项目标识,例如:oa" v-model:value="formData.mark" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="展示状态" name="is_show">
|
<a-form-item label="展示状态" name="is_show">
|
||||||
<a-switch
|
<a-switch
|
||||||
@ -59,6 +59,12 @@
|
|||||||
>
|
>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="数据库驱动" name="drive_type">
|
||||||
|
<a-radio-group v-model:value="formData.drive_type">
|
||||||
|
<a-radio :value="1">MySQL</a-radio>
|
||||||
|
<a-radio :value="2">Click House</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
@ -98,12 +104,6 @@ const formRules = {
|
|||||||
database_name: [
|
database_name: [
|
||||||
{ required: true, message: "请输入数据库名称", trigger: "submit" },
|
{ required: true, message: "请输入数据库名称", trigger: "submit" },
|
||||||
],
|
],
|
||||||
database_username: [
|
|
||||||
{ required: true, message: "请输入数据库用户", trigger: "submit" },
|
|
||||||
],
|
|
||||||
database_password: [
|
|
||||||
{ required: true, message: "请输入数据库密码", trigger: "submit" },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
@ -116,6 +116,7 @@ const formData = ref({
|
|||||||
database_name: undefined,
|
database_name: undefined,
|
||||||
database_username: undefined,
|
database_username: undefined,
|
||||||
database_password: undefined,
|
database_password: undefined,
|
||||||
|
drive_type: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -138,6 +139,7 @@ const toCheckDbConnect = () => {
|
|||||||
database_address: formData.value.database_address,
|
database_address: formData.value.database_address,
|
||||||
database_username: formData.value.database_username,
|
database_username: formData.value.database_username,
|
||||||
database_password: formData.value.database_password,
|
database_password: formData.value.database_password,
|
||||||
|
drive_type: formData.value.drive_type,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
message.success(res.message);
|
message.success(res.message);
|
||||||
});
|
});
|
||||||
@ -149,8 +151,6 @@ const validateConnect = () => {
|
|||||||
database_name: "请输入数据库名称",
|
database_name: "请输入数据库名称",
|
||||||
database_port: "请输入数据库端口",
|
database_port: "请输入数据库端口",
|
||||||
database_address: "请输入数据库地址",
|
database_address: "请输入数据库地址",
|
||||||
database_username: "请输入数据库用户",
|
|
||||||
database_password: "请输入数据库密码",
|
|
||||||
};
|
};
|
||||||
for (const key in fields) {
|
for (const key in fields) {
|
||||||
if (!formData.value[key]) {
|
if (!formData.value[key]) {
|
||||||
@ -171,6 +171,7 @@ const resetFormData = () => {
|
|||||||
database_name: undefined,
|
database_name: undefined,
|
||||||
database_username: undefined,
|
database_username: undefined,
|
||||||
database_password: undefined,
|
database_password: undefined,
|
||||||
|
drive_type: 1,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
337
src/views/page-show-info/page-info/index,.vue
Normal file
337
src/views/page-show-info/page-info/index,.vue
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-view-wrapp">
|
||||||
|
<div v-if="!isInQiankun" class="project">
|
||||||
|
<span>项目: </span>
|
||||||
|
<a-select
|
||||||
|
style="min-width: 160px"
|
||||||
|
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) => {
|
||||||
|
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, watch } 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 { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
|
||||||
|
|
||||||
|
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 isInQiankun = computed(() => {
|
||||||
|
return qiankunWindow.__POWERED_BY_QIANKUN__ || window.proxy?.__POWERED_BY_QIANKUN__
|
||||||
|
})
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
watch(() => route.query.viewId, () => {
|
||||||
|
getPageInfoData()
|
||||||
|
})
|
||||||
|
|
||||||
|
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: {
|
||||||
|
...route.query,
|
||||||
|
projectTag: projectTag.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
getPageInfoData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 请求
|
||||||
|
|
||||||
|
// 获取项目下拉
|
||||||
|
const getProjectList = () => {
|
||||||
|
getProjectDrop()
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
projectOptions.value = res.data;
|
||||||
|
projectTag.value = route.query.projectTag || res.data[0].mark;
|
||||||
|
projectVal.value =
|
||||||
|
projectOptions.value?.find((item) => {
|
||||||
|
return item.mark === route.query.projectTag;
|
||||||
|
})?.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) {
|
||||||
|
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) {
|
||||||
|
if (route.query.viewId) {
|
||||||
|
ids.value = res.data?.filter((item: any) => {
|
||||||
|
return item.preview_id === Number(route.query.viewId);
|
||||||
|
}).map((item: any) => {
|
||||||
|
return {
|
||||||
|
id: item.preview_id,
|
||||||
|
data: item,
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
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>
|
10
src/views/page-show-info/page-info/service.ts
Normal file
10
src/views/page-show-info/page-info/service.ts
Normal 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,
|
||||||
|
});
|
@ -2,7 +2,7 @@
|
|||||||
<div class="normal-container">
|
<div class="normal-container">
|
||||||
<div class="view-create-box">
|
<div class="view-create-box">
|
||||||
<div class="left-box">
|
<div class="left-box">
|
||||||
<a-form :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="项目"
|
<a-form-item label="项目"
|
||||||
><a-select
|
><a-select
|
||||||
placeholder="请选择项目"
|
placeholder="请选择项目"
|
||||||
@ -11,7 +11,7 @@
|
|||||||
@change="onProjectChange"
|
@change="onProjectChange"
|
||||||
></a-select
|
></a-select
|
||||||
></a-form-item>
|
></a-form-item>
|
||||||
<a-form-item label="数据表">
|
<a-form-item label="数据来源">
|
||||||
<a-select
|
<a-select
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
:options="modularSel"
|
:options="modularSel"
|
||||||
@ -19,8 +19,16 @@
|
|||||||
@change="onModularChange"
|
@change="onModularChange"
|
||||||
></a-select>
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="字段">
|
<a-form-item label="展示类型">
|
||||||
<a-checkbox-group v-if="fieldList.length" v-model:value="fieldIds">
|
<a-select
|
||||||
|
placeholder="请选择展示类型"
|
||||||
|
:options="showTypeSel"
|
||||||
|
v-model:value="showTypeId"
|
||||||
|
@change="onShowTypeChange"
|
||||||
|
></a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="字段" v-if="fieldList.length">
|
||||||
|
<a-checkbox-group v-model:value="fieldIds">
|
||||||
<a-checkbox
|
<a-checkbox
|
||||||
v-for="(item, index) in fieldList"
|
v-for="(item, index) in fieldList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -28,14 +36,19 @@
|
|||||||
>{{ item.label }}</a-checkbox
|
>{{ item.label }}</a-checkbox
|
||||||
>
|
>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
<a-empty v-else description="暂无字段数据" />
|
</a-form-item>
|
||||||
|
<a-form-item label="x轴" v-if="xDataList.length">
|
||||||
|
<a-radio-group :options="xDataList" v-model:value="xDataId"></a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="y轴" v-if="yDataList.length">
|
||||||
|
<a-checkbox-group :options="yDataList" v-model:value="yDataId"></a-checkbox-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<a-button
|
<a-button
|
||||||
class="preview-btn"
|
class="preview-btn"
|
||||||
:loading="previewLoading"
|
:loading="previewLoading"
|
||||||
@click="toPreview"
|
@click="() => {toPreview({})}"
|
||||||
>预览</a-button
|
>预览</a-button
|
||||||
>
|
>
|
||||||
<a-button type="primary" @click="addViewName">点击保存</a-button>
|
<a-button type="primary" @click="addViewName">点击保存</a-button>
|
||||||
@ -43,9 +56,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right-box">
|
<div class="right-box">
|
||||||
<div class="y-table-container" v-if="previewData.type === 'table'">
|
<div class="y-table-container" v-if="previewData.type === 'table'">
|
||||||
|
<div class="y-table-name">
|
||||||
|
<div class="title">{{ previewData.preview_name }}</div>
|
||||||
|
</div>
|
||||||
<div class="y-table-filter">
|
<div class="y-table-filter">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in previewData.filterConfig"
|
v-for="item in previewData.filterConfig"
|
||||||
:key="item.name"
|
:key="item.name"
|
||||||
class="filter-item"
|
class="filter-item"
|
||||||
>
|
>
|
||||||
@ -67,6 +83,7 @@
|
|||||||
v-model:value="previewData.filterData[item.name]"
|
v-model:value="previewData.filterData[item.name]"
|
||||||
@change="toFilt"
|
@change="toFilt"
|
||||||
/>
|
/>
|
||||||
|
<a-range-picker v-if="item.type === 'time'" class="date-item" v-model:value="previewData.filterData[item.name]" @change="toFilt" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="y-table-content">
|
<div class="y-table-content">
|
||||||
@ -74,7 +91,7 @@
|
|||||||
:columns="previewData.columnConfig"
|
:columns="previewData.columnConfig"
|
||||||
:data-source="previewData.dataList"
|
:data-source="previewData.dataList"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
:scroll="{ x: 1200 }"
|
:scroll="{ x: 1000, y: `calc(100vh - 260px)` }"
|
||||||
size="small"
|
size="small"
|
||||||
bordered
|
bordered
|
||||||
></a-table>
|
></a-table>
|
||||||
@ -85,10 +102,11 @@
|
|||||||
:hide-on-single-page="false"
|
:hide-on-single-page="false"
|
||||||
size="small"
|
size="small"
|
||||||
class="pagination-box"
|
class="pagination-box"
|
||||||
@change="toPreview"
|
@change="() => { toPreview({}) }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<y-chart v-else-if="previewData.type === 'chart'" :chart-cfg="previewData.chartCfg" :filter-config="previewData.filter" @toFilt="() => {toPreview({})}"></y-chart>
|
||||||
<div class="preview-area" v-else>
|
<div class="preview-area" v-else>
|
||||||
<div><BarChartOutlined /></div>
|
<div><BarChartOutlined /></div>
|
||||||
<div>预览区</div>
|
<div>预览区</div>
|
||||||
@ -113,16 +131,30 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from "vue";
|
import { onMounted, reactive, ref } from "vue";
|
||||||
import { getProModularField, preview, saveView } from "./service";
|
import {
|
||||||
|
getProModularField,
|
||||||
|
preview,
|
||||||
|
saveView,
|
||||||
|
getShowTypeSelect,
|
||||||
|
getFieldOpts,
|
||||||
|
} from "./service";
|
||||||
import { message } from "ant-design-vue";
|
import { message } from "ant-design-vue";
|
||||||
import { BarChartOutlined } from "@ant-design/icons-vue";
|
import { BarChartOutlined } from "@ant-design/icons-vue";
|
||||||
|
import yChart from "@/components/common/y-chart.vue";
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
const projectSel = ref([]);
|
const projectSel = ref([]); // 项目下拉
|
||||||
const modularSel = ref([]);
|
const modularSel = ref([]) // 数据来源下拉
|
||||||
const fieldList = ref([]);
|
const showTypeSel = ref([]); // 展示类型下拉
|
||||||
|
const fieldList = ref([]); // 字段列表
|
||||||
|
const xDataList = ref([]); // x轴数据列表
|
||||||
|
const yDataList = ref([]); // y轴数据列表
|
||||||
const projectId = ref();
|
const projectId = ref();
|
||||||
const modularId = ref();
|
const modularId = ref();
|
||||||
|
const showTypeId = ref();
|
||||||
const fieldIds = ref([]);
|
const fieldIds = ref([]);
|
||||||
|
const xDataId = ref();
|
||||||
|
const yDataId = ref();
|
||||||
|
|
||||||
const previewLoading = ref(false);
|
const previewLoading = ref(false);
|
||||||
const nameVisible = ref(false);
|
const nameVisible = ref(false);
|
||||||
@ -134,6 +166,8 @@ const previewData = reactive({
|
|||||||
columnConfig: [], // 表格表头
|
columnConfig: [], // 表格表头
|
||||||
dataList: [], // 表格数据
|
dataList: [], // 表格数据
|
||||||
filterData: {},
|
filterData: {},
|
||||||
|
config: {},
|
||||||
|
filter: [],
|
||||||
page: 1,
|
page: 1,
|
||||||
perPage: 20,
|
perPage: 20,
|
||||||
total: 0,
|
total: 0,
|
||||||
@ -141,6 +175,7 @@ const previewData = reactive({
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
toGetProModularField();
|
toGetProModularField();
|
||||||
|
toGetShowTypes();
|
||||||
});
|
});
|
||||||
|
|
||||||
const toGetProModularField = () => {
|
const toGetProModularField = () => {
|
||||||
@ -149,51 +184,117 @@ const toGetProModularField = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取展示类型下拉
|
||||||
|
const toGetShowTypes = () => {
|
||||||
|
getShowTypeSelect().then((res) => {
|
||||||
|
showTypeSel.value = res.data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取字段列表
|
||||||
|
const toGetFieldOpts = () => {
|
||||||
|
getFieldOpts({
|
||||||
|
modularId: modularId.value,
|
||||||
|
showTypeId: showTypeId.value,
|
||||||
|
}).then((res) => {
|
||||||
|
fieldList.value = res.data.list ? tranformList(res.data.list) : [];
|
||||||
|
xDataList.value = res.data.x_data ? tranformList(res.data.x_data) : [];
|
||||||
|
yDataList.value = res.data.y_data ? tranformList(res.data.y_data) : [];
|
||||||
|
if (!fieldList.value.length) {
|
||||||
|
fieldIds.value = [];
|
||||||
|
} else {
|
||||||
|
xDataId.value = undefined;
|
||||||
|
yDataId.value = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onProjectChange = (val) => {
|
const onProjectChange = (val) => {
|
||||||
|
// 重置数据
|
||||||
const target = projectSel.value.find((item) => item.value === val);
|
const target = projectSel.value.find((item) => item.value === val);
|
||||||
modularSel.value = target.child;
|
modularSel.value = target.child;
|
||||||
modularId.value = undefined;
|
modularId.value = undefined;
|
||||||
|
resetSelectData();
|
||||||
|
resetPreviewData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onModularChange = () => {
|
||||||
|
resetSelectData();
|
||||||
|
resetPreviewData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onShowTypeChange = () => {
|
||||||
|
toGetFieldOpts();
|
||||||
|
};
|
||||||
|
|
||||||
|
const tranformList = (list) => {
|
||||||
|
return list.map((item) => {
|
||||||
|
return {
|
||||||
|
label: item.field_name,
|
||||||
|
value: item.field_id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置配置数据
|
||||||
|
const resetSelectData = () => {
|
||||||
|
showTypeId.value = undefined
|
||||||
fieldList.value = [];
|
fieldList.value = [];
|
||||||
fieldIds.value = [];
|
fieldIds.value = [];
|
||||||
resetPreviewData();
|
xDataList.value = [];
|
||||||
};
|
yDataList.value = [];
|
||||||
|
xDataId.value = undefined;
|
||||||
const onModularChange = (val) => {
|
yDataId.value = [];
|
||||||
const target = modularSel.value.find((item) => item.value === val);
|
}
|
||||||
fieldList.value = target.child;
|
|
||||||
resetPreviewData();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// 重置预览数据
|
||||||
const resetPreviewData = () => {
|
const resetPreviewData = () => {
|
||||||
previewData.type = "";
|
previewData.type = "";
|
||||||
previewData.filterConfig = [];
|
previewData.filterConfig = [];
|
||||||
previewData.columnConfig = [];
|
previewData.columnConfig = [];
|
||||||
previewData.dataList = [];
|
previewData.dataList = [];
|
||||||
previewData.filterData = {};
|
previewData.filterData = {};
|
||||||
|
previewData.config = {};
|
||||||
previewData.page = 1;
|
previewData.page = 1;
|
||||||
previewData.perPage = 20;
|
previewData.perPage = 20;
|
||||||
previewData.total = 0;
|
previewData.total = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const toPreview = () => {
|
// 请求预览数据
|
||||||
|
const toPreview = ({filter}) => {
|
||||||
previewLoading.value = true;
|
previewLoading.value = true;
|
||||||
const filter = previewData.filterConfig
|
let filterData
|
||||||
|
if (!filter) {
|
||||||
|
const cloneFilter = _.cloneDeep(previewData.filterConfig)
|
||||||
|
filterData = cloneFilter
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
return previewData.filterData[item.name] !== undefined;
|
return previewData.filterData[item.name] !== undefined && previewData.filterData[item.name] !== null;
|
||||||
})
|
})
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
return {
|
return item.type === 'time' && previewData.filterData[item.name] ? {
|
||||||
|
name: item.name,
|
||||||
|
type: item.type,
|
||||||
|
start_time: previewData.filterData[item.name][0].format('YYYY-MM-DD'),
|
||||||
|
end_time: previewData.filterData[item.name][1].format('YYYY-MM-DD'),
|
||||||
|
} : {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
value: previewData.filterData[item.name],
|
value: previewData.filterData[item.name],
|
||||||
};
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
filterData = filter;
|
||||||
|
}
|
||||||
|
|
||||||
preview({
|
preview({
|
||||||
modularId: modularId.value,
|
modularId: modularId.value,
|
||||||
fieldIds: fieldIds.value.toString(),
|
fieldIds: fieldIds.value.toString(),
|
||||||
page: previewData.page,
|
page: previewData.page,
|
||||||
perPage: previewData.perPage,
|
perPage: previewData.perPage,
|
||||||
filter,
|
filter: filterData,
|
||||||
|
showTypeId: showTypeId.value,
|
||||||
|
xDataId: xDataId.value?.toString(),
|
||||||
|
yDataId: yDataId.value?.toString(),
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
previewData.type = res.data.type;
|
previewData.type = res.data.type;
|
||||||
@ -207,6 +308,9 @@ const toPreview = () => {
|
|||||||
previewData.columnConfig = res.data.header;
|
previewData.columnConfig = res.data.header;
|
||||||
previewData.dataList = res.data.data;
|
previewData.dataList = res.data.data;
|
||||||
previewData.total = res.data.count;
|
previewData.total = res.data.count;
|
||||||
|
} else {
|
||||||
|
previewData.chartCfg = res.data.config;
|
||||||
|
previewData.filter = res.data.filter;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@ -228,15 +332,18 @@ const toSaveView = () => {
|
|||||||
modularId: modularId.value,
|
modularId: modularId.value,
|
||||||
fieldIds: fieldIds.value.toString(),
|
fieldIds: fieldIds.value.toString(),
|
||||||
previewName: previewName.value,
|
previewName: previewName.value,
|
||||||
|
showTypeId: showTypeId.value,
|
||||||
|
xDataId: xDataId.value?.toString(),
|
||||||
|
yDataId: yDataId.value?.toString(),
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
message.success("保存成功");
|
message.success("保存成功,可前往视图列表查看");
|
||||||
nameVisible.value = false;
|
nameVisible.value = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const toFilt = () => {
|
const toFilt = () => {
|
||||||
previewData.page = 1;
|
previewData.page = 1;
|
||||||
toPreview();
|
toPreview({});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -282,7 +389,12 @@ const toFilt = () => {
|
|||||||
font-size: 100px;
|
font-size: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.y-table-name {
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
.y-table-filter {
|
.y-table-filter {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@ -290,10 +402,14 @@ const toFilt = () => {
|
|||||||
.filter-item {
|
.filter-item {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.input-item {
|
.input-item {
|
||||||
width: 180px;
|
width: 180px;
|
||||||
}
|
}
|
||||||
|
.date-item {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
.y-table-content {
|
.y-table-content {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,26 @@ export function getProModularField() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 展示类型下拉
|
||||||
|
export function getShowTypeSelect() {
|
||||||
|
return get({
|
||||||
|
url: `/api/v1/modular/get-show-type-drop`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字段列表
|
||||||
|
export function getFieldOpts({ modularId, showTypeId }) {
|
||||||
|
return get({
|
||||||
|
url: "/api/v1/preview/get-preview-field",
|
||||||
|
params: {
|
||||||
|
modular_id: modularId,
|
||||||
|
show_type_id: showTypeId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 预览
|
// 预览
|
||||||
export function preview({ modularId, fieldIds, page, perPage, filter }) {
|
export function preview({ modularId, fieldIds, page, perPage, filter, showTypeId, xDataId, yDataId }) {
|
||||||
return post({
|
return post({
|
||||||
url: "api/v1/preview/view",
|
url: "api/v1/preview/view",
|
||||||
data: {
|
data: {
|
||||||
@ -17,18 +35,24 @@ export function preview({ modularId, fieldIds, page, perPage, filter }) {
|
|||||||
page,
|
page,
|
||||||
per_page: perPage,
|
per_page: perPage,
|
||||||
filter,
|
filter,
|
||||||
|
show_type_id: showTypeId,
|
||||||
|
x_data_id: xDataId,
|
||||||
|
y_data_id: yDataId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击保存
|
// 点击保存
|
||||||
export function saveView({ modularId, fieldIds, previewName }) {
|
export function saveView({ modularId, fieldIds, previewName, showTypeId, xDataId, yDataId }) {
|
||||||
return post({
|
return post({
|
||||||
url: "api/v1/preview/save",
|
url: "api/v1/preview/save",
|
||||||
data: {
|
data: {
|
||||||
modular_id: modularId,
|
modular_id: modularId,
|
||||||
field_ids: fieldIds,
|
field_ids: fieldIds,
|
||||||
preview_name: previewName,
|
preview_name: previewName,
|
||||||
|
show_type_id: showTypeId,
|
||||||
|
x_data_id: xDataId,
|
||||||
|
y_data_id: yDataId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="normal-container">
|
<div class="normal-container">
|
||||||
<div class="view-list-box">
|
<div class="view-list-box">
|
||||||
<div class="left-box">
|
<div class="left-box">
|
||||||
<a-form :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
<a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-item label="项目">
|
<a-form-item label="项目">
|
||||||
<a-select
|
<a-select
|
||||||
:options="projectSel"
|
:options="projectSel"
|
||||||
@ -11,11 +11,11 @@
|
|||||||
@change="onProjectChange"
|
@change="onProjectChange"
|
||||||
></a-select>
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="数据表">
|
<a-form-item label="数据来源">
|
||||||
<a-select
|
<a-select
|
||||||
:options="modularSel"
|
:options="modularSel"
|
||||||
v-model:value="modularId"
|
v-model:value="modularId"
|
||||||
placeholder="请选择数据表"
|
placeholder="请先选好项目再选择"
|
||||||
@change="onModularChange"
|
@change="onModularChange"
|
||||||
></a-select>
|
></a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@ -73,16 +73,18 @@
|
|||||||
<div class="right-box">
|
<div class="right-box">
|
||||||
<y-table
|
<y-table
|
||||||
v-if="selectViewInfo.type === 'table'"
|
v-if="selectViewInfo.type === 'table'"
|
||||||
:filterConfig="selectViewInfo.filter"
|
:filter-config="selectViewInfo.filter"
|
||||||
:dataList="selectViewInfo.data"
|
:data-list="selectViewInfo.data"
|
||||||
:columnConfig="selectViewInfo.header"
|
:column-config="selectViewInfo.header"
|
||||||
:total="selectViewInfo.count"
|
:total="selectViewInfo.count"
|
||||||
|
:title="selectViewInfo.preview_name"
|
||||||
@toFilt="
|
@toFilt="
|
||||||
(params) => {
|
(params) => {
|
||||||
toGetViewInfo(params);
|
toGetViewInfo(params);
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
<y-chart v-else-if="selectViewInfo.type === 'chart'" :chartCfg="selectViewInfo.config" :title="selectViewInfo.preview_name" :filter-config="selectViewInfo.filter" @toFilt="toGetViewInfo" />
|
||||||
<div class="preview-area" v-else>
|
<div class="preview-area" v-else>
|
||||||
<div><BarChartOutlined /></div>
|
<div><BarChartOutlined /></div>
|
||||||
<div>展示区</div>
|
<div>展示区</div>
|
||||||
@ -109,6 +111,11 @@ const selectedRowId = ref();
|
|||||||
const selectViewInfo = ref({
|
const selectViewInfo = ref({
|
||||||
type: "",
|
type: "",
|
||||||
filter: [],
|
filter: [],
|
||||||
|
config: {
|
||||||
|
line: {
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const pageState = reactive({
|
const pageState = reactive({
|
||||||
@ -182,6 +189,7 @@ const toDelete = (previewId) => {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border-right: 1px solid #ddd;
|
border-right: 1px solid #ddd;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.ant-table-row:hover) {
|
:deep(.ant-table-row:hover) {
|
||||||
|
@ -4,10 +4,41 @@ import vue from '@vitejs/plugin-vue';
|
|||||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||||
import Components from 'unplugin-vue-components/vite';
|
import Components from 'unplugin-vue-components/vite';
|
||||||
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
|
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';
|
||||||
import { server } from 'typescript';
|
import qiankun from 'vite-plugin-qiankun'
|
||||||
|
import yargsParser from 'yargs-parser'
|
||||||
|
|
||||||
|
const argv = yargsParser(process.argv.slice(2))
|
||||||
|
|
||||||
|
console.log(process.env.DEV_ENV)
|
||||||
|
|
||||||
|
let base: string
|
||||||
|
switch (argv.mode) {
|
||||||
|
case 'staging':
|
||||||
|
case 'test':
|
||||||
|
base = 'https://custom-chart.shiyue.com/'
|
||||||
|
break
|
||||||
|
case 'production':
|
||||||
|
base = 'https://custom-chart.shiyuegame.com/'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
base = 'http://localhost:8080/'
|
||||||
|
}
|
||||||
|
if (process.env.DEV_ENV === 'development') {
|
||||||
|
base = 'http://localhost:8080/'
|
||||||
|
}
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
sourcemap: false,
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
assetFileNames: '[name]-ycode-[hash:8].[ext]',
|
||||||
|
chunkFileNames: '[name]-ycode-[hash:8].js',
|
||||||
|
entryFileNames: '[name]-ycode-[hash:8].js',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
vueJsx(),
|
vueJsx(),
|
||||||
@ -16,14 +47,20 @@ export default defineConfig({
|
|||||||
importStyle: 'less',
|
importStyle: 'less',
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
|
qiankun('y-code-app', { useDevMode: process.env.DEV_ENV === 'development' }),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
base,
|
||||||
|
define: {
|
||||||
|
_BASE_HOST_: `'${base}'`,
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
hmr: true,
|
hmr: true,
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
|
port: 8080,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user