diff --git a/web/.env.development b/web/.env.development index 309efdb..8bae5dc 100644 --- a/web/.env.development +++ b/web/.env.development @@ -6,3 +6,4 @@ VITE_USE_PROXY = true # base api VITE_BASE_API = 'http://139.224.70.152:9990/api/v1' +# VITE_BASE_API = 'http://127.0.0.1:9999/api/v1' diff --git a/web/src/api/index.js b/web/src/api/index.js index c034d08..8a2be22 100644 --- a/web/src/api/index.js +++ b/web/src/api/index.js @@ -1,281 +1,5 @@ import { request } from '@/utils' -const baseValuationDetail = { - valuation_result: 1180000, - created_at: '2024-11-10T09:30:00Z', - reviewed_at: null, - status: 'pending', - admin_notes: null, - asset_name: '蜀绣传承精品', - institution: '天府非遗文化发展有限公司', - industry: '文化创意', - annual_revenue: 980000, - rd_investment: 165000, - three_year_income: [890000, 975000, 1180000], - funding_status: '国家资助', - inheritor_level: '市级传承人', - inheritor_age_count: [4, 6, 2], - inheritor_certificates: [ - 'https://dummyimage.com/120x80/edf2ff/409eff&text=证书A1', - 'https://dummyimage.com/120x80/fef6f0/f0a020&text=证书A2', - ], - heritage_level: '国家级非遗', - heritage_asset_level: '一级保护', - patent_application_no: '1111111,2222222', - historical_evidence: { - artifacts: 1, - ancient_literature: 2, - inheritor_testimony: 0, - modern_research: 3, - }, - patent_certificates: ['https://dummyimage.com/120x80/e8f5e9/34a853&text=专利1'], - pattern_images: ['https://dummyimage.com/120x80/f3e8ff/9c27b0&text=纹样1'], - application_maturity: '推广阶段', - application_coverage: '全国覆盖', - cooperation_depth: '品牌联名', - offline_activities: 4, - platform_accounts: { - bilibili: { account: 'B站@蜀绣', likes: 1260, comments: 320, shares: 188 }, - }, - sales_volume: 5200, - link_views: 86500, - circulation: '500-1000份', - last_market_activity: '近3个月', - monthly_transaction: '50-100万元', - price_fluctuation: [1200, 3200], - model_value_b: 1250000, - market_value_c: 1180000, - final_value_ab: 1220000, - dynamic_pledge_rate: 0.62, - calculation_result: { - flow: [ - { - title: '基础估值', - description: '基于近三年收益与研发投入的模型估值', - value: '¥1,250,000', - }, - { - title: '市场对标', - description: '结合同类资产市场成交价修正', - value: '¥1,180,000', - }, - { - title: '综合校准', - description: '叠加ESG、政策匹配度得出最终估值', - value: '¥1,220,000', - }, - ], - }, -} - -const valuationRecords = [ - { - id: 2001, - phone: '13800138001', - wechat: 'zhangsan_wx', - }, - { - id: 2002, - phone: '13800138002', - wechat: 'lisi2024', - valuation_result: 880000, - created_at: '2024-11-09T14:20:00Z', - reviewed_at: '2024-11-09T16:45:00Z', - status: 'approved', - admin_notes: '评估结果合理,已通过审核', - asset_name: '景泰蓝掐丝珐琅', - institution: '京华非遗研究院', - application_maturity: '成熟期', - application_coverage: '华北地区', - cooperation_depth: '科技载体', - platform_accounts: { - douyin: { account: '抖音@景泰蓝工坊', likes: 2350, comments: 610, shares: 302 }, - }, - price_fluctuation: [980, 2680], - calculation_result: { - flow: [ - { - title: '基础估值', - description: '模型估算品牌溢价后得出结果', - value: '¥900,000', - }, - { - title: '市场对标', - description: '对比近六个月文博拍卖价格', - value: '¥860,000', - }, - { - title: '综合校准', - description: '结合政策扶持与线上声量校准', - value: '¥880,000', - }, - ], - }, - }, - { - id: 2003, - phone: '13800138003', - wechat: 'wangwu_user', - valuation_result: 2100000, - created_at: '2024-11-08T16:45:00Z', - reviewed_at: '2024-11-08T18:30:00Z', - status: 'approved', - admin_notes: '评估价格偏高,但审核通过', - asset_name: '苗绣银饰', - institution: '黔锦民族文化有限公司', - industry: '民族工艺', - funding_status: '地方配套资金', - inheritor_level: '国家级代表性传承人', - inheritor_age_count: [2, 3, 1], - application_coverage: '西南片区', - platform_accounts: { - kuaishou: { account: '快手@苗绣手作', likes: 1800, comments: 420, shares: 210 }, - }, - price_fluctuation: [2600, 5200], - }, - { - id: 2004, - phone: '13800138004', - wechat: 'zhaoliu_vip', - valuation_result: 560000, - created_at: '2024-11-07T11:15:00Z', - status: 'pending', - asset_name: '景德镇青花', - institution: '景尚文化传播有限公司', - industry: '陶瓷制造', - funding_status: '社会资本', - platform_accounts: { - bilibili: { account: 'B站@青花研习社', likes: 860, comments: 146, shares: 98 }, - }, - price_fluctuation: [560, 1200], - }, - { - id: 2005, - phone: '13800138005', - wechat: 'sunqi888', - valuation_result: 1680000, - created_at: '2024-11-06T08:30:00Z', - reviewed_at: '2024-11-06T10:15:00Z', - status: 'approved', - admin_notes: '评估数据完整,审核通过', - asset_name: '藏医药香丸', - institution: '高原本草研究中心', - industry: '中医药', - application_coverage: '西藏及周边', - cooperation_depth: '国家外交礼品', - platform_accounts: { - douyin: { account: '抖音@藏医手作', likes: 3120, comments: 815, shares: 356 }, - }, - price_fluctuation: [3200, 7600], - }, - { - id: 2006, - phone: '13800138006', - wechat: 'zhouba2024', - valuation_result: 950000, - created_at: '2024-11-05T13:20:00Z', - status: 'pending', - asset_name: '苏绣屏风', - institution: '苏澜绣坊', - funding_status: '企业自筹', - platform_accounts: { - bilibili: { account: 'B站@苏绣博物馆', likes: 980, comments: 240, shares: 130 }, - }, - price_fluctuation: [1500, 3600], - }, - { - id: 2007, - phone: '13800138007', - wechat: 'wujiu_user', - valuation_result: 3200000, - created_at: '2024-11-04T15:45:00Z', - reviewed_at: '2024-11-04T17:20:00Z', - status: 'approved', - admin_notes: '高价值资产,评估结果准确', - asset_name: '宋锦织造', - institution: '苏州织造研究所', - funding_status: '国家重点补贴', - inheritor_age_count: [6, 8, 4], - application_maturity: '成熟期', - cooperation_depth: '科技载体', - platform_accounts: { - douyin: { account: '抖音@宋锦织造', likes: 4800, comments: 1020, shares: 520 }, - }, - }, - { - id: 2008, - phone: '13800138008', - wechat: 'zhengshi_vip', - valuation_result: 750000, - created_at: '2024-11-03T10:10:00Z', - reviewed_at: '2024-11-03T12:00:00Z', - status: 'approved', - admin_notes: '评估流程规范,结果可信', - asset_name: '黄梅挑花', - institution: '徽楚非遗中心', - cooperation_depth: '品牌联名', - price_fluctuation: [980, 1800], - }, - { - id: 2009, - phone: '13800138009', - wechat: 'chenjun2024', - valuation_result: 1890000, - created_at: '2024-11-02T14:30:00Z', - status: 'pending', - asset_name: '黎锦织造', - institution: '海南黎锦工坊', - funding_status: '国家资助', - application_coverage: '华南地区', - }, - { - id: 2010, - phone: '13800138010', - wechat: 'liuxia_user', - valuation_result: 430000, - created_at: '2024-11-01T11:45:00Z', - reviewed_at: '2024-11-01T13:30:00Z', - status: 'approved', - admin_notes: '低价值资产,评估合理', - asset_name: '大漆工艺', - institution: '榫卯器物社', - funding_status: '地方专项', - cooperation_depth: '品牌联名', - platform_accounts: { - bilibili: { account: 'B站@大漆工坊', likes: 420, comments: 75, shares: 33 }, - }, - }, - { - id: 2011, - phone: '13800138011', - wechat: 'zhaolei2024', - valuation_result: 2100000, - created_at: '2024-10-31T09:20:00Z', - reviewed_at: '2024-10-31T11:00:00Z', - status: 'approved', - admin_notes: '评估报告详细,数据支撑充分', - asset_name: '龙泉青瓷', - institution: '浙瓷非遗研究院', - cooperation_depth: '科技载体', - }, - { - id: 2012, - phone: '13800138012', - wechat: 'sunmei_vip', - valuation_result: 680000, - created_at: '2024-10-30T16:15:00Z', - status: 'pending', - asset_name: '侗锦织造', - institution: '黔东南侗锦合作社', - funding_status: '社会资本', - }, -] - -const mockValuationDetails = valuationRecords.map((record) => ({ - ...baseValuationDetail, - ...record, -})) - export default { login: (data) => request.post('/base/access_token', data, { noNeedToken: true }), getUserInfo: () => request.get('/base/userinfo'), @@ -326,87 +50,18 @@ export default { // invoice (交易管理-对公转账记录) getInvoiceList: (params = {}) => request.get('/transactions/receipts', { params }), getInvoiceById: (params = {}) => request.get(`/transactions/receipts/${params.id}`, { params }), - sendInvoice: (data = {}) => request.post('/transactions/send-email', data), + // 后端接口要求请求体包裹在 data 字段下 + sendInvoice: (data = {}) => request.post('/transactions/send-email', { data }), // valuation (估值评估) - getValuationList: (params = {}) => { - // 模拟分页和搜索 - let filteredValuations = [...mockValuationDetails] - - // 手机号搜索 - if (params.phone) { - filteredValuations = filteredValuations.filter(valuation => - valuation.phone.includes(params.phone) - ) - } - - // 微信号搜索 - if (params.wechat) { - filteredValuations = filteredValuations.filter(valuation => - valuation.wechat && valuation.wechat.includes(params.wechat) - ) - } - - // 状态筛选 - if (params.status) { - filteredValuations = filteredValuations.filter(valuation => - valuation.status === params.status - ) - } - - // 提交时间筛选 - if (params.created_at && Array.isArray(params.created_at) && params.created_at.length === 2) { - const [startDate, endDate] = params.created_at - filteredValuations = filteredValuations.filter(valuation => { - const valuationDate = new Date(valuation.created_at) - return valuationDate >= new Date(startDate) && valuationDate <= new Date(endDate) - }) - } - - // 分页处理 - const page = params.page || 1 - const pageSize = params.page_size || 10 - const startIndex = (page - 1) * pageSize - const endIndex = startIndex + pageSize - const paginatedValuations = filteredValuations.slice(startIndex, endIndex).map((item) => ({ - id: item.id, - phone: item.phone, - wechat: item.wechat, - valuation_result: item.valuation_result, - created_at: item.created_at, - reviewed_at: item.reviewed_at, - status: item.status, - admin_notes: item.admin_notes, - })) - - // 返回 Promise 模拟异步请求 - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - data: paginatedValuations, - total: filteredValuations.length, - page: page, - page_size: pageSize - }) - }, 300) // 模拟网络延迟 - }) - }, - getValuationById: (params = {}) => { - const id = Number(params.valuation_id || params.id) - return new Promise((resolve, reject) => { - setTimeout(() => { - const detail = mockValuationDetails.find((item) => item.id === id) - if (detail) { - resolve({ data: detail }) - } else { - reject({ code: 404, message: '未找到估值详情' }) - } - }, 200) - }) - }, - createValuation: (data = {}) => request.post('/valuation', data), - updateValuation: (data = {}) => request.put(`/valuation/${data.id}`, data), - deleteValuation: (params = {}) => request.delete(`/valuation/${params.valuation_id}`), - approveValuation: (data = {}) => request.post(`/valuation/${data.valuation_id}/approve`, data), - rejectValuation: (data = {}) => request.post(`/valuation/${data.valuation_id}/reject`, data), - updateValuationNotes: (data = {}) => request.put(`/valuation/${data.valuation_id}/admin-notes`, data), + getValuationList: (params = {}) => request.get('/valuations/', { params }), + getValuationById: (params = {}) => request.get(`/valuations/${params.valuation_id || params.id}`), + createValuation: (data = {}) => request.post('/valuations', data), + updateValuation: (data = {}) => request.put(`/valuations/${data.id}`, data), + deleteValuation: (params = {}) => request.delete(`/valuations/${params.valuation_id || params.id}`), + approveValuation: (data = {}) => + request.post(`/valuations/${data.valuation_id || data.id}/approve`, { admin_notes: data.admin_notes }), + rejectValuation: (data = {}) => + request.post(`/valuations/${data.valuation_id || data.id}/reject`, { admin_notes: data.admin_notes }), + updateValuationNotes: (data = {}) => + request.put(`/valuations/${data.valuation_id || data.id}/admin-notes`, { admin_notes: data.admin_notes }), } diff --git a/web/src/views/transaction/invoice/index.vue b/web/src/views/transaction/invoice/index.vue index b878c74..6294e38 100644 --- a/web/src/views/transaction/invoice/index.vue +++ b/web/src/views/transaction/invoice/index.vue @@ -239,14 +239,11 @@ async function fetchDetail(row) { // 确认发送邮件 async function handleInvoiceConfirm(formData) { try { - // 根据报错 'loc': ('body', 'data'),后端确实需要 data 字段包裹 const payload = { - data: { - email: formData.email, - subject: formData.email, // 用户要求 subject 传 email - body: formData.content, // 映射 content -> body - file_url: formData.attachments?.[0] || '', // 映射 attachments -> file_url - } + email: formData.email, + subject: formData.email, // 用户要求 subject 传 email + body: formData.content, // 映射 content -> body + file_url: formData.attachments?.[0] || '', // 映射 attachments -> file_url } await api.sendInvoice(payload) diff --git a/web/src/views/valuation/audit/constants.js b/web/src/views/valuation/audit/constants.js index aa23f6a..f55aa27 100644 --- a/web/src/views/valuation/audit/constants.js +++ b/web/src/views/valuation/audit/constants.js @@ -1,12 +1,16 @@ export const STATUS_OPTIONS = [ { label: '全部', value: '' }, { label: '待审核', value: 'pending' }, - { label: '已完成', value: 'approved' }, + { label: '已通过', value: 'approved' }, + { label: '已拒绝', value: 'rejected' }, + { label: '已完成', value: 'success' }, ] export const STATUS_MAP = { pending: { type: 'warning', text: '待审核' }, - approved: { type: 'success', text: '已完成' }, + approved: { type: 'success', text: '已通过' }, + rejected: { type: 'error', text: '已拒绝' }, + success: { type: 'success', text: '已完成' }, } export const getStatusConfig = (status) => STATUS_MAP[status] || { type: 'default', text: '未知' } diff --git a/web/src/views/valuation/audit/index.vue b/web/src/views/valuation/audit/index.vue index e24c71c..d798736 100644 --- a/web/src/views/valuation/audit/index.vue +++ b/web/src/views/valuation/audit/index.vue @@ -36,6 +36,13 @@ const renderStatus = (status) => { return h(NTag, { type: config.type }, { default: () => config.text }) } +const getValuationResult = (row) => { + if (row?.final_value_ab !== undefined && row.final_value_ab !== null) return row.final_value_ab + if (row?.market_value_c !== undefined && row.market_value_c !== null) return row.market_value_c + if (row?.model_value_b !== undefined && row.model_value_b !== null) return row.model_value_b + return row?.valuation_result +} + // 列定义 const columns = [ { title: '编号', key: 'id', width: 80, align: 'center' }, @@ -45,6 +52,9 @@ const columns = [ width: 120, align: 'center', ellipsis: { tooltip: true }, + render(row) { + return row.phone || row.user_phone || row.user?.phone || '-' + }, }, { title: '微信号', @@ -52,6 +62,9 @@ const columns = [ width: 120, align: 'center', ellipsis: { tooltip: true }, + render(row) { + return row.wechat || row.user_wechat || row.user?.wechat || '-' + }, }, { title: '评估结果', @@ -59,7 +72,8 @@ const columns = [ width: 120, align: 'center', render(row) { - return formatAmount(row.valuation_result) + const val = getValuationResult(row) + return val || val === 0 ? formatAmount(val) : '-' }, }, { @@ -110,7 +124,7 @@ const columns = [ } ) } - if (row.status === 'approved') { + if (['approved', 'rejected', 'success'].includes(row.status)) { return h( NButton, { @@ -328,12 +342,6 @@ watch( -