Commit 8fc6d48c by 李少勇

完成快照功能和文件预览的demo功能

parent d717ce2d
......@@ -4,9 +4,9 @@
"author": "psbc",
"private": true,
"scripts": {
"start": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js serve",
"start": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js serve --set NODE_ENV=development",
"start_new": "set NODE_OPTIONS=--openssl-legacy-provider && node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js serve",
"build": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js build"
"build": "node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js build --set NODE_ENV=production"
},
"dependencies": {
"async-validator": "^3.5.2",
......
......@@ -421,6 +421,8 @@ import DbiBtb from "~/views/Statics/Dbibtb";
import Infbnk from "~/views/Statics/Infbnk";
import Dbibnk from "~/views/Statics/Dbibnk";
import HistoryRecord from "~/views/HistoryRecord/index";
import FileReview from "~/views/FileReview/index";
/**
* 带有name的才会被添加进顶部的标签页里
......@@ -858,5 +860,9 @@ const BusRouter = [
{ path: 'infbnk', component: Infbnk, name: 'StaticsInfbnk', meta: { title: '银行行号信息查询' } },
{ path: 'dbibnk/:inr', component: Dbibnk, name: 'StaticsDbibnk', meta: { title: (tag) => { return '银行行号信息详情: ' + tag.params.inr } } },
// 快照
{ path: 'historyRecord', component: HistoryRecord, name: 'HistoryRecord', meta: { title: '交易快照' } },
// 文件预览
{ path: 'fileReview', component: FileReview, name: 'FileReview', meta: { title: '文件预览' } },
]
export default BusRouter
\ No newline at end of file
......@@ -109,6 +109,7 @@ export default {
#business_container {
flex: 1;
box-shadow: 0 1px 15px 0 rgb(0 0 0 / 12%), 0 0 3px 0 rgb(0 0 0 / 4%);
position: relative;
}
#business_container .eContainer, #business_container .eContainer-search{
box-sizing: border-box;
......
<template>
<div class="page-wrap">
<iframe :src="fileUrl" frameborder="0" width="100%" height="100%"></iframe>
</div>
</template>
<script>
import Api from "~/service/Api"
export default {
name: 'FileReview',
data () {
return {
fileUrl: ''
}
},
mounted () {
this.getFileTemplateUrl()
},
methods: {
async getFileTemplateUrl () {
let res = await Api.post('/file/api/filePreview?fileName=01.pdf')
console.log('res===', res)
this.viewPdf(res)
// this.fileUrl = 'data:image/png;base64,' + res
// console.log('this.fileUrl', this.fileUrl)
},
viewPdf (content) {
if (!content) {
console.log(content)
this.$message.error('暂无意见')
return
}
const blob = this.base64ToBlob(content)
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob)
} else {
const fileURL = URL.createObjectURL(blob)
this.fileUrl = fileURL
// window.open(fileURL)
}
},
base64ToBlob (code) {
code = code.replace(/[\n\r]/g, '')
const raw = window.atob(code)
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
return new Blob([uInt8Array], { type: 'application/pdf' })
}
}
}
</script>
<style lang="scss" scoped>
.page-wrap {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
padding: 16px;
box-sizing: border-box;
}
</style>
<template>
<div>
<el-table
:data="tableData"
border
style="width: 100%;max-width: 700px;">
<el-table-column
v-for="(item, index) in tableColums"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width"
>
<template slot-scope="scope">
<button
v-if="scope.row[item.prop].isButton === 'Y'"
disabled
class="cus-btn"
>
{{ scope.row[item.prop].value }}
</button>
<div
v-else
style="width: 100%;padding: 3px 0;"
:style="{
borderBottom: scope.row[item.prop].isRedLine === 'Y' ? '2px solid red' : ''
}"
>{{ scope.row[item.prop].value || '&nbsp;' }}</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { cloneDeep } from 'lodash'
export default {
name: 'Table',
props: {
gridValues: {
type: Array,
default: () => []
}
},
computed: {
tableColums () {
console.log('this.gridValues', this.gridValues)
let list = this.gridValues.filter((item) => {
return item.row === '0'
})
let tableColums = []
list.map((item, index) => {
tableColums.push({
prop: 'prop' + index,
label: item.value,
width: Number(item.width) < 50 ? 50 : Number(item.width)
})
})
console.log('tableColums', tableColums)
return tableColums
},
tableData () {
let list = this.gridValues.filter((item) => {
return item.row !== '0'
})
let tableData = []
let obj = {}
this.tableColums.map((item) => {
obj[item.prop] = ''
})
let rowNumber = Number(list[list.length - 1].row)
for (let i = 0; i < rowNumber; i++) {
tableData.push(cloneDeep(obj))
list.map((item) => {
if ((i + 1) === Number(item.row)) {
tableData[i]['prop' + item.column] = {
value: item.value,
isRedLine: item.isRedLine,
isButton: item.isButton
}
}
})
}
return tableData
}
},
data () {
return {
}
},
methods: {}
}
</script>
<style lang="scss" scoped>
::v-deep .el-table th .cell {
padding: 0!important;
overflow: hidden;
white-space: nowrap;
font-size: 10px;
color: black;
}
::v-deep .el-table td {
padding: 0!important;
}
::v-deep .el-table td .cell {
padding: 0!important;
overflow: hidden;
white-space: nowrap;
font-size: 10px;
color: black;
}
.cus-btn {
background-color: #fff!important;
color: black!important;
font-size: 10px;
padding: 0;overflow: hidden;white-space: nowrap;
font-weight: bold;
}
</style>
<template>
<div class="page-wrap">
<div style="width: 100%;padding: 10px;background-color: #fff;border-bottom: 1px solid #666666;box-sizing: border-box;">
<el-select v-model="selectFileNale" placeholder="请选择" @change="handleChangeFile">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<div class="form-content">
<div
class="field-item"
v-for="(fieldItem, fieldIndex) in frameFieldList"
:key="fieldIndex"
>
<div
v-if="fieldItem.viewType === 'Table' && fieldItem.gridValues.length"
style="position: absolute;"
:style="{
left: fieldItem.left + 'px',
top: fieldItem.top + 'px'
}"
>
<MTable :gridValues="fieldItem.gridValues"></MTable>
</div>
<div
v-if="['Label'].includes(fieldItem.viewType)"
style="position: absolute;font-size: 10px;overflow: hidden;font-weight: bold;"
:style="{
left: fieldItem.left + 'px',
top: fieldItem.top + 'px',
width: (Number(fieldItem.width) + 50) + 'px',
height: fieldItem.height + 'px',
lineHeight: fieldItem.height + 'px',
borderBottom: fieldItem.checkvalue === 1 ? '2px solid red' : ''
}"
>{{ fieldItem.value }}</div>
<button
v-if="fieldItem.viewType === 'Button' && fieldItem.value.indexOf('用户确认') === -1"
disabled
class="cus-btn"
:style="{
left: fieldItem.left + 'px',
top: fieldItem.top + 'px',
width: fieldItem.width + 'px',
height: fieldItem.height + 'px'
}"
>{{ replaceCode(fieldItem.value) }}</button>
<el-input
v-if="['Amount', 'Date', 'Input'].includes(fieldItem.viewType)"
size="mini"
disabled
placeholder=" "
v-model.trim="fieldItem.value"
style="position: absolute;font-size: 10px;"
:style="{
left: fieldItem.left + 'px',
top: fieldItem.top + 'px',
width: (Number(fieldItem.width) < 70 ? (Number(fieldItem.width) + 10) : Number(fieldItem.width)) + 'px',
height: fieldItem.height + 'px',
borderBottom: fieldItem.checkvalue === '1' ? '2px solid red' : ''
}"
></el-input>
<el-input
v-if="['Combobox'].includes(fieldItem.viewType)"
size="mini"
disabled
placeholder=" "
suffix-icon="el-icon-arrow-down"
v-model.trim="fieldItem.value"
style="position: absolute;font-size: 10px;"
:style="{
left: fieldItem.left + 'px',
top: fieldItem.top + 'px',
width: fieldItem.width + 'px',
height: fieldItem.height + 'px',
borderBottom: fieldItem.checkvalue === '1' ? '2px solid red' : ''
}"
>
</el-input>
<div
v-if="['Block'].includes(fieldItem.viewType)"
class="type-block"
:style="{
left: fieldItem.left + 'px',
top: fieldItem.top + 'px',
width: fieldItem.width + 'px',
height: fieldItem.height + 'px',
borderBottom: fieldItem.checkvalue === '1' ? '2px solid red' : ''
}"
>{{ fieldItem.value }}</div>
</div>
</div>
<div class="form-tab">
<div
class="tab-item"
v-for="(item, index) in panelList"
:key="index"
@click="handleChangeTab(item.name)"
>
<el-tag
size="small"
:type="activePanel === item.name ? '' : 'info'"
effect="plain"
>{{ replaceCode(item.name) }}</el-tag>
</div>
</div>
</div>
</template>
<script>
import Api from "~/service/Api"
import MTable from './components/Table'
export default {
name: 'HistoryRecord',
components: {
MTable
},
data () {
return {
options: [
{
value: 'test.DSP',
label: 'test.DSP'
},
{
value: '10000059.DSP',
label: '10000059.DSP'
}, {
value: '10000302.DSP',
label: '10000302.DSP'
}, {
value: '10000400.DSP',
label: '10000400.DSP'
}, {
value: '10000401.DSP',
label: '10000401.DSP'
},
{
value: '10000402.DSP',
label: '10000402.DSP'
},
{
value: '10000403.DSP',
label: '10000403.DSP'
},
{
value: '10000404.DSP',
label: '10000404.DSP'
},
{
value: '10000557.DSP',
label: '10000557.DSP'
},
{
value: '10000594.DSP',
label: '10000594.DSP'
},
{
value: '10000595.DSP',
label: '10000595.DSP'
},
{
value: '10004105.DSP',
label: '10004105.DSP'
},
{
value: '10004145.DSP',
label: '10004145.DSP'
},
{
value: '10004200.DSP',
label: '10004200.DSP'
},
{
value: '10004205.DSP',
label: '10004205.DSP'
},
{
value: '10004208.DSP',
label: '10004208.DSP'
},
{
value: '10004218.DSP',
label: '10004218.DSP'
},
{
value: '10004221.DSP',
label: '10004221.DSP'
},
{
value: '10004230.DSP',
label: '10004230.DSP'
},
{
value: '10004244.DSP',
label: '10004244.DSP'
},
{
value: '10004248.DSP',
label: '10004248.DSP'
},
{
value: '10004256.DSP',
label: '10004256.DSP'
},
{
value: '10004259.DSP',
label: '10004259.DSP'
},
{
value: '10004260.DSP',
label: '10004260.DSP'
},
{
value: '10004279.DSP',
label: '10004279.DSP'
}
],
selectFileNale: 'test.DSP',
panelList: [],
activePanel: '',
frameFieldList: []
}
},
mounted () {
this.getConfigData()
},
methods: {
handleChangeFile () {
this.getConfigData()
},
async getConfigData () {
let res = await Api.post('/api/dspfile?file=' + this.selectFileNale)
console.log('res===', res)
if (res.success) {
this.panelList = res.data?.panelLists
this.activePanel = this.panelList[0].name
this.frameFieldList = this.panelList[0].list
}
},
handleChangeTab (name) {
this.activePanel = name
this.frameFieldList = this.panelList.filter((item) => {
return item.name === name
})[0].list
},
replaceCode (str) {
return str.replace(/\u001f|&/g, '')
},
replaceSpecialCode (str) {
return str.replace(/&/g, '')
}
}
}
</script>
<style lang="scss" scoped>
.page-wrap {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
padding: 16px;
box-sizing: border-box;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
.form-content {
width: 100%;
flex: 1;
position: relative;
border: 1px solid #f6f6f6;
overflow-y: auto;
.field-item {
.cus-btn {
background-color: #fff!important;
color: black!important;
position: absolute;font-size: 10px;
padding: 0;overflow: hidden;white-space: nowrap;
z-index: 1;
font-weight: bold;
}
.type-block {
position: absolute;font-size: 10px;
border: 1px solid #E4E7ED;
background-color: #fff;overflow: auto;
}
}
}
.form-tab {
padding: 10px 10px 0;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-wrap: wrap;
border: 1px solid #9ea4ab;
margin-top: 10px;
.tab-item {
color: black;
text-align: center;
border-radius: 2px;
cursor: pointer;
margin-right: 16px;
margin-bottom: 4px;
}
.tab-item-active {
color: #409eff;
border: 1px solid #409eff;
}
}
::v-deep .el-input__inner {
padding: 0;
height: 22px;
line-height: 22px;
background-color: #fff;
color: black;
}
::v-deep .el-input__suffix {
right: 2px!important;
display: flex;
align-items: center;
}
::v-deep .el-textarea.is-disabled .el-textarea__inner {
background-color: #fff!important;
color: black!important;
padding: 0!important;
}
::v-deep .el-tag--plain.el-tag--info {
color: black!important;
}
}
</style>
......@@ -240,6 +240,9 @@ export default {
{ inifrm: "eafinf", ininam: "查 -- 外债远期信用证(含即期单证相符)", pntmiu: "28" },
{ inifrm: "eafame", ininam: "改 -- 外债远期信用证(含即期单证相符)", pntmiu: "28" },
{ inifrm: "eafdel", ininam: "删 -- 外债远期信用证(含即期单证相符)", pntmiu: "28" },
{ inifrm: "29", ininam: "快照", pntmiu: "" },
{ inifrm: "historyRecord", ininam: "交易快照", pntmiu: "29" },
{ inifrm: "fileReview", ininam: "文件预览", pntmiu: "29" },
// { inifrm: "3", ininam: "出口信用证", pntmiu: "" },
// { inifrm: "infled", ininam: "出口信用证交易查询", pntmiu: "3" },
......
......@@ -34,7 +34,7 @@ module.exports = {
},
proxy: {
'/gjjs/business/': {
target: 'http://127.0.0.1:8081',
target: 'http://192.168.0.85:8082',
changeOrigin: true,
pathRewrite: {
'^/gjjs/business': '/gjjs/business'
......@@ -91,13 +91,28 @@ module.exports = {
pathRewrite: {
'^/esfeserver': '/esfeserver'
}
},
// 快照
'/gjjs/api/': {
target: 'http://192.168.0.85:8082',
changeOrigin: true,
pathRewrite: {
'^/gjjs': ''
}
},
// 文件预览
'/gjjs/file/': {
target: 'http://192.168.0.85:8081',
changeOrigin: true,
pathRewrite: {
'^/gjjs/file': ''
}
}
}
},
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
devtool: 'source-map',
resolve: {
alias: {
'~': resolve('src')
......@@ -129,44 +144,43 @@ module.exports = {
// when there are many pages, it will cause too many meaningless requests
config.plugins.delete('prefetch')
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [{
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}])
.end()
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
config.when(process.env.NODE_ENV !== 'development',
config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [{
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}])
.end()
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
})
// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
config.optimization.runtimeChunk('single')
}
)
}
})
// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
config.optimization.runtimeChunk('single')
}
)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment