Merge branch 'main' of https://git.1024tool.vip/zfc/guzhi
This commit is contained in:
commit
f17c1678c8
@ -46,7 +46,8 @@ const activeDetailTab = ref('audit')
|
||||
const reportLoading = ref(false)
|
||||
const reportContent = ref('')
|
||||
|
||||
const pickFilledValue = (...values) => values.find((val) => val !== undefined && val !== null && val !== '')
|
||||
const pickFilledValue = (...values) =>
|
||||
values.find((val) => val !== undefined && val !== null && val !== '')
|
||||
const formatEnumField = (key, ...values) => formatEnumByKey(pickFilledValue(...values), key)
|
||||
|
||||
// 证书弹窗相关状态
|
||||
@ -72,7 +73,7 @@ watch(activeDetailTab, async (newTab) => {
|
||||
// 获取报告内容
|
||||
const fetchReport = async () => {
|
||||
if (!props.detailData?.id) return
|
||||
|
||||
|
||||
reportLoading.value = true
|
||||
try {
|
||||
const response = await api.getValuationReport({ valuation_id: props.detailData.id })
|
||||
@ -89,7 +90,7 @@ const fetchReport = async () => {
|
||||
const detailSections = computed(() => {
|
||||
const detail = props.detailData
|
||||
if (!detail) return []
|
||||
|
||||
|
||||
const sections = [
|
||||
{
|
||||
key: 'basic',
|
||||
@ -97,7 +98,11 @@ const detailSections = computed(() => {
|
||||
fields: [
|
||||
{ label: '资产名称', type: 'text', value: detail.asset_name || '-' },
|
||||
{ label: '所属机构/权利人', type: 'text', value: detail.institution || '-' },
|
||||
{ label: '统一社会信用代码/身份证号', type: 'text', value: detail.credit_code_or_id || '-' },
|
||||
{
|
||||
label: '统一社会信用代码/身份证号',
|
||||
type: 'text',
|
||||
value: detail.credit_code_or_id || '-',
|
||||
},
|
||||
{ label: '所属行业', type: 'text', value: detail.industry || '-' },
|
||||
{ label: '业务/传承介绍', type: 'text', value: detail.biz_intro || '-' },
|
||||
],
|
||||
@ -106,17 +111,37 @@ const detailSections = computed(() => {
|
||||
key: 'finance',
|
||||
title: '财务状况',
|
||||
fields: [
|
||||
{ label: '近12个月机构营收/万元', type: 'text', value: formatNumberValue(detail.annual_revenue) },
|
||||
{ label: '近12个月机构研发投入/万元', type: 'text', value: formatNumberValue(detail.rd_investment) },
|
||||
{ label: '近三年机构收益/万元', type: 'list', value: formatThreeYearIncome(detail.three_year_income) },
|
||||
{ label: '资产受资助情况', type: 'text', value: formatEnumField('fundingStatus', detail.funding_status) },
|
||||
{
|
||||
label: '近12个月机构营收/万元',
|
||||
type: 'text',
|
||||
value: formatNumberValue(detail.annual_revenue),
|
||||
},
|
||||
{
|
||||
label: '近12个月机构研发投入/万元',
|
||||
type: 'text',
|
||||
value: formatNumberValue(detail.rd_investment),
|
||||
},
|
||||
{
|
||||
label: '近三年机构收益/万元',
|
||||
type: 'list',
|
||||
value: formatThreeYearIncome(detail.three_year_income),
|
||||
},
|
||||
{
|
||||
label: '资产受资助情况',
|
||||
type: 'text',
|
||||
value: formatEnumField('fundingStatus', detail.funding_status),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'tech',
|
||||
title: '非遗等级与技术',
|
||||
fields: [
|
||||
{ label: '非遗传承人等级', type: 'text', value: formatEnumField('inheritorLevel', detail.inheritor_level) },
|
||||
{
|
||||
label: '非遗传承人等级',
|
||||
type: 'text',
|
||||
value: formatEnumField('inheritorLevel', detail.inheritor_level),
|
||||
},
|
||||
{
|
||||
label: '非遗传承人年龄水平及数量',
|
||||
type: 'list',
|
||||
@ -126,10 +151,22 @@ const detailSections = computed(() => {
|
||||
{
|
||||
label: '非遗等级',
|
||||
type: 'text',
|
||||
value: formatEnumField('heritageLevel', detail.heritage_level, detail.heritage_asset_level),
|
||||
value: formatEnumField(
|
||||
'heritageLevel',
|
||||
detail.heritage_level,
|
||||
detail.heritage_asset_level
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '非遗资产所用专利的申请号',
|
||||
type: 'text',
|
||||
value: detail.patent_application_no || '-',
|
||||
},
|
||||
{
|
||||
label: '非遗资产历史证明证据及数量',
|
||||
type: 'list',
|
||||
value: formatHistoricalEvidence(detail.historical_evidence),
|
||||
},
|
||||
{ label: '非遗资产所用专利的申请号', type: 'text', value: detail.patent_application_no || '-' },
|
||||
{ label: '非遗资产历史证明证据及数量', type: 'list', value: formatHistoricalEvidence(detail.historical_evidence) },
|
||||
{
|
||||
label: '非遗资产所用专利/纹样图片',
|
||||
type: 'images',
|
||||
@ -144,50 +181,86 @@ const detailSections = computed(() => {
|
||||
{
|
||||
label: '非遗资产应用成熟度',
|
||||
type: 'text',
|
||||
value: formatEnumField('applicationMaturity', detail.application_maturity, detail.implementation_stage),
|
||||
value: formatEnumField(
|
||||
'applicationMaturity',
|
||||
detail.application_maturity,
|
||||
detail.implementation_stage
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '非遗资产应用覆盖范围',
|
||||
type: 'text',
|
||||
value: formatEnumField('applicationCoverage', detail.application_coverage, detail.coverage_area),
|
||||
value: formatEnumField(
|
||||
'applicationCoverage',
|
||||
detail.application_coverage,
|
||||
detail.coverage_area
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '非遗资产跨界合作深度',
|
||||
type: 'text',
|
||||
value: formatEnumField('cooperationDepth', detail.cooperation_depth, detail.collaboration_type),
|
||||
value: formatEnumField(
|
||||
'cooperationDepth',
|
||||
detail.cooperation_depth,
|
||||
detail.collaboration_type
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '近12个月线下相关宣讲活动次数',
|
||||
type: 'text',
|
||||
value: formatNumberValue(detail.offline_activities ?? detail.offline_teaching_count),
|
||||
},
|
||||
{ label: '线上相关宣传账号信息', type: 'list', value: formatPlatformAccounts(detail.platform_accounts) },
|
||||
{
|
||||
label: '线上相关宣传账号信息',
|
||||
type: 'list',
|
||||
value: formatPlatformAccounts(detail.platform_accounts),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'products',
|
||||
title: '非遗资产衍生商品信息',
|
||||
fields: [
|
||||
{ label: '代表产品近12个月销售数量', type: 'text', value: formatNumberValue(detail.sales_volume) },
|
||||
{
|
||||
label: '代表产品近12个月销售数量',
|
||||
type: 'text',
|
||||
value: formatNumberValue(detail.sales_volume),
|
||||
},
|
||||
{ label: '商品链接浏览量', type: 'text', value: formatNumberValue(detail.link_views) },
|
||||
{ label: '发行量', type: 'text', value: formatEnumField('circulation', detail.circulation, detail.scarcity_level) },
|
||||
{
|
||||
label: '发行量',
|
||||
type: 'text',
|
||||
value: formatEnumField('circulation', detail.circulation, detail.scarcity_level),
|
||||
},
|
||||
{
|
||||
label: '最近一次市场活动时间',
|
||||
type: 'text',
|
||||
value: formatEnumField('marketActivity', detail.last_market_activity, detail.market_activity_time),
|
||||
value: formatEnumField(
|
||||
'marketActivity',
|
||||
detail.last_market_activity,
|
||||
detail.market_activity_time
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '月交易额水平',
|
||||
type: 'text',
|
||||
value: formatEnumField('monthlyTransaction', detail.monthly_transaction, detail.monthly_transaction_amount),
|
||||
value: formatEnumField(
|
||||
'monthlyTransaction',
|
||||
detail.monthly_transaction,
|
||||
detail.monthly_transaction_amount
|
||||
),
|
||||
},
|
||||
{
|
||||
label: '近30天价格区间',
|
||||
type: 'text',
|
||||
value: formatPriceRange(detail.price_fluctuation),
|
||||
},
|
||||
{ label: '近30天价格区间', type: 'text', value: formatPriceRange(detail.price_fluctuation) },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// 为每个 section 生成 NDataTable 需要的 columns 和 data
|
||||
return sections.map(section => {
|
||||
return sections.map((section) => {
|
||||
const columns = [
|
||||
{
|
||||
title: '字段名',
|
||||
@ -196,55 +269,65 @@ const detailSections = computed(() => {
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
},
|
||||
...section.fields.map(field => ({
|
||||
...section.fields.map((field) => ({
|
||||
title: field.label,
|
||||
key: field.label,
|
||||
width: 200,
|
||||
ellipsis: ['list', 'images'].includes(field.type) ? false : {
|
||||
tooltip: {
|
||||
style: { maxWidth: '600px', maxHeight: '400px', overflow: 'auto' }
|
||||
},
|
||||
},
|
||||
ellipsis: ['list', 'images'].includes(field.type)
|
||||
? false
|
||||
: {
|
||||
tooltip: {
|
||||
style: { maxWidth: '600px', maxHeight: '400px', overflow: 'auto' },
|
||||
},
|
||||
},
|
||||
render: (row) => {
|
||||
const fieldData = row[field.label]
|
||||
if (!fieldData) return '-'
|
||||
|
||||
|
||||
if (fieldData.type === 'list') {
|
||||
if (fieldData.value && fieldData.value.length) {
|
||||
return h('div', { style: 'display: flex; flex-direction: column; gap: 4px;' },
|
||||
fieldData.value.map(item => h('span', item))
|
||||
return h(
|
||||
'div',
|
||||
{ style: 'display: flex; flex-direction: column; gap: 4px;' },
|
||||
fieldData.value.map((item) => h('span', item))
|
||||
)
|
||||
}
|
||||
return '-'
|
||||
} else if (fieldData.type === 'images') {
|
||||
if (fieldData.value && fieldData.value.length) {
|
||||
const createImages = () => h(NImageGroup, {}, () =>
|
||||
fieldData.value.map(img =>
|
||||
h(NImage, {
|
||||
src: img,
|
||||
width: 72,
|
||||
height: 48,
|
||||
objectFit: 'cover',
|
||||
style: 'margin-right: 8px;'
|
||||
})
|
||||
const createImages = () =>
|
||||
h(NImageGroup, {}, () =>
|
||||
fieldData.value.map((img) =>
|
||||
h(NImage, {
|
||||
src: img,
|
||||
width: 72,
|
||||
height: 48,
|
||||
objectFit: 'cover',
|
||||
style: 'margin-right: 8px;',
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return h(NPopover, {
|
||||
trigger: 'hover',
|
||||
displayDirective: 'show',
|
||||
keepAliveOnHover: true,
|
||||
style: { maxWidth: '600px', maxHeight: '400px', overflow: 'auto' }
|
||||
}, {
|
||||
trigger: () => h('div', { style: 'display: flex; overflow: hidden;' }, createImages()),
|
||||
default: () => createImages()
|
||||
})
|
||||
return h(
|
||||
NPopover,
|
||||
{
|
||||
trigger: 'hover',
|
||||
displayDirective: 'show',
|
||||
keepAliveOnHover: true,
|
||||
style: { maxWidth: '600px', maxHeight: '400px', overflow: 'auto' },
|
||||
},
|
||||
{
|
||||
trigger: () =>
|
||||
h('div', { style: 'display: flex; overflow: hidden;' }, createImages()),
|
||||
default: () => createImages(),
|
||||
}
|
||||
)
|
||||
}
|
||||
return '-'
|
||||
} else {
|
||||
return fieldData.value || '-'
|
||||
}
|
||||
}
|
||||
},
|
||||
})),
|
||||
]
|
||||
|
||||
@ -268,64 +351,64 @@ const detailSections = computed(() => {
|
||||
|
||||
const calcFlow = computed(() => props.detailData?.calculation_result?.flow || [])
|
||||
|
||||
|
||||
|
||||
const renderedFlowHtml = computed(() => {
|
||||
return marked.parse(reportContent.value || mockReportMarkdown)
|
||||
})
|
||||
|
||||
|
||||
// 证书相关功能
|
||||
const handleUploadCertificate = () => {
|
||||
certificateModalMode.value = 'upload'
|
||||
certificateData.value = {
|
||||
detailData: props.detailData
|
||||
detailData: props.detailData,
|
||||
}
|
||||
certificateModalVisible.value = true
|
||||
}
|
||||
|
||||
const handleViewCertificate = () => {
|
||||
certificateModalMode.value = 'view'
|
||||
|
||||
|
||||
const formatFiles = (urlData) => {
|
||||
if (!urlData) return []
|
||||
// Handle string (single or comma-separated)
|
||||
const urls = typeof urlData === 'string' ? urlData.split(',') : (Array.isArray(urlData) ? urlData : [])
|
||||
|
||||
return urls.filter(u => u).map((url, index) => ({
|
||||
id: String(index),
|
||||
name: url.substring(url.lastIndexOf('/') + 1) || 'unknown',
|
||||
status: 'finished',
|
||||
url: url
|
||||
}))
|
||||
const urls =
|
||||
typeof urlData === 'string' ? urlData.split(',') : Array.isArray(urlData) ? urlData : []
|
||||
|
||||
return urls
|
||||
.filter((u) => u)
|
||||
.map((url, index) => ({
|
||||
id: String(index),
|
||||
name: url.substring(url.lastIndexOf('/') + 1) || 'unknown',
|
||||
status: 'finished',
|
||||
url: url,
|
||||
}))
|
||||
}
|
||||
|
||||
certificateData.value = {
|
||||
reportFiles: formatFiles(props.detailData?.report_url),
|
||||
certificateFiles: formatFiles(props.detailData?.certificate_url),
|
||||
detailData: props.detailData
|
||||
detailData: props.detailData,
|
||||
}
|
||||
certificateModalVisible.value = true
|
||||
}
|
||||
|
||||
const handleCertificateConfirm = async (data) => {
|
||||
console.log('证书数据:', data)
|
||||
|
||||
|
||||
try {
|
||||
const certificateUrl = data.certificateFiles?.map(f => f.url).filter(Boolean) || []
|
||||
const reportUrl = data.reportFiles?.map(f => f.url).filter(Boolean) || []
|
||||
|
||||
const certificateUrl = data.certificateFiles?.map((f) => f.url).filter(Boolean) || []
|
||||
const reportUrl = data.reportFiles?.map((f) => f.url).filter(Boolean) || []
|
||||
|
||||
// 现在改为只能上传 1 张
|
||||
const payload = {
|
||||
...props.detailData,
|
||||
certificate_url: certificateUrl?.[0],
|
||||
report_url: reportUrl?.[0],
|
||||
status: 'success'
|
||||
status: 'success',
|
||||
}
|
||||
console.log("🔥🔥🔥🔥🔥🔥🔥 ~ handleCertificateConfirm ~ payload:", payload);
|
||||
console.log('🔥🔥🔥🔥🔥🔥🔥 ~ handleCertificateConfirm ~ payload:', payload)
|
||||
|
||||
await api.updateValuation(payload)
|
||||
|
||||
|
||||
$message.success('上传并通知成功')
|
||||
certificateModalVisible.value = false
|
||||
emit('back') // 或者 emit('refresh') 取决于需求,这里假设返回列表或刷新
|
||||
@ -359,12 +442,7 @@ const handleCertificateConfirm = async (data) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NTabs
|
||||
v-model:value="activeDetailTab"
|
||||
type="line"
|
||||
size="large"
|
||||
class="audit-tabs"
|
||||
>
|
||||
<NTabs v-model:value="activeDetailTab" type="line" size="large" class="audit-tabs">
|
||||
<NTabPane name="audit" tab="审核信息">
|
||||
<NSpin :show="loading">
|
||||
<div v-for="section in detailSections" :key="section.key" class="detail-section">
|
||||
@ -395,19 +473,11 @@ const handleCertificateConfirm = async (data) => {
|
||||
|
||||
<!-- 证书按钮 -->
|
||||
<div class="certificate-actions">
|
||||
<NButton
|
||||
v-if="mode === 'approve'"
|
||||
type="primary"
|
||||
@click="handleUploadCertificate"
|
||||
>
|
||||
<NButton v-if="mode === 'approve'" type="primary" @click="handleUploadCertificate">
|
||||
<TheIcon icon="mdi:upload" :size="16" class="mr-4" />
|
||||
上传证书
|
||||
</NButton>
|
||||
<NButton
|
||||
v-else
|
||||
type="info"
|
||||
@click="handleViewCertificate"
|
||||
>
|
||||
<NButton v-else type="info" @click="handleViewCertificate">
|
||||
<TheIcon icon="mdi:eye" :size="16" class="mr-4" />
|
||||
查看证书
|
||||
</NButton>
|
||||
@ -441,7 +511,7 @@ const handleCertificateConfirm = async (data) => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin: -16px 0px 10px ;
|
||||
margin: -16px 0px 10px;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
@ -556,8 +626,8 @@ const handleCertificateConfirm = async (data) => {
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
.markdown-body :deep(h1),
|
||||
.markdown-body :deep(h2),
|
||||
.markdown-body :deep(h1),
|
||||
.markdown-body :deep(h2),
|
||||
.markdown-body :deep(h3),
|
||||
.markdown-body :deep(h4),
|
||||
.markdown-body :deep(h5),
|
||||
@ -567,10 +637,23 @@ const handleCertificateConfirm = async (data) => {
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
}
|
||||
.markdown-body :deep(h1) { font-size: 2em; border-bottom: 1px solid #eaecef; padding-bottom: .3em; }
|
||||
.markdown-body :deep(h2) { font-size: 1.5em; border-bottom: 1px solid #eaecef; padding-bottom: .3em; }
|
||||
.markdown-body :deep(h3) { font-size: 1.25em; }
|
||||
.markdown-body :deep(p) { margin-top: 0; margin-bottom: 16px; }
|
||||
.markdown-body :deep(h1) {
|
||||
font-size: 2em;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
.markdown-body :deep(h2) {
|
||||
font-size: 1.5em;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
.markdown-body :deep(h3) {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
.markdown-body :deep(p) {
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.markdown-body :deep(blockquote) {
|
||||
margin: 0 0 16px;
|
||||
padding: 0 1em;
|
||||
@ -592,7 +675,8 @@ const handleCertificateConfirm = async (data) => {
|
||||
.markdown-body :deep(table tr:nth-child(2n)) {
|
||||
background-color: #f6f8fa;
|
||||
}
|
||||
.markdown-body :deep(table th), .markdown-body :deep(table td) {
|
||||
.markdown-body :deep(table th),
|
||||
.markdown-body :deep(table td) {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #dfe2e5;
|
||||
}
|
||||
@ -603,7 +687,7 @@ const handleCertificateConfirm = async (data) => {
|
||||
padding: 0.2em 0.4em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
background-color: rgba(27,31,35,0.05);
|
||||
background-color: rgba(27, 31, 35, 0.05);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.markdown-body :deep(pre) {
|
||||
@ -767,6 +851,4 @@ const handleCertificateConfirm = async (data) => {
|
||||
color: #999;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@ -148,7 +148,7 @@ export const formatPlatformAccounts = (accounts = {}) => {
|
||||
if (!info) return `${label}:-`
|
||||
return `${label}:${info.account || '-'}(赞${formatNumberValue(info.likes)} / 评${formatNumberValue(
|
||||
info.comments
|
||||
)} / 转${formatNumberValue(info.shares)})`
|
||||
)} / 转${formatNumberValue(info.shares)}/ 七日浏览量${formatNumberValue(info.views)})`
|
||||
})
|
||||
return list.length ? list : ['暂无账号信息']
|
||||
}
|
||||
|
||||
@ -5,6 +5,11 @@ export default {
|
||||
getUserInfo: () => request.get('/base/userinfo'),
|
||||
getUserMenu: () => request.get('/base/usermenu'),
|
||||
getUserApi: () => request.get('/base/userapi'),
|
||||
deleteAccount: (data) => request.delete('/app-user/account', {
|
||||
data: {
|
||||
code: data.code // Body 中携带 code
|
||||
}
|
||||
}),
|
||||
// 手机号
|
||||
registerPhone: (data) => request.post('/app-user/register', data, { noNeedToken: true }),
|
||||
loginPhone: (data) => request.post('/app-user/login', data, { noNeedToken: true }),
|
||||
|
||||
BIN
web1/src/assets/icon/iconLogout.png
Normal file
BIN
web1/src/assets/icon/iconLogout.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
web1/src/assets/icon/评估完成.png
Normal file
BIN
web1/src/assets/icon/评估完成.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@ -52,6 +52,14 @@ export const basicRoutes = [
|
||||
title: '抬头管理',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Logout',
|
||||
path: 'logout',
|
||||
component: () => import('@/views/user-center/components/Logout.vue'),
|
||||
meta: {
|
||||
title: '账号注销',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -185,11 +185,7 @@
|
||||
</n-form-item>
|
||||
|
||||
<div class="btn-container">
|
||||
<button
|
||||
class="primary-btn"
|
||||
:disabled="!isFormValid"
|
||||
@click="handleUploadSubmit"
|
||||
>
|
||||
<button class="primary-btn" :disabled="!isFormValid" @click="handleUploadSubmit">
|
||||
确认上传
|
||||
</button>
|
||||
</div>
|
||||
@ -295,11 +291,7 @@ const message = useMessage()
|
||||
|
||||
// 计算表单是否有效
|
||||
const isFormValid = computed(() => {
|
||||
return (
|
||||
uploadedFiles.value.length > 0 &&
|
||||
!!formModel.invoiceHeader &&
|
||||
!!formModel.invoiceType
|
||||
)
|
||||
return uploadedFiles.value.length > 0 && !!formModel.invoiceHeader && !!formModel.invoiceType
|
||||
})
|
||||
|
||||
const handleUploadFinish = ({ file, event }) => {
|
||||
@ -384,10 +376,10 @@ defineExpose({
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
width: 6px;
|
||||
height: 24px;
|
||||
background: #a30113;
|
||||
border-radius: 2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
|
||||
@ -315,10 +315,10 @@ const rowKey = (row) => row.id ?? row.name ?? row.company_name ?? row.taxId ?? r
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
width: 6px;
|
||||
height: 24px;
|
||||
background: #a30113;
|
||||
border-radius: 2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
|
||||
368
web1/src/views/user-center/components/Logout.vue
Normal file
368
web1/src/views/user-center/components/Logout.vue
Normal file
@ -0,0 +1,368 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="header-left">
|
||||
<div class="title-bar"></div>
|
||||
<div class="title-text">账号注销</div>
|
||||
</div>
|
||||
<div v-if="deleteAble" class="logout-container">
|
||||
<!-- 手机号信息 -->
|
||||
<div class="phone-info">当前绑定的手机号码为:{{ maskedPhone }}</div>
|
||||
|
||||
<!-- 验证码输入区域 -->
|
||||
<div class="code-form">
|
||||
<n-form :model="form" :rules="rules" ref="formRef" label-width="100px">
|
||||
<n-form-item label="" prop="code" class="verify-code-item">
|
||||
<!-- 验证码输入框 + 按钮 容器 -->
|
||||
<div class="code-input-wrapper">
|
||||
<n-input
|
||||
v-model:value="form.code"
|
||||
placeholder="手机验证码"
|
||||
maxlength="6"
|
||||
@input="handleCodeInput"
|
||||
class="custom-code-input"
|
||||
:bordered="false"
|
||||
/>
|
||||
<n-button
|
||||
class="send-code-btn"
|
||||
text
|
||||
@click="handleSendCode"
|
||||
:disabled="countDown > 0"
|
||||
>
|
||||
{{ countDown > 0 ? `${countDown}s后重新获取` : '获取验证码' }}
|
||||
</n-button>
|
||||
</div>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
|
||||
<!-- 注销按钮 -->
|
||||
<n-button class="logout-btn" @click="handleLogout" :disabled="!isFormValid"> 确定 </n-button>
|
||||
</div>
|
||||
<div v-else class="logout-container" style="text-align: center">
|
||||
<img src="@/assets/icon/评估完成.png" mode="scaleToFill" class="warn-icon" />
|
||||
<p class="warn-title">无法注销</p>
|
||||
<p class="warn-content">当前有未完成的估值记录/剩余估值次数,无法注销账号</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onUnmounted } from 'vue'
|
||||
import { defineProps, defineEmits } from 'vue'
|
||||
import { useMessage, useDialog } from 'naive-ui' // 引入 Naive UI 消息/弹窗
|
||||
|
||||
// 初始化 Naive UI 消息和弹窗
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
|
||||
// 接收父组件传递的手机号
|
||||
const props = defineProps({
|
||||
userPhone: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
deleteAble: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
// 定义事件
|
||||
const emits = defineEmits(['send-code', 'confirm-logout'])
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref(null)
|
||||
|
||||
// 表单数据
|
||||
const form = ref({
|
||||
code: '',
|
||||
})
|
||||
// 倒计时
|
||||
const countDown = ref(0)
|
||||
let timer = null
|
||||
|
||||
// 手机号脱敏处理
|
||||
const maskedPhone = computed(() => {
|
||||
if (!props.userPhone) return ''
|
||||
return `${props.userPhone.slice(0, 3)}****${props.userPhone.slice(7, 11)}`
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const rules = ref({
|
||||
code: [
|
||||
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||||
{ len: 6, message: '请输入6位验证码', trigger: 'blur' },
|
||||
],
|
||||
})
|
||||
|
||||
// 表单是否有效
|
||||
const isFormValid = computed(() => {
|
||||
return props.userPhone && form.value.code.length === 6
|
||||
})
|
||||
|
||||
// 验证码输入限制
|
||||
const handleCodeInput = () => {
|
||||
if (form.value.code.length > 6) {
|
||||
form.value.code = form.value.code.slice(0, 6)
|
||||
}
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
const handleSendCode = async () => {
|
||||
if (!props.userPhone) {
|
||||
message.warning('手机号不存在,无法发送验证码')
|
||||
return
|
||||
}
|
||||
|
||||
// 调用父组件的发送验证码方法
|
||||
const res = await emits('send-code', props.userPhone)
|
||||
if (res) {
|
||||
// 启动倒计时
|
||||
countDown.value = 60
|
||||
timer = setInterval(() => {
|
||||
countDown.value--
|
||||
if (countDown.value <= 0) {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
}, 1000)
|
||||
message.success('验证码发送成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 提交注销
|
||||
const handleLogout = () => {
|
||||
// 表单验证
|
||||
formRef.value.validate((errors) => {
|
||||
if (!errors) {
|
||||
emits('confirm-logout', {
|
||||
code: form.value.code,
|
||||
})
|
||||
} else {
|
||||
message.warning('请填写正确的6位验证码')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 页面卸载时清除定时器
|
||||
watch(
|
||||
() => countDown.value,
|
||||
(val) => {
|
||||
if (val <= 0 && timer) {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 组件卸载时清除定时器
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 根容器样式 */
|
||||
.logout-container {
|
||||
width: 600px;
|
||||
margin: 50px auto;
|
||||
padding: 30px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 标题样式 */
|
||||
.logout-title {
|
||||
font-size: 12px;
|
||||
color: #303133;
|
||||
line-height: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 手机号信息样式 */
|
||||
.phone-info {
|
||||
font-size: 12px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 表单容器 */
|
||||
.code-form {
|
||||
margin-bottom: 40px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
/* 验证码表单项 */
|
||||
.verify-code-item {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/* 验证码输入框 + 按钮 容器(核心布局) */
|
||||
.code-input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
gap: 10px; /* 输入框和按钮间距 */
|
||||
}
|
||||
|
||||
/* 自定义验证码输入框样式 */
|
||||
.custom-code-input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e5e5e5;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.warn-icon {
|
||||
margin-top: 80px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.warn-title {
|
||||
margin-top: 20px;
|
||||
font-size: 20px;
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
}
|
||||
.warn-content {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
/* 穿透修改 Naive UI 输入框样式 */
|
||||
:deep(.custom-code-input .n-input-wrapper) {
|
||||
height: 100%;
|
||||
padding: 0 10px;
|
||||
}
|
||||
:deep(.custom-code-input .n-input__input-el) {
|
||||
height: 100%;
|
||||
line-height: 40px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 输入框 hover 状态 */
|
||||
.custom-code-input:hover {
|
||||
border-color: #a3011380; /* 半透明红 */
|
||||
}
|
||||
|
||||
/* 输入框 聚焦状态 */
|
||||
:deep(.custom-code-input .n-input-wrapper:focus-within) {
|
||||
border-color: #a30113;
|
||||
box-shadow: 0 0 0 2px rgba(163, 1, 19, 0.1);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 输入框 错误状态 */
|
||||
:deep(.n-form-item--error .custom-code-input) {
|
||||
border-color: #d03050;
|
||||
}
|
||||
:deep(.n-form-item--error .custom-code-input .n-input-wrapper:focus-within) {
|
||||
border-color: #d03050;
|
||||
box-shadow: 0 0 0 2px rgba(208, 48, 80, 0.1);
|
||||
}
|
||||
|
||||
/* 验证码按钮样式 */
|
||||
.send-code-btn {
|
||||
height: 100%;
|
||||
min-width: 120px;
|
||||
padding: 0 15px;
|
||||
border-radius: 4px;
|
||||
color: #a30113;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
background: #a3011332;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 按钮 hover(非禁用) */
|
||||
.send-code-btn:not(:disabled):hover {
|
||||
background: #a3011332;
|
||||
color: #a30113;
|
||||
}
|
||||
|
||||
/* 按钮 点击态 */
|
||||
.send-code-btn:not(:disabled):active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* 按钮 禁用态 */
|
||||
.send-code-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* 注销按钮样式 */
|
||||
.logout-btn {
|
||||
margin: auto;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
width: 180px;
|
||||
height: 40px;
|
||||
background: #a30113;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 注销按钮 hover(非禁用) */
|
||||
.logout-btn:not(:disabled):hover {
|
||||
background: #a30113;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 注销按钮 禁用态 */
|
||||
.logout-btn:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.title-bar {
|
||||
width: 6px;
|
||||
height: 24px;
|
||||
background: #a30113;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 表单错误提示位置调整 */
|
||||
:deep(.n-form-item-feedback-wrapper) {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
padding-top: 2px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
:deep(.custom-code-input) {
|
||||
/* Chrome/Safari/Edge */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
/* Firefox */
|
||||
input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
}
|
||||
:deep(.n-button__content) {
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@ -6,6 +6,8 @@
|
||||
</div>
|
||||
<div class="user-phone">{{ userPhone || '18988880000' }}</div>
|
||||
<div class="valuation-count">剩余评估次数:{{ valuationCount }}</div>
|
||||
|
||||
<div class="logout-btn" @click="logout">退出登录</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-list">
|
||||
@ -29,24 +31,48 @@
|
||||
import iconHistory from '@/assets/icon/估值记录.png'
|
||||
import iconTransfer from '@/assets/icon/对公转账.png'
|
||||
import iconInvoice from '@/assets/icon/抬头管理.png'
|
||||
import iconLogout from '@/assets/icon/iconLogout.png'
|
||||
import { useDialog } from 'naive-ui'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const dialog = useDialog()
|
||||
defineProps({
|
||||
userPhone: String,
|
||||
valuationCount: Number,
|
||||
currentMenu: String,
|
||||
menuList: Array
|
||||
menuList: Array,
|
||||
})
|
||||
|
||||
defineEmits(['menu-click'])
|
||||
|
||||
function getMenuIcon(id) {
|
||||
const iconMap = {
|
||||
'history': iconHistory,
|
||||
'transfer': iconTransfer,
|
||||
'invoice': iconInvoice
|
||||
history: iconHistory,
|
||||
transfer: iconTransfer,
|
||||
invoice: iconInvoice,
|
||||
logout: iconLogout,
|
||||
}
|
||||
return iconMap[id]
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
await new Promise((resolve, reject) => {
|
||||
dialog.warning({
|
||||
title: '提示',
|
||||
content: '确认退出登录',
|
||||
positiveText: '确认',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => resolve(),
|
||||
onNegativeClick: () => reject('cancel'),
|
||||
onClose: () => reject('cancel'),
|
||||
})
|
||||
})
|
||||
// 清除本地缓存
|
||||
localStorage.removeItem('ACCESS_TOKEN')
|
||||
// 跳转到登录页
|
||||
router.push('/login')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -117,12 +143,12 @@ function getMenuIcon(id) {
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
background: #F5F7FA;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.menu-item.active {
|
||||
background: #FFF0F0;
|
||||
color: #A30113;
|
||||
background: #fff0f0;
|
||||
color: #a30113;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@ -153,6 +179,19 @@ function getMenuIcon(id) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
width: 168px;
|
||||
height: 32px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sidebar-card {
|
||||
width: 100%;
|
||||
|
||||
@ -217,10 +217,10 @@ onMounted(fetchHistory)
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
width: 6px;
|
||||
height: 24px;
|
||||
background: #a30113;
|
||||
border-radius: 2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
|
||||
@ -16,23 +16,19 @@
|
||||
|
||||
<!-- 右侧内容区 -->
|
||||
<div class="content-area">
|
||||
<!-- 返回按钮 (暂时注释) -->
|
||||
<!-- <div class="back-button" @click="handleBackToHome">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
<span>返回首页</span>
|
||||
</div> -->
|
||||
|
||||
<!-- 子路由视图 -->
|
||||
<router-view
|
||||
:asset-list="assetList"
|
||||
:invoice-list="invoiceList"
|
||||
:user-phone="userPhone"
|
||||
:deleteAble="deleteAble"
|
||||
@return-home="handleBackToHome"
|
||||
@add-invoice="addInvoice"
|
||||
@update-invoice="updateInvoice"
|
||||
@delete-invoice="deleteInvoice"
|
||||
@upload-submit="uploadSubmit"
|
||||
@send-code="sendVerificationCode"
|
||||
@confirm-logout="confirmAccountLogout"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -40,12 +36,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, h, watch, computed } from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useMessage, useDialog } from 'naive-ui' // 引入 Naive UI 消息/弹窗
|
||||
import api from '@/api'
|
||||
import AppHeader from '@/components/AppHeader.vue'
|
||||
import UserSidebar from './components/UserSidebar.vue'
|
||||
|
||||
// 初始化 Naive UI 消息和弹窗实例
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
@ -55,12 +56,14 @@ const currentMenu = computed(() => {
|
||||
if (path.includes('/history')) return 'history'
|
||||
if (path.includes('/transfer')) return 'transfer'
|
||||
if (path.includes('/invoice')) return 'invoice'
|
||||
if (path.includes('/logout')) return 'logout' // 新增:注销菜单匹配
|
||||
return 'history'
|
||||
})
|
||||
|
||||
// 用户信息
|
||||
const userPhone = ref('')
|
||||
const valuationCount = ref(0)
|
||||
const deleteAble = ref(true)
|
||||
|
||||
// 资产列表
|
||||
const assetList = ref([])
|
||||
@ -68,7 +71,7 @@ const assetList = ref([])
|
||||
// 开票列表
|
||||
const invoiceList = ref([])
|
||||
|
||||
// 菜单列表
|
||||
// 菜单列表(新增注销菜单)
|
||||
const menuList = ref([
|
||||
{
|
||||
id: 'history',
|
||||
@ -82,6 +85,10 @@ const menuList = ref([
|
||||
id: 'invoice',
|
||||
label: '抬头管理',
|
||||
},
|
||||
{
|
||||
id: 'logout', // 新增:注销账号菜单
|
||||
label: '账号注销',
|
||||
},
|
||||
])
|
||||
|
||||
// 返回首页
|
||||
@ -91,7 +98,6 @@ function handleBackToHome() {
|
||||
|
||||
// 菜单点击
|
||||
function handleMenuClick(menu) {
|
||||
// 使用路由导航
|
||||
router.push(`/user-center/${menu.id}`)
|
||||
}
|
||||
|
||||
@ -114,10 +120,12 @@ async function loadData() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载估值记录失败:', error)
|
||||
$message.error('加载估值记录失败,请稍后重试')
|
||||
// 替换:ElMessage → message
|
||||
message.error('加载估值记录失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
//加载发票抬头列表
|
||||
|
||||
// 加载发票抬头列表
|
||||
async function loadInvoiceList() {
|
||||
try {
|
||||
const res = await api.getInvoiceHeaders()
|
||||
@ -127,37 +135,43 @@ async function loadInvoiceList() {
|
||||
}
|
||||
}
|
||||
|
||||
//添加发票抬头
|
||||
// 添加发票抬头
|
||||
async function addInvoice(data) {
|
||||
try {
|
||||
await api.addInvoiceHeaders(data)
|
||||
$message.success('添加成功')
|
||||
// 替换:ElMessage → message
|
||||
message.success('添加成功')
|
||||
loadInvoiceList()
|
||||
} catch (error) {
|
||||
console.error('新增发票抬头失败:', error)
|
||||
}
|
||||
}
|
||||
//更新发票抬头
|
||||
|
||||
// 更新发票抬头
|
||||
async function updateInvoice(data) {
|
||||
try {
|
||||
await api.updateInvoiceHeaders(data)
|
||||
$message.success('编辑成功')
|
||||
// 替换:ElMessage → message
|
||||
message.success('编辑成功')
|
||||
loadInvoiceList()
|
||||
} catch (error) {
|
||||
console.error('更新发票抬头失败:', error)
|
||||
}
|
||||
}
|
||||
//删除发票抬头
|
||||
|
||||
// 删除发票抬头
|
||||
async function deleteInvoice(data) {
|
||||
try {
|
||||
await api.deleteInvoiceHeaders(data.id)
|
||||
$message.success('删除成功')
|
||||
// 替换:ElMessage → message
|
||||
message.success('删除成功')
|
||||
loadInvoiceList()
|
||||
} catch (error) {
|
||||
console.error('删除发票抬头失败:', error)
|
||||
}
|
||||
}
|
||||
//上传对公转账凭证
|
||||
|
||||
// 上传对公转账凭证
|
||||
async function uploadSubmit(data) {
|
||||
try {
|
||||
console.log('上传对公转账凭证===', data)
|
||||
@ -167,6 +181,53 @@ async function uploadSubmit(data) {
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:发送注销验证码
|
||||
async function sendVerificationCode(phone) {
|
||||
try {
|
||||
await api.sendVerifyCode({ phone })
|
||||
message.success('验证码已发送,请注意查收')
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('发送验证码失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:确认注销账号
|
||||
async function confirmAccountLogout(formData) {
|
||||
// 替换:ElMessageBox.confirm → dialog.warning
|
||||
await new Promise((resolve, reject) => {
|
||||
dialog.warning({
|
||||
title: '提示',
|
||||
content: '提交后账号将注销,不可撤回,确认注销账户?',
|
||||
positiveText: '确认',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => resolve(),
|
||||
onNegativeClick: () => reject('cancel'),
|
||||
onClose: () => reject('cancel'),
|
||||
})
|
||||
})
|
||||
|
||||
// 调用注销接口(传入手机号和验证码)
|
||||
api
|
||||
.deleteAccount({
|
||||
code: formData.code,
|
||||
})
|
||||
.then((res) => {
|
||||
console.log(res, '111111111111111')
|
||||
// 替换:ElMessage → message
|
||||
message.success('账号注销成功')
|
||||
// 清除本地缓存
|
||||
localStorage.removeItem('phone')
|
||||
// 跳转到登录页
|
||||
router.push('/login')
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, '111111111111111')
|
||||
deleteAble.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
loadInvoiceList()
|
||||
@ -200,26 +261,7 @@ onMounted(() => {
|
||||
min-height: calc(100vh - 100px); /* Adjust based on header + margin */
|
||||
position: relative;
|
||||
overflow: hidden; /* Ensure rounded corners */
|
||||
}
|
||||
|
||||
.back-button {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 14px;
|
||||
background: transparent;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
color: #a30113;
|
||||
padding: 20px; /* 新增:添加内边距 */
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
@ -232,9 +274,5 @@ onMounted(() => {
|
||||
.main-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user