szh-new
张同海 4 months ago
commit 85e9e52320

@ -10,7 +10,7 @@
/>
<title><%= title %></title>
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_3756681_hx1ti0yzulr.css" />
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_3756681_gku4yfyle6.css" />
</head>
<body>
<script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 46 KiB

@ -165,6 +165,7 @@
.ds-action-bar {
position: fixed;
right: 30px;
top: 65vh;
height: auto;
z-index: 999;
cursor: pointer;

@ -5,113 +5,125 @@
-->
<template>
<div class="cost-action-bar">
<a-button type="link" size="mini" @click="addRow">
<span class="iconfont icon-tianjia" :style="{ fontSize: '12px' }"></span>
添加
</a-button>
<a-button type="link" @click="copyRow">
<span class="iconfont icon-fuzhi" :style="{ fontSize: '12px' }"></span>
复制
</a-button>
<a-button type="link" @click="save">
<span class="iconfont icon-icon_baocun" :style="{ fontSize: '12px' }"></span>
保存
</a-button>
<a-popconfirm
:visible="deleteFlag"
title="确定要删除勾选的数据?"
ok-text="确定"
cancel-text="取消"
@confirm="deleteRow"
@cancel="cancelDelete"
@click="checkDelete"
>
<a-button danger type="link" >
<span class="iconfont icon-shanchu1" :style="{ fontSize: '12px' }"></span>
删除
</a-button>
</a-popconfirm>
<a-popconfirm
title="是否取消数据录入?"
ok-text="确定"
cancel-text="取消"
@confirm="cancelEdit"
>
<a-button danger type="link">
<span class="iconfont icon-shanchu" :style="{ fontSize: '12px' }"></span>
取消
</a-button>
</a-popconfirm>
<a-button type="link" @click="refresh">
<span class="iconfont icon-shuaxin" :style="{ fontSize: '12px' }"></span>
刷新
</a-button>
<a-dropdown>
<template #overlay>
<a-menu>
<a-sub-menu :title="tbType == 'receive' ? '打印应付账单' : '打印应收账单'">
<a-menu-item @click="printFee(1)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item @click="printFee(2)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item @click="printFee(3)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
</a-sub-menu>
<a-menu-item @click="feeTem"></a-menu-item>
<a-menu-item @click="saveToTem"></a-menu-item>
</a-menu>
</template>
<a-button type="link">
<span class="iconfont icon-printing" :style="{ fontSize: '12px' }"></span>
打印
</a-button>
</a-dropdown>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item @click="submit"></a-menu-item>
<a-menu-item @click="submitAll">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item>整票提交</a-menu-item>
<a-menu-item @click="revokeSubmit"></a-menu-item>
<a-menu-item>撤销整票提交</a-menu-item>
<a-menu-item>申请开票</a-menu-item>
<a-menu-item>收费申请</a-menu-item>
<a-menu-item>费用拆分</a-menu-item>
<a-menu-item @click="openFlowChart"></a-menu-item>
<a-menu-item>批量更改费用对象</a-menu-item>
<a-menu-item>批量修改核算单位</a-menu-item>
<a-menu-item>禁开发票</a-menu-item>
<a-menu-item>费用信息排序</a-menu-item>
</a-menu>
</template>
<a-button type="link">
提交审核
<span class="iconfont icon-xia" :style="{ fontSize: '12px' }"></span>
</a-button>
</a-dropdown>
<a-button @click="openApplyModify" type="link">
申请修改
</a-button>
<a-button type="link" @click="deleteApply">
申请删除
</a-button>
<a-button type="link" @click="cancelApply">
取消申请
</a-button>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item @click="history"></a-menu-item>
<a-menu-item @click="feeTem"></a-menu-item>
<a-menu-item @click="saveToTem"></a-menu-item>
<a-sub-menu :title="tbType == 'receive' ? '生成应付' : '生成应收'">
<a-menu-item @click="selectInsert(1)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item @click="selectInsert(2)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
</a-sub-menu>
</a-menu>
</template>
<a-button type="link">
引入费用
<span class="iconfont icon-xia" :style="{ fontSize: '12px' }"></span>
</a-button>
</a-dropdown>
<div class="flex">
<div>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item @click="submit"></a-menu-item>
<a-menu-item @click="submitAll">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item>整票提交</a-menu-item>
<a-menu-item @click="revokeSubmit"></a-menu-item>
<a-menu-item>撤销整票提交</a-menu-item>
<a-menu-item>申请开票</a-menu-item>
<a-menu-item>收费申请</a-menu-item>
<a-menu-item>费用拆分</a-menu-item>
<a-menu-item @click="openFlowChart"></a-menu-item>
<a-menu-item>批量更改费用对象</a-menu-item>
<a-menu-item>批量修改核算单位</a-menu-item>
<a-menu-item>禁开发票</a-menu-item>
<a-menu-item>费用信息排序</a-menu-item>
</a-menu>
</template>
<a-button type="link">
<span class="iconfont icon-tijiao1"></span>
提交审核
<span class="iconfont icon-30jiantouxiangxiafill"></span>
</a-button>
</a-dropdown>
<a-button @click="openApplyModify" type="link">
<span class="iconfont icon-electronic-signature"></span>
申请修改
</a-button>
<a-button type="link" @click="deleteApply">
<span class="iconfont icon-shanchuzu"></span>
申请删除
</a-button>
<a-button type="link" @click="cancelApply">
<span class="iconfont icon-weiwancheng"></span>
取消申请
</a-button>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item @click="history"></a-menu-item>
<a-menu-item @click="feeTem"></a-menu-item>
<a-menu-item @click="saveToTem"></a-menu-item>
<a-sub-menu :title="tbType == 'receive' ? '生成应付' : '生成应收'">
<a-menu-item @click="selectInsert(1)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item @click="selectInsert(2)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
</a-sub-menu>
</a-menu>
</template>
<a-button type="link">
<span class="iconfont icon-a-17Fdaoru"></span>
引入费用
<span class="iconfont icon-30jiantouxiangxiafill"></span>
</a-button>
</a-dropdown>
</div>
<div>
<a-button type="link" @click="save">
<span class="iconfont icon-icon_baocun"></span>
保存
</a-button>
<a-button type="link" @click="copyRow">
<span class="iconfont icon-fuzhi3"></span>
复制
</a-button>
<a-dropdown>
<template #overlay>
<a-menu>
<a-sub-menu :title="tbType == 'receive' ? '打印应付账单' : '打印应收账单'">
<a-menu-item @click="printFee(1)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item @click="printFee(2)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
<a-menu-item @click="printFee(3)">{{ tbType == 'receive' ? '' : '' }}</a-menu-item>
</a-sub-menu>
<a-menu-item @click="feeTem"></a-menu-item>
<a-menu-item @click="saveToTem"></a-menu-item>
</a-menu>
</template>
<a-button type="link">
<span class="iconfont icon-printing"></span>
打印
<span class="iconfont icon-30jiantouxiangxiafill"></span>
</a-button>
</a-dropdown>
<a-button type="link" size="mini" @click="addRow">
<span class="iconfont icon-tianjia"></span>
添加
</a-button>
<a-popconfirm
title="是否取消数据录入?"
ok-text="确定"
cancel-text="取消"
@confirm="cancelEdit"
>
<a-button type="link">
<span class="iconfont icon-shanchu"></span>
取消
</a-button>
</a-popconfirm>
<a-popconfirm
:visible="deleteFlag"
title="确定要删除勾选的数据?"
ok-text="确定"
cancel-text="取消"
@confirm="deleteRow"
@cancel="cancelDelete"
@click="checkDelete"
>
<a-button type="link" >
<span class="iconfont icon-shanchu1"></span>
删除
</a-button>
</a-popconfirm>
<a-button type="link" @click="refresh">
<span class="iconfont icon-shuaxin"></span>
刷新
</a-button>
</div>
</div>
<!-- 引入历史数据弹窗 -->
<HistoryDrawer ref="historyDrawer" @submit="submitHistory"></HistoryDrawer>
<!-- 费用模版弹窗 -->
@ -460,12 +472,19 @@
<style lang="scss">
.cost-action-bar {
margin-left: 20px;
margin-right: -10px;
position: relative;
top: 4px;
.ant-btn-link {
padding: 0 7px;
}
.ant-btn {
font-size: 12px;
}
.flex {
justify-content: space-between;
}
}
.ant-dropdown-menu-item-only-child {
width: 150px!important;

@ -7,8 +7,9 @@
<a-spin :spinning="loading">
<div class="cost-entry-receive">
<div class="flex">
<h4>{{ tbType == 'receive' ? '应收' : '应付' }}</h4>
<h4>{{ tbType == 'receive' ? '应收费用' : '应付费用' }}</h4>
<ActionBar
style="flex: 1"
:data="list"
:row="row"
:tbType="tbType"
@ -84,7 +85,12 @@
//
details: { type: [Object, Array] },
//
type: { type: [String, Number] }
type: { type: [String, Number] },
//
height: {
type: [String, Number],
default: '300'
}
})
const emits = defineEmits(['broInsert'])
//
@ -421,7 +427,7 @@
]
//
const settings = {
height: '360',
height: props.height,
width: '100%',
autoWrapRow: true,
autoWrapCol: true,
@ -898,9 +904,7 @@
.cost-entry-receive {
.flex {
h4 {
margin: 0 10px;
line-height: 30px;
font-size: 14px;
margin: 10px 0;
}
}
.line {
@ -912,6 +916,5 @@
}
background-color: #ffffff;
padding: 0;
margin-top: 10px;
}
</style>

@ -8,9 +8,13 @@
<!-- 主单信息组件 -->
<MainInfo :data="details"></MainInfo>
<!-- 应收表格 -->
<FeeTable tbType="receive" :type="type" :broData="broPayData" :id="data.id" :details="details" @broInsert="broReceive"></FeeTable>
<div class="fee-card-box mt15">
<FeeTable tbType="receive" :height="height" :type="type" :broData="broPayData" :id="data.id" :details="details" @broInsert="broReceive"></FeeTable>
</div>
<!-- 应付表格 -->
<FeeTable tbType="pay" :broData="broReceiveData" :type="type" :id="data.id" :details="details" @broInsert="broPay"></FeeTable>
<div class="fee-card-box mt15">
<FeeTable tbType="pay" :height="height" :broData="broReceiveData" :type="type" :id="data.id" :details="details" @broInsert="broPay"></FeeTable>
</div>
<FeeStatistic :id="data.id" />
</div>
</template>
@ -25,7 +29,12 @@
const props = defineProps({
details: { type: [Object, Array] },
//
type: { type: [String, Number] }
type: { type: [String, Number] },
//
height: {
type: [String, Number],
default: '300'
}
})
const data = ref(null)
// data.value = props.details
@ -49,14 +58,11 @@
},
{ immediate: true, deep: true }
)
// export default defineComponent({
// name: 'CostEntry',
// props,
// setup(props) {
// console.log(props, 222)
// watchEffect(() => {
// console.log(props.details)
// })
// }
// })
</script>
<style scoped>
.fee-card-box {
border: 1px solid #E8EBED;
padding: 0 20px 20px;
}
</style>

@ -65,6 +65,8 @@
<style>
.cost-entry-main-info {
background-color: #ffffff;
padding: 15px 15px 0 15px;
padding: 6px 20px 0 20px;
border: 1px solid #E8EBED;
border-top: none;
}
</style>

@ -24,6 +24,7 @@
v-bind="getBindValues"
:row-class-name="getRowClassName"
@change="handleTableChange"
@resize-column="resizeColumn"
>
<template v-for="item in Object.keys($slots)" #[item]="data" :key="item">
<slot :name="item" v-bind="data || {}"></slot>
@ -326,7 +327,9 @@
expose(tableAction)
emit('register', tableAction, formActions)
const resizeColumn = (w, col) => {
setCacheColumnsByField(col.dataIndex, { width: w })
}
return {
formRef,
tableElRef,
@ -346,6 +349,7 @@
getFormSlotKeys,
getWrapperClass,
columns: getViewColumns,
resizeColumn
}
},
})

@ -119,7 +119,7 @@ export function useColumns(
columns.forEach((item) => {
const { customRender, slots } = item
item['resizable'] = true
handleItem(
item,
Reflect.has(item, 'ellipsis') ? !!item.ellipsis : !!ellipsis && !customRender && !slots,
@ -193,7 +193,8 @@ export function useColumns(
if (!dataIndex || !value) {
return
}
cacheColumns.forEach((item) => {
// cacheColumns.forEach((item) => {
columnsRef.value.forEach((item) => {
if (item.dataIndex === dataIndex) {
Object.assign(item, value)
return

@ -0,0 +1,98 @@
<!--
* @Author: lijj
* @Date: 2024-05-06 09:18:47
* @Description: 附件列表
-->
<template>
<a-upload
name="file"
accept=".xlsx,xls"
:before-upload="importFile"
:show-upload-list="false"
>
<a-button type="link">
<span class="iconfont icon-a-17Fdaoru"></span>
引入excel数据
</a-button>
</a-upload>
</template>
<script lang="ts" setup name="ImportExcel">
import { defineProps, defineEmits } from 'vue'
import * as XLSX from 'xlsx'
//
import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage()
const props = defineProps({
//
title: {
type: Array,
default: () => {
return []
}
},
//
field: {
type: Array,
required: true,
default: () => {
return []
}
}
})
const emit = defineEmits(['success'])
//
const importFile = (file) => {
function getHeaderRow (sheet) {
const headers = [];
/* sheet['!ref']表示所有单元格的范围例如从A1到F8则记录为 A1:F8*/
const range = XLSX.utils.decode_range(sheet['!ref']);
let C, R = range.s.r; /* 从第一行开始 */
/* 按列进行数据遍历 */
for (C = range.s.c; C <= range.e.c; ++C) {
/* 查找第一行中的单元格 */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
let hdr = "UNKNOWN " + C; // <--
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
headers.push(hdr)
}
return headers
}
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = (e) => {
/* 解析数据 */
const bstr = e.target.result;
const wb = XLSX.read(bstr, { type: 'binary' });
/* 获取文件的第一个工作表WorkSheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* 数组转换 */
const data = XLSX.utils.sheet_to_json(ws, { header: 1 });
const dataTitle = getHeaderRow(ws)
const dataList = data.slice(0)
dataList.shift()
if (props.title.length && dataTitle.length) {
for (let i = 0; i < props.title.length; i++) {
if (props.title[i] != dataTitle[i]) {
return createMessage.warning(`表头第${i + 1}列应为${props.title[i]}`)
}
}
}
//
const res = []
dataList.forEach(row => {
const obj = {}
props.field.forEach((key, index) => {
obj[key] = row[index] || null
})
res.push(obj)
})
emit('success', res)
}
}
</script>
<style lang="less">
</style>

@ -4,6 +4,7 @@ import { Button } from './Button'
import VXETable from 'vxe-table'
import ConfigForm from './ConfigForm/index.vue'
import ActionBar from './ActionBar/index.vue'
import ImportExcel from './importExcel/index.vue'
import 'vxe-table/lib/style.css'
import {
// Need
@ -56,7 +57,7 @@ import {
Timeline
} from 'ant-design-vue'
const compList = [AntButton.Group, Icon, ConfigForm, ActionBar]
const compList = [AntButton.Group, Icon, ConfigForm, ActionBar, ImportExcel]
export function registerGlobComp(app: App) {
compList.forEach((comp) => {

@ -0,0 +1,5 @@
.ant-form-item-label {
>label {
font-size: 12px!important;
}
}

@ -3,6 +3,8 @@
@import './btn.less';
@import './tabs.less';
@import './modal.less';
@import './table.less';
@import './form.less';
.ant-image-preview-root {
img {

@ -1,76 +1,111 @@
@prefix-cls: ~'@{namespace}-basic-table';
// fix table unnecessary scrollbar
.@{prefix-cls} {
.hide-scrollbar-y {
.ant-spin-nested-loading {
.ant-spin-container {
.ant-table {
.ant-table-content {
.ant-table-scroll {
.ant-table-hide-scrollbar {
overflow-y: auto !important;
}
.ant-table-body {
overflow-y: auto !important;
}
}
.ant-table-fixed-right {
.ant-table-body-outer {
.ant-table-body-inner {
overflow-y: auto !important;
}
}
}
.ant-table-thead {
th {
background-color: rgba(240, 244, 250, 1) !important;
font-size: 12px;
font-weight: 400 !important;
letter-spacing: 1px;
line-height: 15.84px;
color: rgba(51, 56, 61, 1) !important;
text-align: left !important;
vertical-align: bottom;
border: none !important;
border-bottom: 1px solid rgba(232, 232, 232, 1) !important;
&.ant-table-selection-column {
border-right: 1px solid rgba(232, 232, 232, 1) !important;
text-align: center!important;
}
}
}
.ant-table-fixed-left {
.ant-table-body-outer {
.ant-table-body-inner {
overflow-y: auto !important;
}
}
}
}
}
.ant-table-tbody {
.ant-table-row {
td {
font-size: 12px;
letter-spacing: 0px;
line-height: 15.84px;
color: rgba(51, 56, 61, 1) !important;
text-align: left !important;
vertical-align: bottom;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial,
sans-serif !important;
font-weight: 400 !important;
color: #262626 !important;
background: rgba(255, 255, 255, 1);
border: none !important;
border-bottom: 1px solid rgba(232, 232, 232, 1) !important;
&.ant-table-selection-column {
border-right: 1px solid rgba(232, 232, 232, 1) !important;
text-align: center!important;
}
}
}
}
.ant-table-cell {
font-size: 12px;
}
.hide-scrollbar-x {
.ant-spin-nested-loading {
.ant-spin-container {
.ant-table {
.ant-table-content {
.ant-table-scroll {
.ant-table-hide-scrollbar {
//overflow-x: auto !important;
}
.ant-table-body {
overflow: auto !important;
}
}
.ant-table-fixed-right {
.ant-table-body-outer {
.ant-table-body-inner {
overflow-x: auto !important;
}
}
}
.ant-table-fixed-left {
.ant-table-body-outer {
.ant-table-body-inner {
overflow-x: auto !important;
}
}
}
}
.vben-basic-table .ant-table.ant-table-bordered > .ant-table-container > .ant-table-content > table > thead > tr > th::before, .vben-basic-table .ant-table.ant-table-bordered > .ant-table-container > .ant-table-header > table > thead > tr > th::before, .vben-basic-table .ant-table.ant-table-bordered > .ant-table-container > .ant-table-body > table > thead > tr > th::before {
background-color: #CED5D9!important;
}
// handsontable 全选checkbox
.handsontable {
.hot-tb-no-data {
position: absolute;
top: 100px;
width: 300px;
left: 50%;
margin-left: -150px;
}
input[type="checkbox"] {
border-color: #E8EBED;
}
.htCore {
thead {
tr {
height: 24px;
background: #fafafa;
th {
line-height: 22px;
background: #F5F9FC;
font-size: 12px;
border-color: #E8EBED;
}
}
}
tbody {
tr {
td {
height: 24px !important;
line-height: 22px;
font-size: 12px;
color: #262626;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
border-color: #E8EBED;
}
}
}
}
}
// 清除禁用状态下的下拉图标
.htDimmed {
cursor: no-drop;
.htAutocompleteArrow {
display: none;
}
}
.handsontableInput {
height: 24px !important;
line-height: 24px !important;
}
.hot-green {
color: #419638 !important;
font-weight: 600;
}
.hot-yellow {
background: #e1a200 !important;
}
.hot-red {
background-color: #f5222d;
}
}

@ -121,51 +121,6 @@
padding: 5px 15px !important;
}
}
.ant-table-thead {
th {
background-color: rgba(240, 244, 250, 1) !important;
font-size: 12px;
font-weight: 400 !important;
letter-spacing: 1px;
line-height: 15.84px;
color: rgba(51, 56, 61, 1) !important;
text-align: left !important;
vertical-align: bottom;
border: none !important;
border-bottom: 1px solid rgba(232, 232, 232, 1) !important;
&.ant-table-selection-column {
border-right: 1px solid rgba(232, 232, 232, 1) !important;
text-align: center!important;
}
}
}
.ant-table-tbody {
.ant-table-row {
td {
font-size: 12px;
letter-spacing: 0px;
line-height: 15.84px;
color: rgba(51, 56, 61, 1) !important;
text-align: left !important;
vertical-align: bottom;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial,
sans-serif !important;
font-weight: 400 !important;
color: #262626 !important;
background: rgba(255, 255, 255, 1);
border: none !important;
border-bottom: 1px solid rgba(232, 232, 232, 1) !important;
&.ant-table-selection-column {
border-right: 1px solid rgba(232, 232, 232, 1) !important;
text-align: center!important;
}
}
}
}
.ant-table-cell {
font-size: 12px;
}
// 列表页面表单和表格的整体样式管理
.ds-table, .ds-table-detail {
@ -190,7 +145,7 @@
}
.ant-table-thead {
th {
padding: 10px 7px!important;
padding: 7px 7px!important;
}
.ant-table-column-sorters, .ant-table-filter-column {
justify-content: flex-start;
@ -265,4 +220,215 @@ input, button, textarea {
}
.vben-basic-table-header__toolbar > * {
margin-right: 0!important;
}
}
h1,
h2,
h3,
h4,
h5 {
font-weight: 600;
color: #262626;
padding: 0;
margin: 0;
}
// 各级标题 适配UI
h1 {
font-size: 18px;
}
h2 {
font-size: 14px;
font-weight: 600!important;
}
h3 {
font-size: 14px;
font-weight: bold !important;
height: 40px;
line-height: 40px;
padding-left: 15px;
border-bottom: 0.7px solid #d9d9d9;
}
h4 {
font-size: 12px;
font-weight: 600!important;
}
h5 {
font-size: 12px;
color: #33383D;
font-weight: 400;
}
.ml10 {
margin-left: 10px;
}
// 表单详情样式
.ds-form-detail {
.ant-form-item {
margin-bottom: 10px;
}
.ant-form-item-control-input-content {
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
font-size: 12px;
}
.ant-form-item-control-input {
min-height: 28px;
}
.ant-form-item-label {
padding: 0 !important;
label {
font-family: PingFang SC-Semibold, PingFang SC;
font-size: 12px;
color: #7A8798;
}
}
}
.ds-tb-check {
position: absolute;
z-index: 199;
left: 15px;
margin-top: 9px;
width: 12px;
}
.ds-detail-box {
margin: 0 0 0 20px;
}
.flex {
display: flex;
.auto {
flex: 1;
}
}
.mt2 {
margin-top: 2px !important;
}
.mt5 {
margin-top: 5px !important;
}
.mt10 {
margin-top: 10px !important;
}
.mr10 {
margin-right: 10px !important;
}
.mb10 {
margin-bottom: 10px !important;
}
.ml10 {
margin-left: 10px !important;
}
.ds-card {
padding: 10px 20px;
background-color: #ffffff;
border: 0.7px solid #E8EBED;
}
.mr15 {
margin-right: 15px !important;
}
.mt15 {
margin-top: 15px;
}
.mb15 {
margin-bottom: 15px;
}
.ml15 {
margin-left: 15px;
}
// 表格状态使用
.ds-green-tag,
.ds-blue-tag,
.ds-orange-tag,
.ds-red-tag,
.ds-purple-tag {
padding: 4px 13px;
border-radius: 30px;
font-size: 10px;
font-weight: 700 !important;
color: #ffffff;
display: inline-block;
vertical-align: bottom;
}
.ds-green-tag {
background-color: rgba(223, 247, 247, 1);
color: rgba(43, 176, 194, 1);
}
.ds-blue-tag {
background-color: rgba(222, 242, 255, 1);
color: rgba(70, 145, 255, 1);
}
.ds-orange-tag {
background-color: rgba(255, 232, 204, 1);
color: rgba(219, 146, 72, 1);
}
.ds-red-tag {
background-color: rgba(255, 232, 232, 1);
color: rgba(255, 128, 145, 1);
}
.ds-purple-tag {
background-color: rgba(232, 232, 255, 1);
color: rgba(137, 124, 222, 1);
}
// 表格状态使用定义2
.ds-green-status,
.ds-blue-status,
.ds-orange-status,
.ds-red-status,
.ds-purple-status,
.ds-grey-status {
font-family: Arial, Helvetica, sans-serif;
font-weight: 600;
}
.ds-green-status {
color: #419638;
}
.ds-blue-status {
color: #096dd9;
}
.ds-orange-status {
color: #e1a200;
}
.ds-red-status {
color: #f5222d;
}
.ds-purple-status {
color: #531dab;
}
.ds-grey-status {
color: #8c8c8c;
}
.icon-30jiantouxiangxiafill {
font-size: 6px;
position: relative;
left: 3px;
top: -1px;
color: #7A8798;
}

@ -1,251 +0,0 @@
h1,
h2,
h3,
h4,
h5 {
font-weight: 600;
color: #262626;
padding: 0;
margin: 0;
}
// UI
h1 {
font-size: 18px;
}
h2 {
font-size: 14px;
font-weight: 600!important;
}
h3 {
font-size: 14px;
font-weight: bold !important;
height: 40px;
line-height: 40px;
padding-left: 15px;
border-bottom: 0.7px solid #d9d9d9;
}
h4 {
font-size: 12px;
font-weight: 600!important;
}
h5 {
font-size: 12px;
color: #33383D;
font-weight: 400;
}
.ml10 {
margin-left: 10px;
}
//
.ds-form-detail {
.ant-form-item {
margin-bottom: 10px;
}
.ant-form-item-control-input-content {
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
font-size: 12px;
}
.ant-form-item-control-input {
min-height: 28px;
}
.ant-form-item-label {
padding: 0 !important;
label {
font-family: PingFang SC-Semibold, PingFang SC;
font-size: 12px;
color: #7A8798;
}
}
}
// handsontable checkbox
.handsontable {
.htCore {
thead {
tr {
height: 24px;
background: #fafafa;
th {
line-height: 22px;
background: #fafafa;
font-size: 12px;
}
}
}
tbody {
tr {
td {
height: 24px !important;
line-height: 22px;
font-size: 12px;
color: #262626;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
//
.htDimmed {
cursor: no-drop;
.htAutocompleteArrow {
display: none;
}
}
.handsontableInput {
height: 24px !important;
line-height: 24px !important;
}
.hot-green {
color: #9acd32 !important;
font-weight: 600;
}
.hot-yellow {
background: #ffe37e !important;
}
.hot-red {
background-color: #ff4500;
}
}
.ds-tb-check {
position: absolute;
z-index: 199;
left: 15px;
margin-top: 9px;
width: 12px;
}
.ds-detail-box {
margin: 0 0 0 20px;
}
.flex {
display: flex;
.auto {
flex: 1;
}
}
.mt2 {
margin-top: 2px !important;
}
.mt5 {
margin-top: 5px !important;
}
.mt10 {
margin-top: 10px !important;
}
.mr10 {
margin-right: 10px !important;
}
.mb10 {
margin-bottom: 10px !important;
}
.ml10 {
margin-left: 10px !important;
}
.ds-card {
padding: 10px 20px;
background-color: #ffffff;
border: 0.7px solid #E8EBED;
}
.mr15 {
margin-right: 15px !important;
}
.mt15 {
margin-top: 15px;
}
.mb15 {
margin-bottom: 15px;
}
.ml15 {
margin-left: 15px;
}
// 使
.ds-green-tag,
.ds-blue-tag,
.ds-orange-tag,
.ds-red-tag,
.ds-purple-tag {
padding: 4px 13px;
border-radius: 30px;
font-size: 10px;
font-weight: 700 !important;
color: #ffffff;
display: inline-block;
vertical-align: bottom;
}
.ds-green-tag {
background-color: rgba(223, 247, 247, 1);
color: rgba(43, 176, 194, 1);
}
.ds-blue-tag {
background-color: rgba(222, 242, 255, 1);
color: rgba(70, 145, 255, 1);
}
.ds-orange-tag {
background-color: rgba(255, 232, 204, 1);
color: rgba(219, 146, 72, 1);
}
.ds-red-tag {
background-color: rgba(255, 232, 232, 1);
color: rgba(255, 128, 145, 1);
}
.ds-purple-tag {
background-color: rgba(232, 232, 255, 1);
color: rgba(137, 124, 222, 1);
}
// 使2
.ds-green-status,
.ds-blue-status,
.ds-orange-status,
.ds-red-status,
.ds-purple-status,
.ds-grey-status {
font-family: Arial, Helvetica, sans-serif;
font-weight: 600;
}
.ds-green-status {
color: #419638;
}
.ds-blue-status {
color: #096dd9;
}
.ds-orange-status {
color: #e1a200;
}
.ds-red-status {
color: #f5222d;
}
.ds-purple-status {
color: #531dab;
}
.ds-grey-status {
color: #8c8c8c;
}

@ -1,6 +1,5 @@
// import dark theme
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
@import './common.scss';
:root {
.el-segmented {
--el-segmented-radius: var(--el-border-radius-base);

@ -1907,3 +1907,49 @@ export function GetSeaExportBillManageList(data) {
data,
})
}
// 复制单票
export function SeaExportCopy(params) {
return request({
url: '/opApi/SeaExport/SeaExportCopy',
method: 'get',
params
})
}
// 提单信息保存
export function EditSeaExportBillManage(data) {
return request({
url: '/opApi/SeaExportBillManage/EditSeaExportBillManage',
method: 'post',
data
})
}
// 舱单分票列表
export function GetShippingBillPartCtnList(data) {
return request({
url: '/opApi/ShippingBillPartCtn/GetShippingBillPartCtnList',
method: 'post',
data
})
}
// 舱单分票编辑
export function EditShippingBillPartCtn(data) {
return request({
url: '/opApi/ShippingBillPartCtn/EditShippingBillPartCtn',
method: 'post',
data
})
}
// 提单信息删除
export function BatchDelBillManageCtn(data) {
return request({
url: '/opApi/SeaExportBillManage/BatchDelBillManageCtn',
method: 'post',
data
})
}

@ -21,7 +21,7 @@
@cancel="cancelDelete"
@click="checkDelete"
>
<a-button danger type="link" >
<a-button type="link" >
<span class="iconfont icon-shanchu1"></span>
删除
</a-button>
@ -30,19 +30,22 @@
<span class="iconfont icon-refresh-1-copy"></span>
更新合计
</a-button>
<a-button type="link">
<span class="iconfont icon-a-17Btuichu"></span>
<a-button :loading="dloading" @click="copyMainBill" type="link">
<span v-show="!dloading" class="iconfont icon-a-17Btuichu"></span>
调入主单信息
</a-button>
</div>
<hot-table ref="hotTb" :data="list" :settings="settings"></hot-table>
<hot-table ref="hotTb" :data="list" :settings="settings">
<img v-show="!list.length" class="hot-tb-no-data" src="../../../../../assets/images/nodata.png" alt="">
</hot-table>
</div>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineProps, defineComponent, onMounted } from 'vue'
import { ref, nextTick, defineProps, defineComponent, onMounted, defineExpose } from 'vue'
import { HotTable } from '@handsontable/vue3'
import { registerAllModules } from 'handsontable/registry'
import 'handsontable/dist/handsontable.full.min.css'
import { GetOpCtnList } from '/@/views/operation/seaexport/api/BookingLedger'
import { GetCtnSelectList, GetPackageSelectList } from '/@/api/common'
//
import { useMessage } from '/@/hooks/web/useMessage'
@ -152,7 +155,7 @@
const list = ref([])
//
const settings = {
height: '600',
height: '507',
width: '100%',
autoWrapRow: true,
autoWrapCol: true,
@ -237,12 +240,58 @@
return !item.selected
})
deleteFlag.value = false
list.value = res
hotTb.value.hotInstance.loadData(res)
}
//
const cancelDelete = () => {
deleteFlag.value = false
}
const dloading = ref(false)
//
const copyMainBill = () => {
const postData = {
queryCondition: JSON.stringify([
{
FieldName: 'bsno',
FieldValue: props.id,
ConditionalType: 1,
},
]),
pageCondition: {
pageIndex: 1,
pageSize: 999,
sortConditions: []
}
}
dloading.value = true
GetOpCtnList(postData).then(res => {
dloading.value = false
const { data } = res
if (data.length) {
const hlist = data.map(item => {
return {
selected: false,
ctn: item.ctn,
ctnId: item.ctnId,
id: item.id,
ctnNum: item.ctnNum,
cntrNo: item.cntrNo,
sealNo: item.sealNo,
pkgs: item.pkgs,
kindPkgs: item.kindPkgs,
kindPkgsName: item.kindPkgsName,
kgs: item.kgs,
cbm: item.cbm,
tareWeight: item.tareWeight,
note: item.note
}
})
list.value = hlist
hotTb.value.hotInstance.loadData(hlist)
}
})
}
onMounted(() => {
const hot = hotTb.value.hotInstance
hot.addHook('afterOnCellMouseDown', function (event, coords, TD) {})
@ -260,6 +309,9 @@
}
})
})
defineExpose({
list
})
</script>
<style lang="less" scoped>

@ -1,5 +1,18 @@
import { FormSchema } from '/@/components/Table'
import SelectTextArea from '/@/views/operation/seaexport/components/SelectTextArea.vue'
import { useOptionsStore } from '/@/store/modules/options'
import { GetPackageSelectList } from '/@/views/operation/seaexport/api/BookingLedger'
import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage()
const optionsStore = useOptionsStore()
import { getDictOption } from '/@/utils/dictUtil'
import { ref } from 'vue'
// 单提份数字典
const FnnoBill = ref([])
getDictOption('no_bill').then((res) => {
FnnoBill.value = res
})
// 上面的表单1
export const formSchema1: FormSchema[] = [
{
label: '',
@ -220,4 +233,685 @@ export const formSchema1: FormSchema[] = [
defaultValue: '',
colProps: { span: 12 }
}
]
// 下面的表单2
export const formSchema2: FormSchema[] = [
{
field: 'etd',
label: 'ETD',
component: 'DatePicker',
colProps: { span: 3 },
defaultValue: ''
},
{
field: 'eta',
label: '预抵日期',
component: 'DatePicker',
colProps: { span: 3 },
defaultValue: ''
},
{
label: '船名Name',
field: 'vessel',
component: 'Input',
show: false,
},
{
label: '船名',
field: 'vesselId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: ({ formModel }) => {
return {
option: optionsStore.getOptionsByCode('GetVesselSelectList'),
labelField: 'vesselName',
valueField: 'id',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.vessel = obj.label
} else {
formModel.vessel = ''
}
}
}
}
},
{
label: '装货港',
field: 'loadPortId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((e) => {
e.ediCode = `${e.portName}/${e.ediCode}`
})
resolve({ data })
})
},
labelField: 'ediCode',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.loadPort = obj.portName
} else {
formModel.loadPort = ''
}
}
}
}
},
{
label: ' ',
field: 'loadPort',
component: 'Input',
colProps: { span: 3 }
},
{
label: '卸货港代码',
field: 'dischargePortId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((e) => {
e.ediCode = `${e.portName}/${e.ediCode}`
})
resolve({ data })
})
},
labelField: 'ediCode',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.dischargePort = obj.portName
} else {
formModel.dischargePort = ''
}
},
}
},
},
{
label: ' ',
field: 'dischargePort',
component: 'Input',
required: false,
colProps: { span: 3 },
},
{
label: '海关航次',
field: 'voyno',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: () => {
return {
option: optionsStore.getOptionsByCode('GetVoynoSelectList'),
labelField: 'voyNo',
valueField: 'voyNo',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
}
}
},
{
label: '目的地',
field: 'destinationId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((e) => {
e.ediCode = `${e.portName}/${e.ediCode}`
})
resolve({ data })
})
},
labelField: 'ediCode',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.destination = obj.portName
} else {
formModel.destination = ''
}
},
}
},
},
{
label: ' ',
field: 'destination',
component: 'Input',
colProps: { span: 3 }
},
{
label: '交货地',
field: 'deliveryPlaceId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((e) => {
e.ediCode = `${e.portName}/${e.ediCode}`
})
resolve({ data })
})
},
labelField: 'ediCode',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.deliveryPlace = obj.portName
} else {
formModel.deliveryPlace = ''
}
},
}
}
},
{
label: ' ',
field: 'deliveryPlace',
component: 'Input',
required: false,
colProps: { span: 3 },
},
{
label: '收货地',
field: 'receiptPlaceId',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 3 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((item) => {
item.portName = `${item.portName}(${item.ediCode})`
})
console.log(data)
resolve({ data })
})
},
labelField: 'portName',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.receiptPlace = obj.label
} else {
formModel.receiptPlace = ''
}
}
}
},
},
{
label: ' ',
field: 'receiptPlace',
component: 'Input',
required: false,
colProps: { span: 3 }
}
]
// 箱数或件数表单
export const formSchema3: FormSchema[] = [
{
label: '件数',
field: 'noPkgs',
component: 'InputTextArea',
required: false,
colProps: { span: 24 },
componentProps: ({ formModel, formActionType }) => {
return {
autoSize: { minRows: 3, maxRows: 3 },
onkeyup: (e) => {
console.log(e)
const arr = e.currentTarget._value.split('\n')
let pkgs = 0
for (let i = 0; i < arr.length; i++) {
if (isNaN(arr[i])) {
arr[i] = ''
return createMessage.warning('请输入正确的数字')
} else {
if (arr[i]) {
pkgs = pkgs + Number(arr[i])
}
}
}
console.log(formActionType)
formModel.pkgs = pkgs
formActionType ? formActionType.submit() : null
}
}
},
},
{
label: '总件数',
field: 'pkgs',
component: 'Input',
colProps: { span: 12 },
dynamicDisabled: true
},
{
label: '包装',
field: 'kindPkgs',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 12 },
componentProps: ({ formActionType, formModel }) => {
return {
option: optionsStore.getOptionsByCode('GetPackageSelectList'),
allowClear: true,
showSearch: true,
labelField: 'packageName',
valueField: 'id',
onChange: (e) => {
if (e) {
GetPackageSelectList().then((res) => {
res.data.forEach((item) => {
if (item.id == e) {
formModel.kindPkgsName = item.cnExplain
}
})
setTimeout(() => {
formActionType ? formActionType.submit() : null
}, 10)
})
}
},
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
}
}
},
{
label: '毛重(公斤)',
field: 'grossWeight',
component: 'InputTextArea',
required: false,
colProps: { span: 24 },
componentProps: ({ formModel }) => {
return {
autoSize: { minRows: 3, maxRows: 3 },
onInput: (e) => {
const arr = e.currentTarget._value.split('\n')
let pkgs = 0
for (let i = 0; i < arr.length; i++) {
if (isNaN(arr[i])) {
arr[i] = ''
return createMessage.warning('请输入正确的数字')
} else {
if (arr[i]) {
pkgs = pkgs + Number(arr[i])
}
}
}
formModel.kgs = pkgs
}
}
},
},
{
label: '总总量KGS',
field: 'kgs',
component: 'Input',
colProps: { span: 24 }
},
{
label: '尺码(立方米)',
field: 'measurement',
component: 'InputTextArea',
required: false,
colProps: { span: 24 },
componentProps: ({ formModel }) => {
return {
autoSize: { minRows: 3, maxRows: 3 },
onInput: (e) => {
const arr = e.currentTarget._value.split('\n')
let pkgs = 0
for (let i = 0; i < arr.length; i++) {
if (isNaN(arr[i])) {
arr[i] = ''
return createMessage.warning('请输入正确的数字')
} else {
if (arr[i]) {
pkgs = pkgs + Number(arr[i])
}
}
}
formModel.cbm = pkgs
}
}
},
},
{
label: '总尺码CBM',
field: 'cbm',
component: 'Input',
colProps: { span: 24 }
}
]
export const formSchema4: FormSchema[] = [
{
field: 'totalNo',
label: '件数大写',
component: 'Input',
required: false,
colProps: { span: 24 },
dynamicDisabled: true,
},
{
field: 'issueType',
label: '签单方式',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: () => {
return {
option: optionsStore.getOptionsByCode('GetIssueTypeSelectList'),
allowClear: true,
showSearch: true,
labelField: 'billType',
valueField: 'id',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
}
}
},
{
field: 'issueDate',
label: '签单日期',
component: 'DatePicker',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: {
format: 'YYYY-MM-DD',
allowClear: true
}
},
{
label: '签单地点',
field: 'issuePlace',
component: 'Input',
required: false,
colProps: { span: 6 }
},
{
field: 'noBill',
label: '提单份数',
component: 'Select',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: {
options: FnnoBill,
allowClear: true,
showSearch: true,
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
},
},
{
field: 'mblFrt',
label: '付费方式',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: () => {
return {
option: optionsStore.getOptionsByCode('GetClientFrtSelectList'),
allowClear: true,
showSearch: true,
labelField: 'cnName',
valueField: 'id',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
}
}
},
{
field: 'prepareAtId',
label: '预付地点',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((e) => {
e.portName = `${e.portName}/${e.ediCode}`
})
resolve({ data })
})
},
labelField: 'portName',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.prepareAt = obj.portName
} else {
formModel.prepareAt = ''
}
}
}
}
},
{
label: '',
field: 'prepareAt',
component: 'Input',
show: false,
colProps: { span: 6 },
},
{
label: '',
field: 'payableAt',
component: 'Input',
show: false,
colProps: { span: 6 },
},
{
field: 'payableAtId',
label: '到付地点',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: ({ formModel }) => {
return {
allowClear: true,
showSearch: true,
api: () => {
return new Promise((resolve) => {
const data = JSON.parse(
JSON.stringify(optionsStore.getOptionsByCode('GetClientPortSelectList')),
)
data.forEach((e) => {
e.portName = `${e.portName}/${e.ediCode}`
})
resolve({ data })
})
},
labelField: 'portName',
valueField: 'id',
resultField: 'data',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
onChange: (e, obj) => {
if (obj) {
formModel.payableAt = obj.portName
} else {
formModel.payableAt = ''
}
},
}
},
},
{
field: 'service',
label: '运输条款',
component: 'ApiSelect',
required: false,
dynamicDisabled: false,
// defaultValue: '',
colProps: { span: 6 },
componentProps: () => {
return {
option: optionsStore.getOptionsByCode('GetServiceSelectList'),
allowClear: true,
showSearch: true,
labelField: 'enName',
valueField: 'id',
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
}
}
},
{
label: '其他备注',
field: 'orderContent',
component: 'InputTextArea',
required: false,
colProps: { span: 12 },
componentProps: {
autoSize: { minRows: 3, maxRows: 3 }
}
},
{
label: '备注',
field: 'remark',
component: 'InputTextArea',
required: false,
colProps: { span: 12 },
componentProps: {
autoSize: { minRows: 3, maxRows: 3 }
}
},
]
// 集装箱表单
export const formSchema5: FormSchema[] = [
{
label: '主提单号',
field: 'mblno',
component: 'Input',
defaultValue: '',
colProps: { span: 12 }
},
{
label: '分提单号',
field: 'hblno',
component: 'Input',
defaultValue: '',
colProps: { span: 12 }
}
]

