Files
workspace/code/g3hd-old/g3hd-vue/src/backup/billDetail20250925选择.vue
T
2026-03-20 16:58:54 +08:00

796 lines
26 KiB
Vue

<template>
<div class="g3-flex-container">
<div class="g3-flex-main" style="margin-bottom: 12px;overflow-y: hidden;height: 50px;">
<div class="g3-toolbar">
<el-button type="success" @click="handleSave" :loading="saving">保存</el-button>
<el-button type="primary">报表</el-button>
<el-button type="primary" @click="handleNew">新建</el-button>
<el-button type="primary" @click="handleCope">复制</el-button>
<el-button type="primary" @click="openDialogSelect">选择映射</el-button>
</div>
</div>
<div class="g3-flex-main" style="flex: 1;">
<div class="g3-content">
<div v-if="maintable" class="g3-grid">
<div class="g3-cell">
<div class="g3-cell-label">账单号:</div>
<el-input v-model="maintable.b_id" placeholder="账单号" />
</div>
<div class="g3-cell">
<div class="g3-cell-label">结算单位:</div>
<g3selectid
v-model="maintable.b_dw_id"
tablename="v_b_othercompany_customer"
value-key="b_id"
label-key="b_name"
:initial-value="maintable.b_dw_id"
:initial-label="maintable.v_dwname"
placeholder="搜索结算单位..."
@update:label="maintable.v_dwname = $event"
/>
</div>
<div class="g3-cell">
<div class="g3-cell-label">账单日期:</div>
<el-date-picker v-model="maintable.b_date" type="date" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" placeholder="请输入时间" style="width: 100%;" />
</div>
<div class="g3-cell">
<div class="g3-cell-label">客户联系人:</div>
<el-input v-model="maintable.b_dw_linkman_id" placeholder="客户联系人" />
</div>
<div class="g3-cell">
<div class="g3-cell-label">结算方式:</div>
<g3selectname
v-model="maintable.b_jsfs"
tablename="b_jsfs"
label-key="b_name"
:initial-label="maintable.b_jsfs"
placeholder="搜索结算方式..."
/>
</div>
<div class="g3-cell">
<div class="g3-cell-label">账期:</div>
<el-input v-model="maintable.b_zl" placeholder="账期" />
</div>
<div class="g3-cell">
<div class="g3-cell-label">我方公司:</div>
<g3selectid
v-model="maintable.b_mycompany_id"
tablename="v_b_othercompany_my"
value-key="b_id"
label-key="b_name"
:initial-value="maintable.b_mycompany_id"
:initial-label="maintable.v_mycompanyname"
placeholder="搜索我方公司..."
@update:label="maintable.v_mycompanyname = $event"
/>
</div>
<div class="g3-cell">
<div class="g3-cell-label">合同收款日:</div>
<el-date-picker v-model="maintable.b_enddate" type="date" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" placeholder="请输入时间" style="width: 100%;" />
</div>
<div class="g3-cell g3-cell-textarea">
<div class="g3-cell-label">银行户名:</div>
<el-input type="textarea" v-model="maintable.b_bankname" />
</div>
<div class="g3-cell">
<div class="g3-cell-label">申请人:</div>
<g3selectid
v-model="maintable.b_owner_id"
tablename="b_user"
value-key="b_id"
label-key="b_name"
:initial-value="maintable.b_owner_id"
:initial-label="maintable.v_ownername"
@update:label="maintable.v_ownername = $event"
/>
</div>
<div class="g3-cell">
<div class="g3-cell-label">预收挂账:</div>
<g3selectname
v-model="maintable.b_yfgz"
tablename="b_ygz"
label-key="b_name"
:initial-label="maintable.b_yfgz"
placeholder="搜索预收挂账..."
/>
</div>
<div class="g3-cell g3-cell-textarea">
<div class="g3-cell-label">备注:</div>
<el-input v-model="maintable.b_bz" type="textarea" placeholder="备注" />
</div>
<div class="g3-cell" style="display: none;">
<div class="g3-cell-label">审核状态:</div>
<el-input v-model="maintable.b_state" placeholder="审核状态" />
</div>
</div>
<div style="display: flex;flex: 1;margin-top: 10px;min-height: 0;flex-direction: column;">
<div style="border: 1px solid #ebeef5;display: flex;align-items: center;padding: 3px 0px;">
<el-button @click="openDialog" style="margin-left: 5px">选择数据</el-button>
<el-dropdown>
<div class="el-dropdown-link">
更多
<span class="iconfont icon-arrow-down" style="font-size: 12px; margin-top: 1px"></span>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleSaveColumn">栏位保存</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<el-table :data="subtable" border height="100%" :row-key="(row) => row.subid || row.mx_xh"
:header-cell-style="{ padding: '6px 0' }" class="g3-my-table" :resizable="true" @header-dragend="handleUpdateWidth">
<el-table-column type="selection" width="50" align="center" />
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop"
:label="column.label" :width="column.edit_width" align="center">
<template #default="{ row }">
<template v-if="column.edit_type === 'customer'">
<g3selectid v-model="row[column.prop]" :tablename="column.edit_source_table"
value-key="b_id" :label-key="column.edit_source_field"
:initial-value="row[column.prop]" :initial-label="row[column.FieldName_v]"
@update:label="row[column.FieldName_v] = $event" />
</template>
<template v-else-if="column.edit_type === 'singleId'">
<g3selectid v-model="row[column.prop]" :tablename="column.edit_source_table"
value-key="b_id" :label-key="column.edit_source_field"
:initial-value="row[column.prop]" :initial-label="row[column.FieldName_v]"
@update:label="row[column.FieldName_v] = $event" />
</template>
<template v-else-if="column.edit_type === 'single'">
<g3selectname v-model="row[column.prop]" :tablename="column.edit_source_table"
:label-key="column.edit_source_field" :initial-label="row[column.prop]"
/>
</template>
<el-date-picker v-else-if="column.edit_type === 'datetime'" v-model="row[column.prop]"
type="datetime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%" placeholder="请输入时间" />
<el-date-picker v-else-if="column.edit_type === 'date'" v-model="row[column.prop]"
type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="请输入时间"
style="width: 100%" />
<el-input v-else v-model="row[column.prop]" size="small" />
</template>
</el-table-column>
<!-- 操作列 -->
<el-table-column width="160" fixed="right" align="center">
<!-- 表头 -->
<template #header>
<div class="action-header-column">
<span class="action-label" style="margin-right: 6px">操作</span>
</div>
</template>
<!-- 每行按钮 -->
<template #default="{ $index }">
<div class="table-actions">
<el-button size="small" type="danger" @click="deleteRow($index)"
style="height: 24px">
删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 错误提示 -->
<el-alert v-if="error" class="g3-error-message" :title="error" type="error" show-icon closable
@close="error = ''" />
</div>
</div>
<TableDialog
v-model:visible="dialogVisible"
title="选择订阅数据"
tableName="v_cw_zdorderfee_s_business"
:whereClause="`2>1 and isnull(mx_zdorderid,'')='' and alreadyamount=0 and mx_type_id='应收'`"
@confirm="onConfirm"
width="70%"
top="6vh"
maxHeight="650"
/>
<TableDialogSelect
v-model:visible="dialogVisibleSelect"
title="选择发货人"
tableName="Businesstoshippermemo1"
whereClause=""
@confirm="onConfirmSelect"
width="70%"
top="6vh"
maxHeight="650"
:psparams="psparams"
/>
</template>
<script setup lang="ts">
import { ref, onMounted, getCurrentInstance } from 'vue'
import axios from '@/utils/axios'
import { ElMessage,ElMessageBox } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import dayjs from 'dayjs'
import {isEqual, compareAndClassifyData, detectChanges, fillDefaultArray,} from '@/utils/dataDiffUtils'
import g3selectid from '@/components/g3selectid.vue'
import g3selectname from '@/components/g3selectname.vue'
import Sortable from "sortablejs"
import TableDialog from '@/components/TableDialog.vue'
import TableDialogSelect from '@/components/TableDialogSingleQuery.vue'
import { useUserStore } from '@/stores/userStore'
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const route = useRoute()
const router = useRouter()
const bBzRows = ref(1)
const loading = ref(false)
const saving = ref(false)
const error = ref('')
const maintable = ref([])
const maintableorigina = ref([])
const columns = ref([])
const subtable = ref([])
const subtableoriginal = ref([])
const id = ref(route.query.id ?? '')
const customer_id = route.query.customer_id
const v_customer_name = route.query.v_customer_name
const op = ref(String(route.query.op ?? ''))
const oldRows = route.query.oldRows ? route.query.oldRows.split(',') : []
//////////////////////////
const sparams = ref([])
let psparams = ''
//sparams.value.push(subtable.value.b_dw_id)
sparams.value.push('HBKF')
psparams = sparams.value.join(',')
const dialogVisibleSelect = ref(false)
const openDialogSelect = () => {
dialogVisibleSelect.value = true
}
// 获取用户选择的行
const onConfirmSelect = (selectedRows) => {
console.log('选中的行:', selectedRows)
const subidStr = selectedRows.map(id => `'${id}'`).join(',')
const whereClause = `subid IN (${subidStr})`
}
/////////////////
//////////////
const dialogVisible = ref(false)
const openDialog = () => {
dialogVisible.value = true
}
// 获取用户选择的行
const onConfirm = (selectedRows) => {
console.log('选中的行:', selectedRows)
const subidStr = selectedRows.map(id => `'${id}'`).join(',')
const whereClause = `subid IN (${subidStr})`
getsubtable('v_cw_zdorderfee_s_business', subtable, subtableoriginal, whereClause)
}
const getsubtable1 = async (tableName, targetRef, originalRef, whereClause) => {
try {
loading.value = true
error.value = null
const params = {
tableName: tableName || 'v_bs_business_container',
pkColumn: 'subid',
whereClause,
}
const response = await axios.get('/pagdetail', { params })
if (response.data?.success) {
const rawData = JSON.parse(JSON.stringify(response.data.data.records || []))
targetRef.value = {
...targetRef.value,
...JSON.parse(JSON.stringify(rawData))
}
} else {
throw new Error(response.data?.message || '返回数据格式异常')
}
} catch (err) {
error.value = `加载数据失败: ${err.message}`
console.error('API Error:', err)
return { data: [], total: 0 }
} finally {
loading.value = false
}
}
//////////////
const getmaintable = async () => {
try {
loading.value = true
error.value = ''
maintable.value = null
const params = {
tableName: "v_cw_order_s",
pkColumn: "b_id",
pkColumnValue: id.value
}
const response = await axios.get('/getobject', { params })
if (response.data?.success) {
maintable.value = { ...response.data.data } || null
maintableorigina.value = { ...response.data.data }
if (!maintable.value) {
ElMessage.warning('未找到对应记录')
}
} else {
throw new Error(response.data?.message || '返回数据格式异常')
}
} catch (err) {
error.value = `加载客户详情失败: ${err.message}`
console.error('加载客户详情错误:', err)
} finally {
loading.value = false
}
}
const handleNew = () => {
maintable.value = []
maintableorigina.value = []
maintable.value.b_customer_id = customer_id
maintable.value.v_customer_name = v_customer_name
id.value = ''
op.value = 'new'
}
const handleCope = () => {
id.value = ''
maintable.value.b_id = maintable.value.b_id + "cope"
op.value = 'new'
}
const fetchTableColumnsEdit = async (tableName, targetRef) => {
try {
loading.value = true
error.value = null
const response = await axios.get('/columnsEdit', {
params: { tableName },
})
if (response.data?.success) {
// 直接对传入的响应式引用赋值
targetRef.value = response.data.data
} else {
throw new Error(response.data?.message || '返回数据格式异常')
}
} catch (err) {
error.value = `加载列配置失败: ${err.message}`
// 出错时赋空数组
targetRef.value = []
} finally {
loading.value = false
}
}
const getsubtable = async (tableName, targetRef, originalRef, whereClause) => {
console.log(tableName)
console.log(whereClause)
try {
loading.value = true
error.value = null
const params = {
tableName: tableName || 'v_bs_business_container',
pkColumn: 'subid',
whereClause,
}
const response = await axios.get('/pagdetail', { params })
console.log(response)
if (response.data?.success) {
const rawData = JSON.parse(JSON.stringify(response.data.data.records || []))
targetRef.value = JSON.parse(JSON.stringify(rawData))
originalRef.value = JSON.parse(JSON.stringify(rawData))
} else {
throw new Error(response.data?.message || '返回数据格式异常')
}
} catch (err) {
error.value = `加载数据失败: ${err.message}`
console.error('API Error:', err)
return { data: [], total: 0 }
} finally {
loading.value = false
}
}
const handleUpdateWidth = (newWidth, oldWidth, column, event) => {
// 更新配置中的宽度
const index = columns.value.findIndex(c => c.prop === column.property);
if (index >= 0) {
const newColumns = [...columns.value];
newColumns[index] = {
...newColumns[index],
width: parseInt(newWidth) || newWidth // 确保是数字
};
columns.value = newColumns;
}
}
const handleSaveColumn = async () => {
try {
saving.value = true
error.value = ''
const newColumns = columns.value.map(item => ({
...item,
col_TableName: 'v_cw_zdorderfee_s_business' // 或者你要的默认值
}))
const response = await axios.post('/saveColumnEdit', newColumns, {
headers: { 'Content-Type': 'application/json' }
})
if (response.data?.success) {
ElMessage.success('保存成功')
} else {
throw new Error(response.data?.message || '保存失败')
}
} catch (err) {
error.value = `保存失败: ${err.message}`
ElMessage.error('保存失败')
} finally {
saving.value = false
}
}
const handleSave = async () => {
try {
saving.value = true
error.value = ''
let updatemaintable = null;
let insertmaintable = null;
let maintableChanges = false
// 使用提取的函数检测变更
//console.log(id)
if (op.value === 'mod') {
const { hasChanges, updateData } = detectChanges(
maintable.value,
maintableorigina.value,
'b_id',
maintable.value.b_id
)
maintableChanges = hasChanges
updatemaintable = updateData
} else {
maintableChanges = true
maintable.value.b_inputdatetime = dayjs().format('YYYY-MM-DD HH:mm:ss')
maintable.value.b_inputuser_id = userStore.userInfo.orgid.username
maintable.value.b_state = '草拟'
maintable.value.b_type='应收'
insertmaintable = { ...maintable.value };
insertmaintable = [insertmaintable]
}
//console.log(updatemaintable)
if (!maintableChanges) {
ElMessage.info('没有数据变更')
return
}
/*const updateArr = subtable.value.map(row => {
const obj = {}
columns.value.forEach(col => {
if (!col.prop.startsWith('v_')) {
obj[col.prop] = row[col.prop] ?? ''
}
})
return obj
})*/
const updateArr = subtable.value.map(row => {
const obj = {}
obj.subid = row.subid
obj.mx_zdorderid = maintable.value.b_id
obj.mx_zdorder_state = ''
return obj
})
const delArr = subtableoriginal.value.filter(
(originalRow) => !subtable.value.some((row) => row['subid'] === originalRow['subid']),
)
const delArrDate = delArr.map(row => {
const obj = {}
obj.subid = row.subid
obj.mx_zdorderid = ''
obj.mx_zdorder_state = maintable.value.b_state
return obj
})
console.log(delArrDate)
const updatesubtable = [...updateArr, ...delArrDate]
const requestData = [
{
tableName: 'cw_zdorder',
keyField: 'b_id',
inserts: insertmaintable,
updates: updatemaintable,
deletes: [],
},
{
tableName: 'bs_business_cw',
keyField: 'subid',
inserts: [],
updates: updatesubtable,
deletes: [],
},
]
const response = await axios.post('/saveobjectV2', requestData, {
headers: { 'Content-Type': 'application/json' }
})
if (response.data?.success) {
ElMessage.success('保存成功')
maintableorigina.value = { ...maintable.value }
} else {
throw new Error(response.data?.message || '保存失败')
}
} catch (err) {
error.value = `保存失败: ${err.message}`
console.error('保存错误:', err)
ElMessage.error('保存失败')
} finally {
saving.value = false
}
}
const deleteRow = (index) => {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
subtable.value.splice(index, 1)
ElMessage.success('删除成功')
})
}
// 初始化加载数据
onMounted(async () => {
if (op.value === 'mod') {
getmaintable()
fetchTableColumnsEdit('v_cw_zdorderfee_s_business', columns)
getsubtable('v_cw_zdorderfee_s_business', subtable, subtableoriginal, `mx_zdorderid = '${id.value}'`)
} else {
maintable.value.b_customer_id = customer_id
maintable.value.v_customer_name = v_customer_name
maintable.value.b_state = '草拟'
fetchTableColumnsEdit('v_cw_zdorderfee_s_business', columns)
if (oldRows && oldRows.length > 0) {
console.log('有数据:', oldRows)
// 拼接 SQL 条件
const subidStr = oldRows.map(id => `'${id}'`).join(',')
const whereClause = `subid IN (${subidStr})`
getsubtable('bs_business_cw', subtable, subtableoriginal, whereClause)
}
}
// el-table 表头行
const headerRow = document.querySelector(".el-table__header-wrapper tr")
Sortable.create(headerRow, {
animation: 150,
handle: "th", // 允许拖动 th
onEnd(evt) {
const oldIndex = evt.oldIndex - 1 // 减掉 selection 列
const newIndex = evt.newIndex - 1
if (oldIndex >= 0 && newIndex >= 0) {
const moved = columns.value.splice(oldIndex, 1)[0]
columns.value.splice(newIndex, 0, moved)
}
}
})
})
</script>
<style scoped>
.g3-flex-container {
box-sizing: border-box;
display: flex;
background-color: #f2f3f5;
width: 100%;
height: 100%;
padding: 10px 12px;
flex-direction: column;
.g3-flex-main {
display: flex;
flex-direction: column;
width: 100%;
padding: 10px;
overflow-y: auto;
background-color: #fff;
border-right: 1px solid #e4e7ed;
border-radius: 6px;
box-shadow: 0 0 12px #0000000d;
}
}
.g3-toolbar {
order: 1;
height: 31px;
display: flex;
justify-content: left;
}
.g3-content {
order: 1;
margin-bottom: 20px;
display: flex;
flex: 1;
overflow-y: auto;
padding: 15px;
flex-direction: column;
}
.g3-error-message {
order: 2;
margin: 15px 0;
}
.g3-grid{
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
border: 1px solid #ddd;
background-color: #ddd;
width: 900px;
}
:deep(.g3-grid .el-input__wrapper) {
border-radius: 0px;
}
.g3-cell{
display: flex;
/* 两列 */
align-items: center;
color: #333;
font-size: 14px;
height: 24px;
}
.g3-cell-label {
padding: 8px;
border-right: 1px solid #ddd;
display: flex;
align-items: center;
justify-content: flex-end;
width: 100px;
flex-shrink: 0;
height: 100%;
background: #f9f9f9;
}
/* ///////////////// */
/* 输入框样式 */
:deep(.el-input) {
width: 100%;
height: 24px !important;
line-height: 24px !important;
}
:deep(.g3-grid .el-input__wrapper) {
border-radius: 0px;
}
:deep(.el-input__inner) {
height: 24px !important;
line-height: 24px !important;
}
:deep(.el-input__wrapper) {
padding: 1px 11px;
}
:deep(.el-input__wrapper) {
border: none !important;
box-shadow: none !important;
}
:deep(.el-select .el-select__wrapper) {
height: 24px !important;
line-height: 24px !important;
min-height: 24px;
border: none !important;
box-shadow: none !important;
border-radius: 0px;
}
:deep(.g3-select-height .el-select .el-select__wrapper) {
height: 100% !important;
padding: 2px 11px !important;
align-items: flex-start;
}
:deep(.el-checkbox.el-checkbox--large) {
height: 24px;
}
:deep(.g3-cell-textarea .el-textarea__inner) {
border-radius: 0px;
box-shadow: unset;
height: 24px !important;
min-height: 24px !important;
}
:deep(.g3-cell-textarea .el-textarea__inner:focus) {
-webkit-box-shadow: 0 0 0 1px var(--el-input-focus-border-color) inset;
box-shadow: 0 0 0 1px var(--el-input-focus-border-color) inset;
outline: none;
}
/* ////////////// */
:deep(.el-table .el-table__cell) {
padding: 0px;
}
:deep(.el-table .cell) {
padding: 0px;
}
.g3-my-table ::v-deep(.el-table__header-wrapper th) {
background-color: #f5f7fa !important;
color: #303133 !important;
}
:deep(.el-tabs__content) {
flex: 1;
display: flex;
}
.table-actions {
display: flex;
align-items: center;
justify-content: center;
}
/**下拉 */
.el-dropdown-link {
cursor: pointer;
display: flex;
align-items: center;
margin-left: 14px;
justify-content: center;
color: #606266;
border-radius: 3px;
border: 1px solid #dcdfe6;
padding: 8px 15px;
}
.el-dropdown .g3-svg-query:focus,
.el-dropdown-link:focus {
outline: none !important;
}
</style>