初始版本提交
This commit is contained in:
183
src/views/activereport/design/components/Designer.vue
Normal file
183
src/views/activereport/design/components/Designer.vue
Normal file
@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<div id="designer-host" class="design-box">
|
||||
<a-button class="button-item" @click.stop="back" type="primary">返回</a-button>
|
||||
<Designer
|
||||
ref="designRef"
|
||||
:language="'zh'"
|
||||
:onSave="onSave"
|
||||
:onSaveAs="onSaveAs"
|
||||
:onOpen="onOpen"
|
||||
:onCreate="onCreate"
|
||||
:onRender="onRender"
|
||||
:onOpenFileMenu="onOpenFileMenu"
|
||||
/>
|
||||
<Viewer v-if="show" :content="viewContent" />
|
||||
<a-modal
|
||||
:visible="open"
|
||||
title="修改文件名"
|
||||
:maskClosable="false"
|
||||
:width="400"
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
@ok="save"
|
||||
@cancel="closeSaveModel"
|
||||
>
|
||||
<div class="model-box">
|
||||
<a-form
|
||||
:model="formState"
|
||||
name="basic"
|
||||
:label-col="{ span: 4 }"
|
||||
:wrapper-col="{ span: 20 }"
|
||||
autocomplete="off"
|
||||
@finish="save"
|
||||
>
|
||||
<a-form-item
|
||||
label="文件名"
|
||||
name="name"
|
||||
:rules="[{ required: true, message: '请输入文件名' }]"
|
||||
>
|
||||
<a-input v-model:value="formState.name" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script language="ts" setup>
|
||||
import { Designer } from '@grapecity/activereports-vue';
|
||||
import '@grapecity/activereports/styles/ar-js-ui.css';
|
||||
import '@grapecity/activereports/styles/ar-js-designer.css';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import '@grapecity/activereports-localization/dist/designer/zh-locale';
|
||||
import Viewer from './../../viewer//components/Viewer.vue';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { addProfessionalReport, updateProfessionalReport } from '/@/api/system/report';
|
||||
const { t } = useI18n();
|
||||
const { notification } = useMessage();
|
||||
const designRef = ref();
|
||||
const open = ref(false);
|
||||
const show = ref(false);
|
||||
const viewContent = ref('');
|
||||
const formState = reactive({
|
||||
name: '',
|
||||
info: {},
|
||||
});
|
||||
let props = defineProps({
|
||||
id: String,
|
||||
fileJsonStr: String,
|
||||
});
|
||||
let emits = defineEmits(['close']);
|
||||
onMounted(() => {
|
||||
if (props.id) {
|
||||
let reportObj = JSON.parse(props.fileJsonStr);
|
||||
formState.name = reportObj.displayName;
|
||||
formState.info = reportObj;
|
||||
designRef.value.setReport(reportObj);
|
||||
}
|
||||
});
|
||||
const getJson = async () => {
|
||||
const res = await window.showOpenFilePicker();
|
||||
const [fh] = res;
|
||||
const file = await fh.getFile();
|
||||
return { name: file.name.split('.')[0], definition: JSON.parse(await file.text()) };
|
||||
};
|
||||
const onCreate = () => {
|
||||
console.log('onCreate', info);
|
||||
};
|
||||
const onOpen = async () => {
|
||||
const obj = await getJson();
|
||||
return Promise.resolve(obj);
|
||||
};
|
||||
const onRender = (info) => {
|
||||
viewContent.value = JSON.stringify(info);
|
||||
show.value = true;
|
||||
};
|
||||
const onSave = (info) => {
|
||||
openSaveModel(info);
|
||||
};
|
||||
const onSaveAs = (info) => {
|
||||
openSaveModel(info);
|
||||
};
|
||||
const onOpenFileMenu = (info) => {
|
||||
console.log('onOpenFileMenu', info);
|
||||
};
|
||||
function openSaveModel(info) {
|
||||
formState.name = info.displayName;
|
||||
formState.info = info;
|
||||
open.value = true;
|
||||
}
|
||||
function closeSaveModel() {
|
||||
open.value = false;
|
||||
}
|
||||
function back() {
|
||||
if (show.value) {
|
||||
viewContent.value = '';
|
||||
show.value = false;
|
||||
} else {
|
||||
backToIndex();
|
||||
}
|
||||
}
|
||||
function backToIndex() {
|
||||
closeSaveModel();
|
||||
emits('close');
|
||||
}
|
||||
async function save() {
|
||||
formState.info.displayName = formState.name;
|
||||
try {
|
||||
let res = false;
|
||||
if (props.id) {
|
||||
res = await updateProfessionalReport({
|
||||
id: props.id,
|
||||
name: formState.name,
|
||||
fileJson: JSON.stringify(formState.info),
|
||||
});
|
||||
} else {
|
||||
res = await addProfessionalReport({
|
||||
name: formState.name,
|
||||
fileJson: JSON.stringify(formState.info),
|
||||
});
|
||||
}
|
||||
if (res) {
|
||||
notification.success({
|
||||
message: t('提示'),
|
||||
description: t('成功!'),
|
||||
}); //提示消息
|
||||
backToIndex();
|
||||
}
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: t('提示'),
|
||||
description: t('失败!'),
|
||||
}); //提示消息
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
#viewer-host {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.design-box {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.button-item {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
top: 40px;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.model-box {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
:deep(.model-box) {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
138
src/views/activereport/design/index.vue
Normal file
138
src/views/activereport/design/index.vue
Normal file
@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<PageWrapper dense fixed-height contentFullHeight>
|
||||
<BasicTable @register="registerTable" v-if="!showDesigner">
|
||||
<template #toolbar>
|
||||
<a-button type="primary" @click="handleCreate" v-auth="'report-design:add'">
|
||||
{{ t('新增报表') }}
|
||||
</a-button>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
icon: 'clarity:note-edit-line',
|
||||
auth: 'report-design:edit',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
{
|
||||
icon: 'ant-design:delete-outlined',
|
||||
auth: 'report-design:delete',
|
||||
color: 'error',
|
||||
popConfirm: {
|
||||
title: t('是否确认删除'),
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<Designer
|
||||
v-if="showDesigner"
|
||||
:id="designData.id"
|
||||
:file-json-str="designData.fileJsonStr"
|
||||
@close="handleClose"
|
||||
/>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { BasicTable, useTable, TableAction, FormSchema, BasicColumn } from '/@/components/Table';
|
||||
import { getProfessionalPageList, deleteProfessionalReport } from '/@/api/system/report';
|
||||
import Designer from './components/Designer.vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
const { t } = useI18n();
|
||||
const columns: BasicColumn[] = [
|
||||
{
|
||||
title: t('文件名'),
|
||||
dataIndex: 'name',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
title: t('创建时间'),
|
||||
dataIndex: 'createDate',
|
||||
align: 'left',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
title: t('修改时间'),
|
||||
dataIndex: 'modifyDate',
|
||||
align: 'left',
|
||||
width: 300,
|
||||
},
|
||||
];
|
||||
|
||||
const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'keyword',
|
||||
label: t('关键字'),
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
componentProps: {
|
||||
placeholder: t('请输入关键字'),
|
||||
},
|
||||
},
|
||||
];
|
||||
const designData = reactive({
|
||||
fileJsonStr: '',
|
||||
id: '',
|
||||
});
|
||||
const { notification } = useMessage();
|
||||
|
||||
const [registerTable, { reload }] = useTable({
|
||||
title: t('报表列表'),
|
||||
api: getProfessionalPageList,
|
||||
columns,
|
||||
formConfig: {
|
||||
rowProps: {
|
||||
gutter: 16,
|
||||
},
|
||||
schemas: searchFormSchema,
|
||||
showResetButton: false,
|
||||
},
|
||||
|
||||
useSearchForm: true,
|
||||
showTableSetting: true,
|
||||
striped: false,
|
||||
|
||||
actionColumn: {
|
||||
width: 80,
|
||||
title: t('操作'),
|
||||
dataIndex: 'action',
|
||||
slots: { customRender: 'action' },
|
||||
fixed: undefined,
|
||||
},
|
||||
tableSetting: {
|
||||
size: false,
|
||||
setting: false,
|
||||
},
|
||||
});
|
||||
|
||||
const showDesigner = ref<boolean>(false);
|
||||
|
||||
function handleCreate() {
|
||||
designData.id = '';
|
||||
designData.fileJsonStr = '';
|
||||
showDesigner.value = true;
|
||||
}
|
||||
|
||||
function handleEdit(record: Recordable) {
|
||||
designData.id = record.id;
|
||||
designData.fileJsonStr = record.fileJson;
|
||||
showDesigner.value = true;
|
||||
}
|
||||
function handleClose() {
|
||||
showDesigner.value = false;
|
||||
}
|
||||
function handleDelete(record: Recordable) {
|
||||
deleteProfessionalReport(record.id).then((_) => {
|
||||
reload();
|
||||
notification.success({
|
||||
message: t('提示'),
|
||||
description: t('删除成功!'),
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
35
src/views/activereport/menu/index.vue
Normal file
35
src/views/activereport/menu/index.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<a-spin :spinning="spinning" :delay="delayTime">
|
||||
<ViewerHome v-if="data.visible" :content="data.content" />
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, unref } from 'vue';
|
||||
import ViewerHome from './../viewer/components/Viewer.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { getProfessionalInfo } from '/@/api/system/report';
|
||||
|
||||
const { currentRoute } = useRouter();
|
||||
const spinning = ref<boolean>(true);
|
||||
const delayTime = 500;
|
||||
const data = reactive({ visible: false, content: '' });
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const { path } = unref(currentRoute);
|
||||
let paths = path.split('/');
|
||||
let id = paths.length > 0 ? paths[paths.length - 1] : '';
|
||||
if (id) {
|
||||
let res = await getProfessionalInfo(id);
|
||||
data.content = res.fileJson;
|
||||
data.visible = true;
|
||||
}
|
||||
spinning.value = false;
|
||||
} catch (error) {
|
||||
console.log('error: ', error);
|
||||
spinning.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
34
src/views/activereport/viewer/components/Viewer.vue
Normal file
34
src/views/activereport/viewer/components/Viewer.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div id="viewer-host">
|
||||
<ReportViewer ref="viewRef" language="zh" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Viewer as ReportViewer } from '@grapecity/activereports-vue';
|
||||
import '@grapecity/activereports/styles/ar-js-ui.css';
|
||||
import '@grapecity/activereports/styles/ar-js-viewer.css';
|
||||
import '@grapecity/activereports/pdfexport';
|
||||
import '@grapecity/activereports/htmlexport';
|
||||
import '@grapecity/activereports/xlsxexport';
|
||||
|
||||
import '@grapecity/activereports-localization/dist/designer/zh-locale';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const viewRef = ref();
|
||||
let props = defineProps({
|
||||
content: String,
|
||||
});
|
||||
onMounted(() => {
|
||||
if (props.content) {
|
||||
let reportObj = JSON.parse(props.content);
|
||||
viewRef.value.Viewer().open(reportObj.definition);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
#viewer-host {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
}
|
||||
</style>
|
||||
8
src/views/activereport/viewer/index.vue
Normal file
8
src/views/activereport/viewer/index.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<Viewer />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import Viewer from './components/Viewer.vue';
|
||||
</script>
|
||||
Reference in New Issue
Block a user