@ -5,35 +5,160 @@
-->
<template>
<div class="ds-sea-lading-info">
<!-- 按钮操作栏 -->
<div class="flex">
<!-- 提单信息表 -->
<BasicTable
class="ds-table-detail"
style="width: 370px"
:canRowSelect="true"
:row-selection="{ selectedRowKeys: state.rowKeys, onChange: selectiChange }"
rowKey="id"
@register="registerTable"
@row-click="onRowClick"
></BasicTable>
<!-- 提单信息详情 -->
<a-tabs v-model:activeKey="activeKey" class="ds-sea-child-tab">
<a-tab-pane key="1" tab="提单信息" size="small">
<div class="flex">
<!-- 收发通表单 -->
<BasicForm style="flex: 1;" @register="registerForm" />
<!-- 集装箱组件 -->
<container
class="ml15"
style="width: 700px;"
></container>
</div>
</a-tab-pane>
<a-tab-pane key="2" tab="其他信息" size="small">
</a-tab-pane>
</a-tabs>
</div>
<a-spin :spinning="loading">
<!-- 按钮操作栏 -->
<div class="btn-box flex">
<div>
<a-button type="link" @click="msg">
<span class="iconfont icon-a-17Btuichu"></span>
调入主单信息
</a-button>
<a-button type="link" @click="msg">
<span class="iconfont icon-time"></span>
历史引入
</a-button>
<a-button type="link" @click="msg">
<span class="iconfont icon-touzijilu"></span>
合票出单
</a-button>
<a-button type="link" @click="msg">
<span class="iconfont icon-a-17Btuichu"></span>
EDI报文导出
<span class="iconfont icon-30jiantouxiangxiafill"></span>
</a-button>
</div>
<div>
<a-button type="link" @click="create">
<span class="iconfont icon-icon_tianjia"></span>
新建
</a-button>
<a-button type="link" @click="save">
<span class="iconfont icon-a-17Btuichu"></span>
保存
</a-button>
<a-popconfirm
:visible="deleteFlag"
title="确定要删除勾选的数据?"
ok-text="确定"
cancel-text="取消"
@confirm="deleteRow"
@cancel="cancelDelete"
@click="checkDelete"
>
<a-button type="link" >
<span class="iconfont icon-shanchu1"></span>
删除
</a-button>
</a-popconfirm>
</div>
</div>
<div class="flex">
<!-- 提单信息表 -->
<BasicTable
class="ds-table-detail"
style="width: 370px"
:canRowSelect="true"
:row-selection="{ selectedRowKeys: state.rowKeys, onChange: selectiChange }"
rowKey="id"
@register="registerTable"
@row-click="onRowClick"
></BasicTable>
<!-- 提单信息详情 -->
<a-tabs v-model:activeKey="activeKey" class="ds-sea-child-tab">
<a-tab-pane key="1" tab="提单信息" size="small">
<div class="flex card-box">
<!-- 收发通表单 -->
<BasicForm style="flex: 1;" @register="registerForm" />
<!-- 集装箱组件 -->
<div style="width: 650px;">
<!-- 集装箱表单 -->
<BasicForm style="margin-bottom: 0;" @register="containerForm" />
<container
ref="contBox"
class="ml15"
:id="id"
></container>
<a-form
v-model="formData"
class="ant-form-small"
layout="vertical"
>
<a-row :gutter="15">
<a-col :span="6">
<a-form-item label="代理">
<a-select
v-model:value="formData.agentId"
width="300px"
placeholder="请选择"
>
<a-select-option v-for="item in getOptions('agentcn')" :key="item.id" :value="item.id">
{{ item.shortName }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="18">
<a-form-item label="AGENT">
<a-input style="height: 26px" v-model:value="formData.agentContent" />
</a-form-item>
</a-col>
</a-row>
</a-form>
</div>
</div>
<div class="card-box mt15" style="border-top: 1px solid #E8EBED;">
<!-- ETD表单 -->
<BasicForm style="margin-top: 8px;" @register="ETDForm" />
<a-row>
<a-col :span="7">
<a-form
v-model="formData"
class="ant-form-small cntrSealNo"
style="margin-top: -15px ;"
layout="vertical"
>
<a-col :span="24">
<a-form-item label="箱号封号">
<a-textarea v-model:value="formData.cntrSealNo" :autoSize="{ minRows: 10, maxRows: 10 }" placeholder="请输入" allow-clear />
</a-form-item>
</a-col>
<a-col :span="24" style="margin-top: 26px;">
<a-form-item label="唛头">
<a-textarea v-model:value="formData.marks" :autoSize="{ minRows: 9, maxRows: 9 }" placeholder="请输入" allow-clear />
</a-form-item>
</a-col>
</a-form>
</a-col>
<a-col :span="10">
<a-form
v-model="formData"
class="ant-form-small"
style="margin: -15px -12px 0 15px"
layout="vertical"
>
<a-form-item label="货物描述">
<a-textarea v-model:value="formData.description" :autoSize="{ minRows: 21, maxRows: 21 }" style="height: 409px" placeholder="请输入" allow-clear />
</a-form-item>
</a-form>
</a-col>
<a-col :span="7">
<BasicForm
class="pkg"
style="margin: -15px -12px 0 27px;"
@register="CountForm"
@submit="submit"
/>
</a-col>
</a-row>
<!-- 签单方式表单 -->
<BasicForm style="margin-top: -10px;" class="issue-form" @register="issueForm" />
</div>
</a-tab-pane>
<a-tab-pane key="2" tab="其他信息" size="small">
</a-tab-pane>
</a-tabs>
</div>
</a-spin>
</div>
</template>
<script lang="ts" setup>
@ -41,12 +166,20 @@
import { BasicTable, useTable } from '/@/components/Table'
import { BasicForm, useForm } from '/@/components/Form/index'
import { GetSeaExportBillManageList } from '../../api/BookingLedger'
import { formSchema1 } from './ladingInfo'
import { formSchema1, formSchema2, formSchema3, formSchema4, formSchema5 } from './ladingInfo'
import { getOptions } from '/@/hooks/dict'
import container from './container.vue'
import { EditSeaExportBillManage, BatchDelBillManageCtn } from '../../api/BookingLedger'
//
import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage()
const props = defineProps({
// id
id: {
type: String
}
},
//
details: { type: Object, default: {} }
})
const activeKey = ref('1')
//
@ -54,30 +187,109 @@
rowKeys: []
})
const selectiChange = (v) => {
if (v.length = 1) {
state.rowKeys = v
} else {
state.rowKeys = [v[v.length - 1]]
state.rowKeys = v
if (v.length == 0) {
resetFields1()
resetFields2()
resetFields3()
resetFields4()
resetFields5()
formData.agentId = ''
formData.agentContent = ''
formData.cntrSealNo = ''
formData.description = ''
formData.marks = ''
}
setFormValue()
}
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema, getFieldsValue }] =
//
const [registerForm, { setFieldsValue: setFieldsValue1, validate: validate1, resetFields: resetFields1 }] =
useForm({
labelWidth: 150,
schemas: formSchema1,
showActionButtonGroup: false,
})
//
const [ETDForm, { setFieldsValue: setFieldsValue2, validate: validate2, resetFields: resetFields2 }] =
useForm({
labelWidth: 150,
schemas: formSchema2,
showActionButtonGroup: false,
})
//
const [CountForm, { setFieldsValue: setFieldsValue3, validate: validate3, resetFields: resetFields3 }] =
useForm({
labelWidth: 150,
schemas: formSchema3,
showActionButtonGroup: false,
})
//
const [issueForm, { setFieldsValue: setFieldsValue4, validate: validate4, resetFields: resetFields4 }] =
useForm({
labelWidth: 150,
schemas: formSchema4,
showActionButtonGroup: false,
})
//
const [containerForm, { setFieldsValue: setFieldsValue5, validate: validate5, resetFields: resetFields5 }] =
useForm({
labelWidth: 150,
schemas: formSchema5,
showActionButtonGroup: false,
})
//
const onRowClick = (record) => {
//
const newSelectedRowKeys = [...state.rowKeys];
if (newSelectedRowKeys.includes(record.id)) {
newSelectedRowKeys.splice(newSelectedRowKeys.indexOf(record.id), 1);
} else {
newSelectedRowKeys.push(record.id);
state.rowKeys = [record?.id]
setSelectedRows([record])
setFormValue()
}
//
const deleteFlag = ref(false)
//
const checkDelete = () => {
if (state.rowKeys.length == 0) {
return createMessage.warning('请勾选要删除的数据!')
}
state.rowKeys = newSelectedRowKeys
deleteFlag.value = true
}
//
const deleteRow = () => {
loading.value = true
deleteFlag.value = false
BatchDelBillManageCtn({ id: props.id, ids: state.rowKeys }).then(res => {
loading.value = false
reload()
})
}
//
const cancelDelete = () => {
deleteFlag.value = false
}
//
const setFormValue = () => {
const row = getSelectRows()[0]
setFieldsValue1({
...row
})
setFieldsValue2({
...row
})
setFieldsValue3({
...row
})
setFieldsValue4({
...row
})
setFieldsValue5({
...row
})
formData.agentId = row.agentId
formData.agentContent = row.agentContent
formData.cntrSealNo = row.cntrSealNo
formData.description = row.description
formData.marks = row.marks
}
const [registerTable, { reload }] = useTable({
const [registerTable, { reload, getSelectRows, setSelectedRows }] = useTable({
api: async (p) => {
const res: API.DataResult = await GetSeaExportBillManageList(p)
return new Promise((resolve) => {
@ -85,7 +297,6 @@
})
},
beforeFetch: (p) => {
console.log(p)
const postParam: API.PageRequest = {
pageCondition: {
pageIndex: p.page,
@ -105,28 +316,10 @@
columns: [
{
title: '分提单号',
dataIndex: 'customerName',
dataIndex: 'hblno',
width: 90,
align: 'left'
},
{
title: '提单模版',
dataIndex: 'customerName',
width: 70,
align: 'left'
},
{
title: '提单类型',
dataIndex: 'customerName',
width: 70,
align: 'left'
},
{
title: '提单签',
dataIndex: 'customerName',
width: 70,
align: 'left'
},
}
],
isTreeTable: false,
pagination: true,
@ -137,15 +330,391 @@
showIndexColumn: false,
canResize: false
})
const loading = ref(false)
//
const formData = reactive({
agentId: '',
agentContent: '',
cntrSealNo: '',
description: '',
marks: ''
})
async function submit() {
setTimeout(() => {
let data = getFieldsValue3()
let SS = data.pkgs
if (SS) {
let GetStringNum = (str) => {
var num = 0
if (str == null || str == '') return num
if (str.length == 0) return num
var if_find = false
var str_num = ''
for (var i = 0; i < str.length; i += 1) {
var member = str.substr(i, 1)
if (
member == '0' ||
member == '1' ||
member == '2' ||
member == '3' ||
member == '4' ||
member == '5' ||
member == '6' ||
member == '7' ||
member == '8' ||
member == '9' ||
member == '.' ||
member == '-'
) {
if (!if_find) {
str_num = str_num + member
}
} else {
if_find = true
}
}
return str_num
}
let ToEn = (a) => {
// eslint-disable-next-line no-array-constructor
const arr1 = new Array('', ' thousand', ' million', ' billion')
const b = a.length
let f: any = null
let h = 0
let g = ''
const e = Math.ceil(b / 3)
const k = b - e * 3
g = ''
for (f = k; f < b; f += 3) {
++h
// eslint-disable-next-line no-undef
const num3 = f >= 0 ? a.substring(f, f + 3) : a.substring(0, k + 3)
// eslint-disable-next-line no-undef
const strEng = English(num3)
// eslint-disable-next-line eqeqeq
if (strEng != '') {
// eslint-disable-next-line eqeqeq
if (g != '') g += ' '
g += English(num3) + arr1[e - h]
}
}
return g
}
let English = (a) => {
// eslint-disable-next-line no-array-constructor
var arr2 = new Array(
'zero',
'ten',
'twenty',
'thirty',
'forty',
'fifty',
'sixty',
'seventy',
'eighty',
'ninety',
)
// eslint-disable-next-line no-array-constructor
var arr3 = new Array(
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
)
// eslint-disable-next-line no-array-constructor
var arr4 = new Array(
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
)
let strRet = ''
// eslint-disable-next-line eqeqeq
if (a.length == 3 && a.substr(0, 3) != '000') {
if (a.substr(0, 1) != '0') {
strRet += arr3[a.substr(0, 1)] + ' hundred'
if (a.substr(1, 2) != '00') strRet += ' and '
} else {
strRet += ' and '
}
a = a.substring(1)
}
if (a.length == 2) {
if (a.substr(0, 1) == '0') a = a.substring(1)
else if (a.substr(0, 1) == '1') strRet += arr4[a.substr(1, 2)]
else {
strRet += arr2[a.substr(0, 1)]
if (a.substr(1, 1) != '0') strRet += '-'
a = a.substring(1)
}
}
if (a.length == 1 && a.substr(0, 1) != '0') strRet += arr3[a.substr(0, 1)]
return strRet
}
SS = SS.toString()
const i = SS.indexOf('\n')
let num = 0
let strKind: any = ''
let enCapital = ''
if (i > 0) {
const slist = SS.split('\n')
for (let i = 0; i < slist.length; i += 1) {
const member = slist[i]
const strNum: any = GetStringNum(member)
if (i == 0) {
strKind = member.substring(strNum.length)
}
num = parseFloat(num).add(parseFloat(strNum))
}
if (strKind !== '') {
enCapital = strKind
} else {
strKind = data.kindPkgsName ? data.kindPkgsName : ''
enCapital = ToEn(num).toUpperCase() + ' ' + strKind + ' ONLY.'
}
} else {
const strNum: any = GetStringNum(SS)
strKind = SS.substring(strNum.length) ? SS.substring(strNum.length) : ''
if (strKind !== '') {
enCapital = strKind
} else {
strKind = data.kindPkgsName ? data.kindPkgsName : ''
enCapital = 'SAY:' + ToEn(strNum).toUpperCase() + ' ' + strKind + ' ONLY.'
}
}
setFieldsValue4({ totalNo: enCapital })
} else {
setFieldsValue4({ totalNo: '' })
}
}, 0)
}
function ToEn(a) {
// eslint-disable-next-line no-array-constructor
const arr1 = new Array('', ' thousand', ' million', ' billion')
const b = a.length
let f: any = null
let h = 0
let g = ''
const e = Math.ceil(b / 3)
const k = b - e * 3
g = ''
for (f = k; f < b; f += 3) {
++h
// eslint-disable-next-line no-undef
const num3 = f >= 0 ? a.substring(f, f + 3) : a.substring(0, k + 3)
// eslint-disable-next-line no-undef
const strEng = English(num3)
// eslint-disable-next-line eqeqeq
if (strEng != '') {
// eslint-disable-next-line eqeqeq
if (g != '') g += ' '
g += English(num3) + arr1[e - h]
}
}
return g
}
function English(a) {
// eslint-disable-next-line no-array-constructor
var arr2 = new Array(
'zero',
'ten',
'twenty',
'thirty',
'forty',
'fifty',
'sixty',
'seventy',
'eighty',
'ninety',
)
// eslint-disable-next-line no-array-constructor
var arr3 = new Array(
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
)
// eslint-disable-next-line no-array-constructor
var arr4 = new Array(
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
)
let strRet = ''
// eslint-disable-next-line eqeqeq
if (a.length == 3 && a.substr(0, 3) != '000') {
if (a.substr(0, 1) != '0') {
strRet += arr3[a.substr(0, 1)] + ' hundred'
if (a.substr(1, 2) != '00') strRet += ' and '
} else {
strRet += ' and '
}
a = a.substring(1)
}
if (a.length == 2) {
if (a.substr(0, 1) == '0') a = a.substring(1)
else if (a.substr(0, 1) == '1') strRet += arr4[a.substr(1, 2)]
else {
strRet += arr2[a.substr(0, 1)]
if (a.substr(1, 1) != '0') strRet += '-'
a = a.substring(1)
}
}
if (a.length == 1 && a.substr(0, 1) != '0') strRet += arr3[a.substr(0, 1)]
return strRet
}
function GetStringNum(str) {
var num = 0
if (str == null || str == '') return num
if (str.length == 0) return num
var if_find = false
var str_num = ''
for (var i = 0; i < str.length; i += 1) {
var member = str.substr(i, 1)
if (
member == '0' ||
member == '1' ||
member == '2' ||
member == '3' ||
member == '4' ||
member == '5' ||
member == '6' ||
member == '7' ||
member == '8' ||
member == '9' ||
member == '.' ||
member == '-'
) {
if (!if_find) {
str_num = str_num + member
}
} else {
if_find = true
}
}
return str_num
}
//
const contBox = ref(null)
//
const create = () => {
state.rowKeys = []
resetFields1()
resetFields2()
resetFields3()
resetFields4()
resetFields5()
formData.agentId = ''
formData.agentContent = ''
formData.cntrSealNo = ''
formData.description = ''
formData.marks = ''
}
//
const save = async() => {
const form1 = await validate1()
const form2 = await validate2()
const form3 = await validate3()
const form4 = await validate4()
const form5 = await validate5()
const postData = Object.assign(form1, form2, form3, form4, form5, formData, { businessId: props.id })
postData['ctnInfo'] = contBox.value.list
loading.value = true
EditSeaExportBillManage(postData).then(res => {
loading.value = false
createMessage.success('保存成功!')
reload()
})
}
const msg = () => {
createMessage.warning('功能开发中...')
}
</script>
<style lang="less" scoped>
<style lang="less">
.ds-sea-lading-info {
padding-right: 20px;
.ds-sea-child-tab {
flex: 1;
margin-left: 16px;
}
.ant-form-small {
margin: 15px 0 15px 15px;
}
.card-box {
padding: 0 20px 0 5px;
border: 1px solid #E8EBED;
border-top: none;
border-radius: 2px;
}
.ant-col-3 {
max-width: 14.28%;
}
.ant-col-7 {
max-width: 28.56%;
.ant-col-24 {
.ant-form-item-control-input {
// height: 180px;
}
}
}
.ant-col-10 {
max-width: 42.84%;
}
.btn-box {
margin: 5px -5px;
justify-content: space-between;
}
.pkg {
.ant-row>div:nth-child(1), .ant-row>div:nth-child(4), .ant-row>div:nth-child(6) {
.ant-form-item-control-input-content>div {
height: 70px;
}
}
}
.cntrSealNo {
.ant-form-item-control-input-content {
height: 180px;
}
}
.issue-form {
.ant-col-12 {
.ant-form-item-control-input-content {
height: 65px;
}
}
}
.ant-input-disabled {
position: absolute;
top: -1px;
}
}
</style>

@ -0,0 +1,381 @@
<!--
* @Author: lijingjia
* @Date: 2024-07-10 14:17:37
* @Description: 舱单分票信息
-->
<template>
<div class="ds-sea-manifest-ticket-info">
<a-spin :spinning="loading">
<div class="flex mt10">
<h4>舱单分票信息</h4>
<a-button type="link" @click="addRow">
<span class="iconfont icon-icon_tianjia"></span>
添加
</a-button>
<a-button type="link" @click="save">
<span class="iconfont icon-baocun"></span>
保存明细
</a-button>
<a-popconfirm
:visible="deleteFlag"
title="确定要删除勾选的数据?"
ok-text="确定"
cancel-text="取消"
@confirm="deleteRow"
@cancel="cancelDelete"
@click="checkDelete"
>
<a-button type="link" >
<span class="iconfont icon-shanchu1"></span>
删除
</a-button>
</a-popconfirm>
<ImportExcel
:title="['分单号', '箱号', '封号', '件数', '件数包装', '重量', '尺码', '备注']"
:field="['hblno', 'cntrNo', 'sealNo', 'pkgs', 'kindPkgsName', 'kgs', 'cbm', 'note']"
@success="importSuccess"
/>
</div>
<hot-table ref="hotTb" :data="list" :settings="settings">
<img v-show="!list.length" class="hot-tb-no-data" src="../../../../../assets/images/nodata.png" alt="">
</hot-table>
</a-spin>
<h4 class="mt15">分票合计</h4>
<a-table
class="calc-tb"
:columns="calcColumns"
:data-source="calcData"
:pagination="false"
bordered
/>
</div>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineProps, defineComponent, onMounted, watch } from 'vue'
import { HotTable } from '@handsontable/vue3'
import { registerAllModules } from 'handsontable/registry'
import 'handsontable/dist/handsontable.full.min.css'
import { GetPackageSelectList } from '/@/api/common'
import { GetShippingBillPartCtnList, EditShippingBillPartCtn } from '../../api/BookingLedger'
//
import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage } = useMessage()
defineComponent({
HotTable,
})
const props = defineProps({
id: {
type: String
}
})
// ref
const hotTb = ref(null)
//
let packageList = []
//
const columns = [
{
data: 'selected',
type: 'checkbox',
title: ' ',
width: 32,
className: 'htCenter',
readOnly: false,
},
{
title: '分单号',
width: 150,
data: 'hblno',
type: 'numeric'
},
{
title: '箱号',
width: 100,
data: 'cntrNo',
type: 'numeric',
},
{
title: '封号',
width: 120,
data: 'sealNo',
type: 'numeric',
},
{
title: '件数',
width: 100,
data: 'pkgs',
type: 'numeric',
},
{
title: '件数包装',
width: 120,
data: 'kindPkgsName',
type: 'dropdown',
source: async (query, process) => {
const results = await GetPackageSelectList()
packageList = results.data
const dict = results.data.map((item) => {
return item.packageName
})
process(dict)
},
},
{
title: '重量',
width: 100,
data: 'kgs',
type: 'numeric'
},
{
title: '尺码',
width: 100,
data: 'cbm',
type: 'numeric'
},
{
title: '备注',
width: 250,
data: 'note',
type: 'numeric'
},
]
//
const list = ref([])
//
const settings = {
height: '360',
width: '100%',
autoWrapRow: true,
autoWrapCol: true,
//
rowHeights: 26,
fixedColumnsLeft: 1,
//
enterMoves: 'row',
columnSorting: true,
//
afterValidate: function (isValid, value, row, prop, source) {
if (!isValid) {
hotTb.value.hotInstance.setDataAtRowProp(row, prop, '')
}
},
columns: columns,
// ()
licenseKey: 'non-commercial-and-evaluation',
//
afterChange(changes, source) {
//
if (source === 'edit' || source === 'Autofill.fill' || source === 'CopyPaste.paste') {
let dict = {}
changes.forEach((res) => {
//
if (changes[0][1] === 'kindPkgsName') {
const item = packageList.filter((item) => {
return item.packageName === changes[0][3]
})
if (item) dict = item[0]
list.value[changes[0][0]]['kindPkgs'] = dict?.ediCode
}
})
}
}
}
const row = {
selected: false,
hblno: '',
pid: props.id,
id: '',
cntrNo: '',
sealNo: '',
pkgs: '',
kindPkgs: '',
kindPkgsName: '',
kgs: '',
cbm: '',
note: ''
}
//
const addRow = () => {
const deepCopyRow = JSON.parse(JSON.stringify(row))
list.value.push(deepCopyRow)
}
//
const deleteFlag = ref(false)
//
const checkDelete = () => {
let flag = false
list.value.forEach(item => {
if (item.selected) flag = true
})
if (!flag) {
return createMessage.warning('请勾选要删除的数据!')
}
deleteFlag.value = true
}
//
const deleteRow = () => {
const res = list.value.filter(item => {
return !item.selected
})
deleteFlag.value = false
list.value = res
hotTb.value.hotInstance.loadData(res)
}
//
const cancelDelete = () => {
deleteFlag.value = false
}
//
const calcColumns = [
{
title: '分单号',
dataIndex: 'hblno',
width: 100
},
{
title: '件数',
dataIndex: 'pkgs',
width: 100
},
{
title: '重量',
dataIndex: 'kgs',
width: 100
},
{
title: '尺码',
dataIndex: 'cbm',
width: 100
}
]
const loading = ref(false)
//
const calcData = ref([])
//
const init = () => {
const postData = {
queryCondition: JSON.stringify([
{
FieldName: 'pid',
FieldValue: props.id,
ConditionalType: 1,
},
]),
pageCondition: {
pageIndex: 1,
pageSize: 999,
sortConditions: []
}
}
loading.value = true
GetShippingBillPartCtnList(postData).then(res => {
loading.value = false
const { data } = res
if (data.length) {
const hlist = data.map(item => {
return {
selected: false,
id: item.id,
pid: item.id,
cntrNo: item.cntrNo,
sealNo: item.sealNo,
pkgs: item.pkgs,
kindPkgs: item.kindPkgs,
kindPkgsName: item.kindPkgsName,
kgs: item.kgs,
cbm: item.cbm,
note: item.note,
hblno: item.hblno
}
})
list.value = hlist
hotTb.value.hotInstance.loadData(hlist)
}
})
}
//
const save = () => {
loading.value = true
EditShippingBillPartCtn({ partList: list.value, businessId: props.id }).then(res => {
loading.value = false
console.log(res)
})
}
//
const importSuccess = (data) => {
data.forEach(item => {
item['selected'] = false
item['pid'] = props.id
item['id'] = ''
//
// kindPkgs
})
list.value = data
hotTb.value.hotInstance.loadData(data)
}
onMounted(() => {
const hot = hotTb.value.hotInstance
hot.addHook('afterOnCellMouseDown', function (event, coords, TD) {})
//
hot.addHook('beforeKeyDown', function (event) {
// 'Enter'
if (event.key === 'ArrowDown') {
if (hot.getSelected()[0][0] == list.value.length - 1 && !hot.getActiveEditor()?._opened) {
list.value.push(JSON.parse(JSON.stringify(row)))
nextTick(() => {
hot.selectCell(list.value.length - 1, 3)
})
return false
}
}
})
init()
watch(
() => list.value,
(v) => {
const map = new Map()
const newArr = v.filter(key =>!map.has(String(key.hblno)) && map.set(String(key.hblno), 1))
newArr.forEach(item => {
item.pkgs = 0
item.kgs = 0
item.cbm = 0
})
newArr.forEach(item => {
v.forEach(row => {
if (item.hblno == row.hblno) {
item.pkgs = (Number(item.pkgs) || 0) + (Number(row.pkgs) || 0)
item.kgs = (Number(item.kgs) || 0) + (Number(row.kgs) || 0)
item.cbm = (Number(item.cbm) || 0) + (Number(row.cbm) || 0)
}
})
})
calcData.value = newArr
},
{
deep: true
}
)
})
</script>
<style lang="less">
.ds-sea-manifest-ticket-info {
.flex {
align-items: center;
h4 {
margin: 0 15px 0 0;
}
}
.calc-tb {
th {
padding: 5px 15px!important;
}
.ant-table-tbody {
.ant-table-cell {
padding: 5px 15px!important;
}
}
}
}
</style>

@ -2,7 +2,7 @@
<textarea
class="ant-input"
v-model="tvalue"
:style="`width:100%;display:inline-block;height: ${height}px`"
:style="`width:100%;display:inline-block;height: ${height}px; line-height: 16px;`"
@input="debounce(textareaChange, 300, $event)"
@blur="textareaBlur"
></textarea>

@ -79,8 +79,13 @@
:details="bookingDetails"
></mastetMore>
</a-tab-pane>
<a-tab-pane key="5-5" tab="应收应付费用" v-if="$route.query.id">
<costEntry :details="bookingDetails" type="1"></costEntry>
<a-tab-pane key="5-5" tab="应收应付费用" v-if="id">
<costEntry :height="feeHeight" :details="bookingDetails" type="1"></costEntry>
</a-tab-pane>
<a-tab-pane key="6-6" tab="舱单分票信息">
<manifestTicket
:id="id"
></manifestTicket>
</a-tab-pane>
</a-tabs>
</a-spin>
@ -121,13 +126,15 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { useAppStore } from '/@/store/modules/app'
import { useMessage } from '/@/hooks/web/useMessage'
import rules from './rules'
import { useRoute, useRouter } from 'vue-router'
//
import costEntry from '/@/components/CostEntry/index.vue'
//
import manifestTicket from './components/manifestTicket.vue'
const router = useRouter()
const route = useRoute()
import {
@ -141,7 +148,7 @@
import { getDictDropDown } from '/@/api/common'
const appStore = useAppStore()
// const go = useGo()
const { notification } = useMessage()
const { notification, createMessage } = useMessage()
import operationArea from './modules/operationArea.vue'
import basicInfo from './modules/basicInfo.vue'
import mailingInfo from './modules/mailingInfo.vue'
@ -191,6 +198,11 @@
// const historyData = ref({})
// const hasHbList = ref(false)
const moreStr = ref('')
//
const feeHeight = computed(() => {
const height = window.innerHeight
return 300
})
// // =========
// watch(
// () => mainOrderActiveKey,
@ -716,9 +728,9 @@
loading.value = false
if (res.succeeded) {
if (ApiData.id) {
notification.success({ message: '保存成功', duration: 3 })
createMessage.success('保存成功!')
} else {
notification.success({ message: '新增成功', duration: 3 })
createMessage.success('新增成功!')
id.value = res.data
init()
}

@ -11,7 +11,6 @@ import {
GetPackageSelectList,
} from '/@/views/operation/seaexport/api/BookingLedger'
import { useOptionsStore } from '/@/store/modules/options'
import { SlotFlags } from '@vue/shared'
const optionsStore = useOptionsStore()
const LockType = [
{ label: '锁定', value: true },
@ -2300,7 +2299,7 @@ export const otherInfoFormSchema: FormSchema[] = [
// defaultValue: '',
colProps: { span: 8 },
componentProps: {
rows: 3
autoSize: { minRows: 3, maxRows: 3 }
}
},
{
@ -2312,7 +2311,7 @@ export const otherInfoFormSchema: FormSchema[] = [
// defaultValue: '',
colProps: { span: 8 },
componentProps: {
rows: 3,
autoSize: { minRows: 3, maxRows: 3 }
}
},
{
@ -2324,7 +2323,7 @@ export const otherInfoFormSchema: FormSchema[] = [
// defaultValue: '',
colProps: { span: 8 },
componentProps: {
rows: 3,
autoSize: { minRows: 3, maxRows: 3 }
}
},
{

@ -124,8 +124,6 @@
async function submit() {
setTimeout(() => {
let data = getFieldsValue2()
console.log(data, 11111111111)
let SS = data.pkgs
if (SS) {
let GetStringNum = (str) => {

@ -1059,8 +1059,6 @@
async function UpExcel(file) {
const reader = new FileReader()
reader.onload = (e: any) => {
console.log(e.target.result)
const data = new Uint8Array(e.target.result)
const workbook = XLSX.read(data, { type: 'array' })
const worksheet = workbook.Sheets[workbook.SheetNames[0]]
@ -1807,7 +1805,7 @@
// }),
//
const settings = {
height: '400',
height: 'auto',
width: '100%',
autoWrapRow: true,
autoWrapCol: true,

@ -4,7 +4,7 @@
* @Date: 2024-04-29 11:54:04
-->
<template>
<div class="ds-card mt15">
<div class="ds-card mt15 other-info">
<div class="flex">
<h4>其他信息</h4>
<ConfigForm
@ -83,3 +83,12 @@
}
}
</style>
<style lang="less">
.other-info {
.ant-col-8 {
.ant-form-item-control-input-content {
height: 65px;
}
}
}
</style>

@ -1235,11 +1235,11 @@
.careful {
img {
margin-left: 10px;
width: 160px;
height: 160px;
width: 100px;
height: 100px;
}
.text {
padding: 37px 30px;
padding: 5px 30px;
h2 {
margin: 0;
}

@ -195,7 +195,7 @@
import tableActionBarRight from './components/tableActionBarRight.vue'
import { onMounted, ref } from 'vue'
import { BasicTable, useTable, TableAction } from '/@/components/Table'
import { PageDataByBooking } from './api/BookingLedger.js'
import { PageDataByBooking, SeaExportCopy } from './api/BookingLedger.js'
import { getColumnsByClient } from '/@/views/baseinfo/formcopy/api'
import { useModal } from '/@/components/Modal'
import { columns, searchFormSchema, FeeStatus } from './columns'
@ -508,7 +508,10 @@
}
//
function copyBooking(record) {
go(`/BookingDetail?id=${record.id}&isCopy=${true}`)
SeaExportCopy({ id: record.id }).then(res => {
reload()
})
// go(`/BookingDetail?id=${record.id}&isCopy=${true}`)
}
onMounted(() => {
//

Loading…
Cancel
Save