feat: 优化估值记录分页及跳转功能,重构企业转让凭证上传与开票信息管理,并调整开票管理为抬头管理
This commit is contained in:
parent
1b56856995
commit
a148b94dff
@ -49,7 +49,7 @@ export const basicRoutes = [
|
||||
path: 'invoice',
|
||||
component: () => import('@/views/user-center/components/InvoiceManagement.vue'),
|
||||
meta: {
|
||||
title: '开票管理',
|
||||
title: '抬头管理',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -1087,10 +1087,11 @@ const previousStep = () => {
|
||||
currentStep.value --
|
||||
}
|
||||
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { unref } from 'vue'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const navToLogin = () => {
|
||||
userStore.logout()
|
||||
@ -1191,10 +1192,12 @@ const submit = () => {
|
||||
const getHistoryList = () => {
|
||||
const params = {
|
||||
page: 1,
|
||||
size: 99
|
||||
page_size: 99
|
||||
};
|
||||
api.getHistoryList(params).then(res=>{
|
||||
historyList.value = res.data
|
||||
return api.getHistoryList(params).then(res=>{
|
||||
const list = res?.data?.items ?? res?.data?.results ?? res?.results ?? []
|
||||
historyList.value = Array.isArray(list) ? list : []
|
||||
return res
|
||||
})
|
||||
}
|
||||
const selectedObj = ref({
|
||||
@ -1327,6 +1330,14 @@ onMounted(async () => {
|
||||
page_size: 99
|
||||
};
|
||||
await getHistoryList()
|
||||
|
||||
if (route.query.id) {
|
||||
const targetId = Number(route.query.id)
|
||||
const targetItem = historyList.value.find(item => item.id === targetId)
|
||||
if (targetItem) {
|
||||
selectTimeBox(targetItem)
|
||||
}
|
||||
}
|
||||
// 使用await提高可读性
|
||||
const res = await api.getIndustryList(params);
|
||||
|
||||
|
||||
@ -81,63 +81,69 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第二步:上传凭证 -->
|
||||
<!-- 第二步:上传凭证 -->
|
||||
<div v-if="currentStep === 2" class="step-content">
|
||||
<div class="form-container">
|
||||
<div class="form-group">
|
||||
<div class="form-label required">上传支付凭证</div>
|
||||
<div class="upload-box" @click="triggerFileInput">
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
style="display: none"
|
||||
@change="handleFileChange"
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="formModel"
|
||||
label-placement="top"
|
||||
require-mark-placement="left"
|
||||
class="custom-form"
|
||||
>
|
||||
<n-form-item label="上传支付凭证" required>
|
||||
<n-upload
|
||||
v-model:file-list="fileList"
|
||||
list-type="image-card"
|
||||
:max="1"
|
||||
accept="image/png,image/jpeg,image/jpg"
|
||||
:custom-request="customRequest"
|
||||
@change="handleUploadChange"
|
||||
>
|
||||
<div class="upload-trigger">
|
||||
<div class="upload-icon">+</div>
|
||||
<div class="upload-text">添加图片</div>
|
||||
</div>
|
||||
</n-upload>
|
||||
<template #feedback>
|
||||
<div class="form-tip">支持jpg、png、jpeg格式,大小不超过5M</div>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="开票抬头" required>
|
||||
<div class="select-wrapper">
|
||||
<n-select
|
||||
v-model:value="formModel.invoiceHeader"
|
||||
:options="invoiceHeaderOptions"
|
||||
placeholder="请选择开票抬头"
|
||||
class="flex-1"
|
||||
/>
|
||||
<div class="add-header-link" @click="handleAddHeader">+ 添加抬头</div>
|
||||
</div>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="开票类型" required>
|
||||
<n-select
|
||||
v-model:value="formModel.invoiceType"
|
||||
:options="invoiceTypeOptions"
|
||||
placeholder="请选择开票类型"
|
||||
/>
|
||||
<div v-if="!uploadedFile" class="upload-placeholder">
|
||||
<div class="upload-icon">+</div>
|
||||
<div class="upload-text">点击上传</div>
|
||||
</div>
|
||||
<div v-else class="upload-preview">
|
||||
<img :src="uploadedFileUrl" alt="支付凭证" />
|
||||
<div class="upload-remove" @click.stop="removeFile">×</div>
|
||||
</div>
|
||||
</n-form-item>
|
||||
|
||||
<div class="btn-container">
|
||||
<n-button
|
||||
type="primary"
|
||||
class="submit-btn"
|
||||
:disabled="!isFormValid"
|
||||
@click="handleUploadSubmit"
|
||||
color="#A30113"
|
||||
style="width: 200px; height: 40px;"
|
||||
>
|
||||
确认上传
|
||||
</n-button>
|
||||
</div>
|
||||
<div class="form-tip">支持jpg、png、jpeg格式,大小不超过5M</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-label required">开票抬头</div>
|
||||
<div class="select-wrapper">
|
||||
<select v-model="selectedInvoiceHeader" class="custom-select">
|
||||
<option value="" disabled selected>请选择开票抬头</option>
|
||||
<option v-for="opt in invoiceHeaderOptions" :key="opt.value" :value="opt.value">
|
||||
{{ opt.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div class="add-header-link" @click="handleAddHeader">+ 添加抬头</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-label required">开票类型</div>
|
||||
<select v-model="selectedInvoiceType" class="custom-select">
|
||||
<option value="" disabled selected>请选择开票类型</option>
|
||||
<option v-for="opt in invoiceTypeOptions" :key="opt.value" :value="opt.value">
|
||||
{{ opt.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="btn-container">
|
||||
<button
|
||||
class="primary-btn"
|
||||
:disabled="!uploadedFile || !selectedInvoiceHeader || !selectedInvoiceType"
|
||||
@click="handleUploadSubmit"
|
||||
>
|
||||
确认上传
|
||||
</button>
|
||||
</div>
|
||||
</n-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -158,17 +164,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 引入抬头管理弹窗 -->
|
||||
<InvoiceModal
|
||||
v-model:show="showInvoiceModal"
|
||||
@submit="handleInvoiceModalSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import InvoiceModal from './InvoiceModal.vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
const emit = defineEmits(['return-home'])
|
||||
|
||||
@ -181,9 +183,8 @@ const uploadedFile = ref(null)
|
||||
const uploadedFileUrl = ref('')
|
||||
|
||||
// 表单选择相关
|
||||
const selectedInvoiceHeader = ref('')
|
||||
const selectedInvoiceType = ref('')
|
||||
const showInvoiceModal = ref(false)
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
// 开票抬头选项
|
||||
const invoiceHeaderOptions = ref([
|
||||
@ -204,60 +205,51 @@ function handleNextStep() {
|
||||
}
|
||||
}
|
||||
|
||||
// 触发文件选择
|
||||
function triggerFileInput() {
|
||||
fileInput.value?.click()
|
||||
}
|
||||
|
||||
// 处理文件选择
|
||||
function handleFileChange(event) {
|
||||
const file = event.target.files?.[0]
|
||||
if (file) {
|
||||
// 验证文件类型
|
||||
if (!file.type.startsWith('image/')) {
|
||||
$message.warning('请上传图片格式的文件')
|
||||
return
|
||||
}
|
||||
|
||||
uploadedFile.value = file
|
||||
uploadedFileUrl.value = URL.createObjectURL(file)
|
||||
}
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
function removeFile() {
|
||||
uploadedFile.value = null
|
||||
uploadedFileUrl.value = ''
|
||||
if (fileInput.value) {
|
||||
fileInput.value.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
// 添加抬头
|
||||
function handleAddHeader() {
|
||||
showInvoiceModal.value = true
|
||||
router.push({ path: '/user-center/invoice', query: { action: 'create' } })
|
||||
}
|
||||
|
||||
// 处理抬头弹窗提交
|
||||
function handleInvoiceModalSubmit(data) {
|
||||
// 模拟添加抬头
|
||||
const newOption = { label: data.name, value: 'header_' + Date.now() }
|
||||
invoiceHeaderOptions.value.push(newOption)
|
||||
selectedInvoiceHeader.value = newOption.value
|
||||
showInvoiceModal.value = false
|
||||
$message.success('添加抬头成功')
|
||||
// 表单数据
|
||||
const formModel = reactive({
|
||||
invoiceHeader: null,
|
||||
invoiceType: null
|
||||
})
|
||||
const fileList = ref([])
|
||||
const message = useMessage()
|
||||
|
||||
// 计算表单是否有效
|
||||
const isFormValid = computed(() => {
|
||||
return fileList.value.length > 0 && formModel.invoiceHeader && formModel.invoiceType
|
||||
})
|
||||
|
||||
// 自定义上传请求(模拟)
|
||||
const customRequest = ({ file, onFinish }) => {
|
||||
setTimeout(() => {
|
||||
onFinish()
|
||||
}, 500)
|
||||
}
|
||||
|
||||
// 处理上传变化
|
||||
function handleUploadChange({ fileList: newFileList }) {
|
||||
fileList.value = newFileList
|
||||
if (newFileList.length > 0) {
|
||||
uploadedFile.value = newFileList[0].file
|
||||
} else {
|
||||
uploadedFile.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// 提交上传
|
||||
function handleUploadSubmit() {
|
||||
if (!uploadedFile.value || !selectedInvoiceHeader.value || !selectedInvoiceType.value) {
|
||||
$message.warning('请完成所有必填项')
|
||||
if (!isFormValid.value) {
|
||||
message.warning('请完成所有必填项')
|
||||
return
|
||||
}
|
||||
|
||||
// 这里可以调用API上传文件
|
||||
// 暂时直接进入下一步
|
||||
$message.success('上传成功')
|
||||
message.success('上传成功')
|
||||
currentStep.value = 3
|
||||
}
|
||||
|
||||
@ -408,83 +400,7 @@ defineExpose({
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form-label.required::before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.upload-box {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border: 1px dashed #DCDFE6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.3s;
|
||||
background: #F5F7FA;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.upload-box:hover {
|
||||
border-color: #A30113;
|
||||
}
|
||||
|
||||
.upload-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.upload-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.upload-preview img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.upload-remove {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
font-size: 12px;
|
||||
@ -496,23 +412,14 @@ defineExpose({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.custom-select {
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
border: 1px solid #DCDFE6;
|
||||
border-radius: 4px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
outline: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.custom-select:focus {
|
||||
border-color: #A30113;
|
||||
}
|
||||
|
||||
|
||||
.add-header-link {
|
||||
font-size: 14px;
|
||||
@ -572,4 +479,23 @@ defineExpose({
|
||||
background: #fab6b6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.upload-trigger {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 24px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -22,18 +22,107 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<InvoiceModal
|
||||
<!-- 添加/编辑抬头弹窗 -->
|
||||
<n-modal
|
||||
v-model:show="showModal"
|
||||
:edit-data="currentInvoice"
|
||||
@submit="handleModalSubmit"
|
||||
/>
|
||||
:mask-closable="false"
|
||||
preset="card"
|
||||
:title="currentInvoice ? '编辑抬头' : '添加抬头'"
|
||||
class="invoice-modal"
|
||||
:style="{ width: '600px' }"
|
||||
:bordered="false"
|
||||
:segmented="{ content: true }"
|
||||
>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-placement="top"
|
||||
require-mark-placement="left"
|
||||
:show-feedback="true"
|
||||
>
|
||||
<n-grid :cols="2" :x-gap="16">
|
||||
<!-- 公司名称 -->
|
||||
<n-form-item-gi :span="1" path="companyName" label="公司名称">
|
||||
<n-input
|
||||
v-model:value="formData.companyName"
|
||||
placeholder="请输入公司名称"
|
||||
clearable
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 公司税号 -->
|
||||
<n-form-item-gi :span="1" path="taxNumber" label="公司税号">
|
||||
<n-input
|
||||
v-model:value="formData.taxNumber"
|
||||
placeholder="请输入公司税号"
|
||||
clearable
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 注册地址 -->
|
||||
<n-form-item-gi :span="2" path="registeredAddress" label="注册地址">
|
||||
<n-input
|
||||
v-model:value="formData.registeredAddress"
|
||||
placeholder="请输入注册地址"
|
||||
clearable
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 注册电话 -->
|
||||
<n-form-item-gi :span="2" path="registeredPhone" label="注册电话">
|
||||
<n-input
|
||||
v-model:value="formData.registeredPhone"
|
||||
placeholder="请输入注册电话"
|
||||
clearable
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 开户银行 -->
|
||||
<n-form-item-gi :span="1" path="bankName" label="开户银行">
|
||||
<n-input
|
||||
v-model:value="formData.bankName"
|
||||
placeholder="请输入开户银行"
|
||||
clearable
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 银行账号 -->
|
||||
<n-form-item-gi :span="1" path="bankAccount" label="银行账号">
|
||||
<n-input
|
||||
v-model:value="formData.bankAccount"
|
||||
placeholder="请输入银行账号"
|
||||
clearable
|
||||
/>
|
||||
</n-form-item-gi>
|
||||
|
||||
<!-- 电子邮箱 -->
|
||||
<n-form-item-gi :span="2" path="email" label="电子邮箱">
|
||||
<n-input
|
||||
v-model:value="formData.email"
|
||||
placeholder="请输入邮箱"
|
||||
clearable
|
||||
/>
|
||||
<template #feedback>
|
||||
<span class="email-hint">此邮箱用于接收发票,请填写正确!</span>
|
||||
</template>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
</n-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="modal-footer">
|
||||
<n-button class="cancel-btn" @click="handleCancel">取消</n-button>
|
||||
<n-button class="save-btn" @click="handleSave">保存</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { h, ref } from 'vue'
|
||||
import { NButton, NDataTable, NSpace } from 'naive-ui'
|
||||
import InvoiceModal from './InvoiceModal.vue'
|
||||
import { h, ref, watch } from 'vue'
|
||||
import { NButton, NDataTable, NSpace, NModal, NForm, NFormItemGi, NGrid, NInput } from 'naive-ui'
|
||||
|
||||
const props = defineProps({
|
||||
invoiceList: {
|
||||
@ -46,6 +135,57 @@ const emit = defineEmits(['add-invoice', 'delete-invoice', 'update-invoice'])
|
||||
|
||||
const showModal = ref(false)
|
||||
const currentInvoice = ref(null)
|
||||
const formRef = ref(null)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
companyName: '',
|
||||
taxNumber: '',
|
||||
registeredAddress: '',
|
||||
registeredPhone: '',
|
||||
bankName: '',
|
||||
bankAccount: '',
|
||||
email: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
companyName: [
|
||||
{ required: true, message: '请输入公司名称', trigger: 'blur' }
|
||||
],
|
||||
taxNumber: [
|
||||
{ required: true, message: '请输入公司税号', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: '请输入电子邮箱', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
||||
message: '请输入正确的邮箱格式',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// 监听弹窗显示状态,重置表单
|
||||
watch(showModal, (newVal) => {
|
||||
if (newVal) {
|
||||
if (currentInvoice.value) {
|
||||
// 编辑模式,填充数据
|
||||
formData.value = { ...currentInvoice.value }
|
||||
} else {
|
||||
// 新增模式,清空数据
|
||||
formData.value = {
|
||||
companyName: '',
|
||||
taxNumber: '',
|
||||
registeredAddress: '',
|
||||
registeredPhone: '',
|
||||
bankName: '',
|
||||
bankAccount: '',
|
||||
email: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 添加开票
|
||||
function handleAddInvoice() {
|
||||
@ -65,6 +205,21 @@ function handleDeleteInvoice(invoice) {
|
||||
emit('delete-invoice', invoice)
|
||||
}
|
||||
|
||||
// 取消
|
||||
function handleCancel() {
|
||||
showModal.value = false
|
||||
formRef.value?.restoreValidation()
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleSave() {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
handleModalSubmit(formData.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 处理弹窗提交
|
||||
function handleModalSubmit(data) {
|
||||
if (currentInvoice.value) {
|
||||
@ -83,7 +238,7 @@ const columns = [
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
titleAlign: 'center',
|
||||
render: (row) => row.name || '-'
|
||||
render: (row) => row.name || row.companyName || '-'
|
||||
},
|
||||
{
|
||||
title: '税号',
|
||||
@ -91,7 +246,7 @@ const columns = [
|
||||
minWidth: 200,
|
||||
align: 'center',
|
||||
titleAlign: 'center',
|
||||
render: (row) => row.taxId || '123456789012345678'
|
||||
render: (row) => row.taxId || row.taxNumber || '123456789012345678'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
@ -131,7 +286,7 @@ const columns = [
|
||||
}
|
||||
]
|
||||
|
||||
const rowKey = (row) => row.id ?? row.name ?? row.taxId
|
||||
const rowKey = (row) => row.id ?? row.name ?? row.companyName ?? row.taxId ?? row.taxNumber
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -194,4 +349,85 @@ const rowKey = (row) => row.id ?? row.name ?? row.taxId
|
||||
.table-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
:deep(.invoice-modal) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
:deep(.invoice-modal .n-card-header) {
|
||||
padding: 20px 24px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
:deep(.invoice-modal .n-card__content) {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
:deep(.n-form-item-label) {
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
:deep(.n-form-item-label__asterisk) {
|
||||
color: #A30113;
|
||||
}
|
||||
|
||||
:deep(.n-input) {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:deep(.n-input__input-el::placeholder) {
|
||||
color: #C0C4CC;
|
||||
}
|
||||
|
||||
.email-hint {
|
||||
font-size: 12px;
|
||||
color: #A30113;
|
||||
margin-top: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
padding: 8px 24px;
|
||||
border: 1px solid #DCDFE6;
|
||||
background: white;
|
||||
color: #606266;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.cancel-btn:hover {
|
||||
border-color: #C0C4CC;
|
||||
background: #F5F7FA;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
padding: 8px 24px;
|
||||
background: #A30113;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.save-btn:hover {
|
||||
background: #880C22;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,275 +0,0 @@
|
||||
<template>
|
||||
<div v-if="show" class="modal-overlay" @click="handleClose">
|
||||
<div class="modal-content" @click.stop>
|
||||
<div class="modal-header">
|
||||
<div class="header-title">{{ editData ? '编辑抬头' : '添加抬头' }}</div>
|
||||
<div class="close-btn" @click="handleClose">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 6L6 18M6 6L18 18" stroke="#909399" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-item">
|
||||
<div class="label required">公司名称</div>
|
||||
<input
|
||||
v-model="formData.name"
|
||||
type="text"
|
||||
placeholder="请输入公司名称"
|
||||
class="custom-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="label required">税号</div>
|
||||
<input
|
||||
v-model="formData.taxId"
|
||||
type="text"
|
||||
placeholder="请输入纳税人识别号"
|
||||
class="custom-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="label">注册地址</div>
|
||||
<input
|
||||
v-model="formData.address"
|
||||
type="text"
|
||||
placeholder="请输入注册地址"
|
||||
class="custom-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="label">注册电话</div>
|
||||
<input
|
||||
v-model="formData.phone"
|
||||
type="text"
|
||||
placeholder="请输入注册电话"
|
||||
class="custom-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="label">开户银行</div>
|
||||
<input
|
||||
v-model="formData.bank"
|
||||
type="text"
|
||||
placeholder="请输入开户银行"
|
||||
class="custom-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<div class="label">银行账号</div>
|
||||
<input
|
||||
v-model="formData.account"
|
||||
type="text"
|
||||
placeholder="请输入银行账号"
|
||||
class="custom-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-note">
|
||||
* 电子发票(PDF)和纸质发票具有同等法律效力,可支持报销入账
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn cancel" @click="handleClose">取消</button>
|
||||
<button class="btn submit" @click="handleSubmit">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
editData: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:show', 'submit'])
|
||||
|
||||
const formData = ref({
|
||||
name: '',
|
||||
taxId: '',
|
||||
address: '',
|
||||
phone: '',
|
||||
bank: '',
|
||||
account: ''
|
||||
})
|
||||
|
||||
watch(() => props.show, (newVal) => {
|
||||
if (newVal) {
|
||||
if (props.editData) {
|
||||
formData.value = { ...props.editData }
|
||||
} else {
|
||||
formData.value = {
|
||||
name: '',
|
||||
taxId: '',
|
||||
address: '',
|
||||
phone: '',
|
||||
bank: '',
|
||||
account: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function handleClose() {
|
||||
emit('update:show', false)
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
if (!formData.value.name || !formData.value.taxId) {
|
||||
$message.warning('请填写必填项')
|
||||
return
|
||||
}
|
||||
emit('submit', formData.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
width: 600px;
|
||||
max-width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px 24px;
|
||||
border-bottom: 1px solid #EBEEF5;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
cursor: pointer;
|
||||
color: #909399;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.close-btn:hover {
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.label.required::before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.custom-input {
|
||||
height: 40px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #DCDFE6;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
outline: none;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
|
||||
.custom-input:focus {
|
||||
border-color: #A30113;
|
||||
}
|
||||
|
||||
.custom-input::placeholder {
|
||||
color: #C0C4CC;
|
||||
}
|
||||
|
||||
.form-note {
|
||||
font-size: 12px;
|
||||
color: #A30113;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 20px 24px;
|
||||
border-top: 1px solid #EBEEF5;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 24px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.btn.cancel {
|
||||
background: white;
|
||||
border-color: #DCDFE6;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.btn.cancel:hover {
|
||||
color: #A30113;
|
||||
border-color: #fde2e2;
|
||||
background-color: #fef0f0;
|
||||
}
|
||||
|
||||
.btn.submit {
|
||||
background: #A30113;
|
||||
border-color: #A30113;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn.submit:hover {
|
||||
background: #880C22;
|
||||
border-color: #880C22;
|
||||
}
|
||||
</style>
|
||||
@ -15,7 +15,8 @@
|
||||
:columns="columns"
|
||||
:data="tableData"
|
||||
:row-key="rowKey"
|
||||
:pagination="false"
|
||||
:pagination="pagination"
|
||||
remote
|
||||
striped
|
||||
size="medium"
|
||||
/>
|
||||
@ -23,7 +24,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { h, onMounted, ref } from 'vue'
|
||||
import { h, onMounted, ref, reactive } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { NButton, NSpace } from 'naive-ui'
|
||||
import api from '@/api'
|
||||
|
||||
@ -34,6 +36,10 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref([...props.assetList])
|
||||
|
||||
@ -50,29 +56,72 @@ function formatDate(dateStr) {
|
||||
return `${dateStr.slice(0, 10)} ${dateStr.slice(11, 16)}`
|
||||
}
|
||||
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
itemCount: 0,
|
||||
showSizePicker: true,
|
||||
pageSizes: [10, 20, 50],
|
||||
prefix: ({ itemCount }) => `共 ${itemCount} 条`,
|
||||
onChange: (page) => {
|
||||
pagination.page = page
|
||||
fetchHistory()
|
||||
},
|
||||
onUpdatePageSize: (pageSize) => {
|
||||
pagination.pageSize = pageSize
|
||||
pagination.page = 1
|
||||
fetchHistory()
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
key: 'index',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
titleAlign: 'center',
|
||||
render: (_, index) => (pagination.page - 1) * pagination.pageSize + index + 1
|
||||
},
|
||||
{
|
||||
title: '资产名称',
|
||||
key: 'asset_name',
|
||||
minWidth: 200,
|
||||
ellipsis: true,
|
||||
render: (row) => row.asset_name || row.name || '未知资产',
|
||||
align: 'center',
|
||||
titleAlign: 'center',
|
||||
render: (row) => h(
|
||||
'div',
|
||||
{
|
||||
class: 'asset-name-link',
|
||||
onClick: () => {
|
||||
router.push({
|
||||
path: '/pages',
|
||||
query: { id: row.id }
|
||||
})
|
||||
}
|
||||
},
|
||||
row.asset_name || row.name || '未知资产'
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '评估时间',
|
||||
key: 'created_at',
|
||||
minWidth: 180,
|
||||
align: 'center',
|
||||
titleAlign: 'center',
|
||||
render: (row) => formatDate(row.created_at),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
align: 'right',
|
||||
align: 'center',
|
||||
titleAlign: 'center',
|
||||
width: 220,
|
||||
render: (row) =>
|
||||
h(
|
||||
NSpace,
|
||||
{ size: 8 },
|
||||
{ size: 8, justify: 'center' },
|
||||
{
|
||||
default: () => [
|
||||
h(
|
||||
@ -81,7 +130,10 @@ const columns = [
|
||||
text: true,
|
||||
type: 'primary',
|
||||
size: 'small',
|
||||
onClick: () => handleDownloadReport(row),
|
||||
onClick: (e) => {
|
||||
e.stopPropagation()
|
||||
handleDownloadReport(row)
|
||||
},
|
||||
},
|
||||
{ default: () => '下载报告' }
|
||||
),
|
||||
@ -91,7 +143,10 @@ const columns = [
|
||||
text: true,
|
||||
type: 'primary',
|
||||
size: 'small',
|
||||
onClick: () => handleDownloadCertificate(row),
|
||||
onClick: (e) => {
|
||||
e.stopPropagation()
|
||||
handleDownloadCertificate(row)
|
||||
},
|
||||
},
|
||||
{ default: () => '下载证书' }
|
||||
),
|
||||
@ -106,9 +161,13 @@ const rowKey = (row) => row.id ?? row.asset_name ?? row.name
|
||||
async function fetchHistory() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await api.getHistoryList({ page: 1, page_size: 50 })
|
||||
const list = res?.data?.results ?? res?.data ?? res?.results ?? []
|
||||
const res = await api.getHistoryList({
|
||||
page: pagination.page,
|
||||
page_size: pagination.pageSize
|
||||
})
|
||||
const list = res?.data?.items ?? res?.data?.results ?? res?.results ?? []
|
||||
tableData.value = Array.isArray(list) ? list : []
|
||||
pagination.itemCount = res?.data?.total ?? res?.total ?? 0
|
||||
} catch (error) {
|
||||
console.error('加载估值记录失败:', error)
|
||||
tableData.value = props.assetList
|
||||
@ -155,4 +214,16 @@ onMounted(fetchHistory)
|
||||
.empty-block {
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
:deep(.asset-name-link) {
|
||||
cursor: pointer;
|
||||
color: #A30113;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
:deep(.asset-name-link:hover) {
|
||||
opacity: 0.8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -72,79 +72,15 @@ const menuList = ref([
|
||||
{
|
||||
id: 'history',
|
||||
label: '估值记录',
|
||||
icon: () => h('svg', {
|
||||
width: 20,
|
||||
height: 20,
|
||||
viewBox: '0 0 24 24',
|
||||
fill: 'none',
|
||||
xmlns: 'http://www.w3.org/2000/svg'
|
||||
}, [
|
||||
h('path', {
|
||||
d: 'M12 8V12L15 15',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': 2,
|
||||
'stroke-linecap': 'round'
|
||||
}),
|
||||
h('circle', {
|
||||
cx: 12,
|
||||
cy: 12,
|
||||
r: 9,
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': 2
|
||||
})
|
||||
])
|
||||
},
|
||||
{
|
||||
id: 'transfer',
|
||||
label: '对公转账',
|
||||
icon: () => h('svg', {
|
||||
width: 20,
|
||||
height: 20,
|
||||
viewBox: '0 0 24 24',
|
||||
fill: 'none',
|
||||
xmlns: 'http://www.w3.org/2000/svg'
|
||||
}, [
|
||||
h('path', {
|
||||
d: 'M12 2V6M12 18V22M6 12H2M22 12H18',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': 2,
|
||||
'stroke-linecap': 'round'
|
||||
}),
|
||||
h('circle', {
|
||||
cx: 12,
|
||||
cy: 12,
|
||||
r: 4,
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': 2
|
||||
})
|
||||
])
|
||||
},
|
||||
{
|
||||
id: 'invoice',
|
||||
label: '开票管理',
|
||||
icon: () => h('svg', {
|
||||
width: 20,
|
||||
height: 20,
|
||||
viewBox: '0 0 24 24',
|
||||
fill: 'none',
|
||||
xmlns: 'http://www.w3.org/2000/svg'
|
||||
}, [
|
||||
h('rect', {
|
||||
x: 3,
|
||||
y: 3,
|
||||
width: 18,
|
||||
height: 18,
|
||||
rx: 2,
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': 2
|
||||
}),
|
||||
h('path', {
|
||||
d: 'M8 12H16M8 16H13',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': 2,
|
||||
'stroke-linecap': 'round'
|
||||
})
|
||||
])
|
||||
label: '抬头管理',
|
||||
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user