估值模型功能提交
Showing
5 changed files
with
1200 additions
and
0 deletions
| ... | @@ -48,3 +48,39 @@ export const sendEntryMsg = (params) => request({ | ... | @@ -48,3 +48,39 @@ export const sendEntryMsg = (params) => request({ |
| 48 | method: 'post', | 48 | method: 'post', |
| 49 | params | 49 | params |
| 50 | }); | 50 | }); |
| 51 | |||
| 52 | /** ----------------------------------------估值模型接口--------------------------------- */ | ||
| 53 | |||
| 54 | /** 获取数据产品估值模型列表 */ | ||
| 55 | export const getValuationModelList = (params) => request({ | ||
| 56 | url: `${import.meta.env.VITE_API_NEW_PORTAL}/valuation-model/page-list`, | ||
| 57 | method: 'post', | ||
| 58 | data: params | ||
| 59 | }) | ||
| 60 | |||
| 61 | /** 保存估值模型 */ | ||
| 62 | export const saveValuationMode = (params) => request({ | ||
| 63 | url: `${import.meta.env.VITE_API_NEW_PORTAL}/valuation-model/save`, | ||
| 64 | method: 'post', | ||
| 65 | data: params | ||
| 66 | }) | ||
| 67 | |||
| 68 | /** 更新估值模型 */ | ||
| 69 | export const updateValuationMode = (params) => request({ | ||
| 70 | url: `${import.meta.env.VITE_API_NEW_PORTAL}/valuation-model/update`, | ||
| 71 | method: 'put', | ||
| 72 | data: params | ||
| 73 | }) | ||
| 74 | |||
| 75 | /** 删除估值模型 */ | ||
| 76 | export const deleteValuationMode = (params) => request({ | ||
| 77 | url: `${import.meta.env.VITE_API_NEW_PORTAL}/valuation-model/delete`, | ||
| 78 | method: 'delete', | ||
| 79 | data: params | ||
| 80 | }) | ||
| 81 | |||
| 82 | /** 获取估值模型详情 */ | ||
| 83 | export const getValuationModelDetail = (params) => request({ | ||
| 84 | url: `${import.meta.env.VITE_API_NEW_PORTAL}/valuation-model/detail?guid=${params.guid}`, | ||
| 85 | method: 'get' | ||
| 86 | }) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -68,6 +68,45 @@ const routes: RouteRecordRaw[] = [ | ... | @@ -68,6 +68,45 @@ const routes: RouteRecordRaw[] = [ |
| 68 | }, | 68 | }, |
| 69 | ], | 69 | ], |
| 70 | }, | 70 | }, |
| 71 | { | ||
| 72 | path: '/data-entry/valuation-model', | ||
| 73 | component: Layout, | ||
| 74 | meta: { | ||
| 75 | title: '估值模型', | ||
| 76 | icon: 'sidebar-videos', | ||
| 77 | }, | ||
| 78 | children: [ | ||
| 79 | { | ||
| 80 | path: '', | ||
| 81 | name: 'valuationModel', | ||
| 82 | component: () => import('@/views/data_transaction/valuationModel.vue'), | ||
| 83 | meta: { | ||
| 84 | title: '估值模型', | ||
| 85 | sidebar: false, | ||
| 86 | breadcrumb: false, | ||
| 87 | cache: true | ||
| 88 | }, | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | path: 'valuation-model-create', | ||
| 92 | name: 'valuationModelCreate', | ||
| 93 | component: () => import('@/views/data_transaction/valuationModelCreate.vue'), | ||
| 94 | meta: { | ||
| 95 | title: '新建估值模型', | ||
| 96 | sidebar: false, | ||
| 97 | breadcrumb: false, | ||
| 98 | cache: true, | ||
| 99 | editPage: true, | ||
| 100 | reuse: true | ||
| 101 | }, | ||
| 102 | beforeEnter: (to, from) => { | ||
| 103 | if (to.query.guid) { | ||
| 104 | to.meta.title = `编辑-${to.query.name}`; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | }, | ||
| 108 | ], | ||
| 109 | }, | ||
| 71 | ] | 110 | ] |
| 72 | 111 | ||
| 73 | export default routes | 112 | export default routes | ... | ... |
src/store/modules/dataEntry.ts
0 → 100644
| 1 | const useEntryStore = defineStore( | ||
| 2 | // api标签分类guid | ||
| 3 | 'isRefresh', | ||
| 4 | |||
| 5 | () => { | ||
| 6 | |||
| 7 | const isRefresh = ref(false); | ||
| 8 | function setIsRefresh(update: boolean) { | ||
| 9 | isRefresh.value = update; | ||
| 10 | } | ||
| 11 | |||
| 12 | return { | ||
| 13 | isRefresh, | ||
| 14 | setIsRefresh, | ||
| 15 | } | ||
| 16 | }, | ||
| 17 | ) | ||
| 18 | |||
| 19 | export default useEntryStore | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <script lang="ts" setup name="valuationModel"> | ||
| 2 | import TableTools from "@/components/Tools/table_tools.vue"; | ||
| 3 | import { commonPageConfig } from '@/components/PageNav/index'; | ||
| 4 | import { | ||
| 5 | getValuationModelList, | ||
| 6 | deleteValuationMode | ||
| 7 | } from '@/api/modules/dataEntry'; | ||
| 8 | import { TableColumnWidth } from "@/utils/enum"; | ||
| 9 | import { changeNum } from "@/utils/common"; | ||
| 10 | import useEntryStore from "@/store/modules/dataEntry"; | ||
| 11 | |||
| 12 | const entryStore = useEntryStore(); | ||
| 13 | |||
| 14 | const router = useRouter() | ||
| 15 | |||
| 16 | const { proxy } = getCurrentInstance() as any; | ||
| 17 | |||
| 18 | /** 头部搜索框配置 */ | ||
| 19 | const searchItemList = ref([ | ||
| 20 | { | ||
| 21 | type: "input", | ||
| 22 | label: "", | ||
| 23 | field: "damName", | ||
| 24 | default: "", | ||
| 25 | placeholder: "数据产品名称", | ||
| 26 | clearable: true, | ||
| 27 | }, | ||
| 28 | { | ||
| 29 | type: "select", | ||
| 30 | label: "", | ||
| 31 | field: "evaluateMethod", | ||
| 32 | default: "", | ||
| 33 | placeholder: "评估方法", | ||
| 34 | options: [ | ||
| 35 | { label: "成本法", value: "1" }, | ||
| 36 | { label: "收益法", value: "2" }, | ||
| 37 | ], | ||
| 38 | clearable: true, | ||
| 39 | } | ||
| 40 | ]); | ||
| 41 | |||
| 42 | /** 分页及搜索传参信息配置。 */ | ||
| 43 | const page = ref({ | ||
| 44 | ...commonPageConfig, | ||
| 45 | damName: '', | ||
| 46 | evaluateMethod: '' | ||
| 47 | }); | ||
| 48 | |||
| 49 | const tableSelectRowData: any = ref([]); | ||
| 50 | |||
| 51 | const tableInfo = ref({ | ||
| 52 | id: 'valuation-model-table', | ||
| 53 | multiple: true, | ||
| 54 | fields: [ | ||
| 55 | { label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" }, | ||
| 56 | { label: "数据产品名称", field: "damName", width: 160 }, | ||
| 57 | { | ||
| 58 | label: "评估方法", field: "evaluateMethod", width: 140, getName: (scope) => { | ||
| 59 | return scope.row.evaluateMethod == '1' ? '成本法' : '收益法'; | ||
| 60 | } | ||
| 61 | }, | ||
| 62 | { label: "评估基准日", field: "evaluateBaseDate", width: TableColumnWidth.DATE, }, | ||
| 63 | { | ||
| 64 | label: "评估价值(元)", field: "damValuation", width: 160, align: 'right' | ||
| 65 | }, | ||
| 66 | { label: "修改人", field: "updateUserName", width: TableColumnWidth.USERNAME }, | ||
| 67 | { label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME }, | ||
| 68 | ], | ||
| 69 | data: [], | ||
| 70 | page: { | ||
| 71 | type: "normal", | ||
| 72 | rows: 0, | ||
| 73 | ...page.value, | ||
| 74 | }, | ||
| 75 | actionInfo: { | ||
| 76 | label: "操作", | ||
| 77 | type: "btn", | ||
| 78 | width: 140, | ||
| 79 | fixed: 'right', | ||
| 80 | btns: (scope) => { | ||
| 81 | let btnsArr: any = []; | ||
| 82 | btnsArr.push({ | ||
| 83 | label: "编辑", value: "edit", click: (scope) => { | ||
| 84 | router.push({ | ||
| 85 | name: 'valuationModelCreate', | ||
| 86 | query: { | ||
| 87 | guid: scope.row.guid, | ||
| 88 | name: scope.row.damName | ||
| 89 | } | ||
| 90 | }) | ||
| 91 | } | ||
| 92 | }); | ||
| 93 | btnsArr.push({ | ||
| 94 | label: "删除", value: "delete", click: (scope) => { | ||
| 95 | proxy.$openMessageBox('此操作将永久删除, 是否继续?', () => { | ||
| 96 | deleteValuationMode([scope.row.guid]).then((res: any) => { | ||
| 97 | if (res.code == proxy.$passCode) { | ||
| 98 | page.value.curr = 1; | ||
| 99 | getTableData(); | ||
| 100 | proxy.$ElMessage({ | ||
| 101 | type: "success", | ||
| 102 | message: "删除成功", | ||
| 103 | }); | ||
| 104 | } else { | ||
| 105 | proxy.$ElMessage({ | ||
| 106 | type: 'error', | ||
| 107 | message: res.msg, | ||
| 108 | }) | ||
| 109 | } | ||
| 110 | }) | ||
| 111 | }, () => { | ||
| 112 | proxy.$ElMessage.info("已取消删除"); | ||
| 113 | }) | ||
| 114 | } | ||
| 115 | }); | ||
| 116 | return btnsArr | ||
| 117 | }, | ||
| 118 | }, | ||
| 119 | loading: false | ||
| 120 | }) | ||
| 121 | |||
| 122 | const toSearch = (val: any, clear: boolean = false) => { | ||
| 123 | if (clear) { | ||
| 124 | searchItemList.value.map((item) => (item.default = "")); | ||
| 125 | page.value.damName = ''; | ||
| 126 | page.value.evaluateMethod = ""; | ||
| 127 | } else { | ||
| 128 | page.value.damName = val.damName; | ||
| 129 | page.value.evaluateMethod = val.evaluateMethod; | ||
| 130 | } | ||
| 131 | getTableData(); | ||
| 132 | }; | ||
| 133 | |||
| 134 | const getTableData = () => { | ||
| 135 | tableInfo.value.loading = true | ||
| 136 | getValuationModelList({ | ||
| 137 | pageIndex: page.value.curr, | ||
| 138 | pageSize: page.value.limit, | ||
| 139 | damName: page.value.damName, | ||
| 140 | evaluateMethod: page.value.evaluateMethod | ||
| 141 | }).then((res: any) => { | ||
| 142 | if (res.code == proxy.$passCode) { | ||
| 143 | const data = res.data || {} | ||
| 144 | tableInfo.value.data = data.records || [] | ||
| 145 | tableInfo.value.page.limit = data.pageSize | ||
| 146 | tableInfo.value.page.curr = data.pageIndex | ||
| 147 | tableInfo.value.page.rows = data.totalRows | ||
| 148 | } else { | ||
| 149 | proxy.$ElMessage({ | ||
| 150 | type: 'error', | ||
| 151 | message: res.msg, | ||
| 152 | }) | ||
| 153 | } | ||
| 154 | tableInfo.value.loading = false | ||
| 155 | }).catch(() => { | ||
| 156 | tableInfo.value.loading = false | ||
| 157 | }) | ||
| 158 | }; | ||
| 159 | |||
| 160 | const tablePageChange = (info) => { | ||
| 161 | page.value.curr = Number(info.curr); | ||
| 162 | page.value.limit = Number(info.limit); | ||
| 163 | tableInfo.value.page.curr = page.value.curr; | ||
| 164 | tableInfo.value.page.limit = page.value.limit; | ||
| 165 | getTableData(); | ||
| 166 | }; | ||
| 167 | |||
| 168 | const tableSelectionChange = (val) => { | ||
| 169 | tableSelectRowData.value = val; | ||
| 170 | }; | ||
| 171 | |||
| 172 | const newCreate = () => { | ||
| 173 | router.push({ | ||
| 174 | name: 'valuationModelCreate' | ||
| 175 | }); | ||
| 176 | } | ||
| 177 | |||
| 178 | const batchDelete = () => { | ||
| 179 | if (tableSelectRowData.value.length == 0) { | ||
| 180 | proxy.$ElMessage({ | ||
| 181 | type: 'error', | ||
| 182 | message: '请选择需要删除的数据', | ||
| 183 | }) | ||
| 184 | return | ||
| 185 | } | ||
| 186 | proxy.$openMessageBox('此操作将永久删除, 是否继续?', () => { | ||
| 187 | deleteValuationMode(tableSelectRowData.value.map(d => d.guid)).then((res: any) => { | ||
| 188 | if (res.code == proxy.$passCode) { | ||
| 189 | page.value.curr = 1; | ||
| 190 | getTableData(); | ||
| 191 | proxy.$ElMessage.success('删除成功'); | ||
| 192 | } else { | ||
| 193 | proxy.$ElMessage.error(res.msg); | ||
| 194 | } | ||
| 195 | }) | ||
| 196 | }, () => { | ||
| 197 | proxy.$ElMessage.info("已取消删除"); | ||
| 198 | }) | ||
| 199 | } | ||
| 200 | |||
| 201 | onBeforeMount(() => { | ||
| 202 | // toSearch({}) | ||
| 203 | }) | ||
| 204 | |||
| 205 | onActivated(() => { | ||
| 206 | if (entryStore.isRefresh) { | ||
| 207 | getTableData(); | ||
| 208 | entryStore.setIsRefresh(false); | ||
| 209 | } | ||
| 210 | }) | ||
| 211 | |||
| 212 | </script> | ||
| 213 | |||
| 214 | <template> | ||
| 215 | <div class="container_wrap"> | ||
| 216 | <div class="table_tool_wrap"> | ||
| 217 | <!-- 头部搜索 --> | ||
| 218 | <TableTools :searchItems="searchItemList" :searchId="'data-source-search'" @search="toSearch" /> | ||
| 219 | <div class="tools_btns"> | ||
| 220 | <el-button type="primary" @click="newCreate">新建</el-button> | ||
| 221 | <el-button @click="batchDelete">批量删除</el-button> | ||
| 222 | </div> | ||
| 223 | </div> | ||
| 224 | <div class="table_panel_wrap"> | ||
| 225 | <Table :tableInfo="tableInfo" @tablePageChange="tablePageChange" @tableSelectionChange="tableSelectionChange" /> | ||
| 226 | </div> | ||
| 227 | </div> | ||
| 228 | </template> | ||
| 229 | |||
| 230 | <style lang="scss" scoped> | ||
| 231 | .table_tool_wrap { | ||
| 232 | width: 100%; | ||
| 233 | height: 84px !important; | ||
| 234 | padding: 0 8px; | ||
| 235 | |||
| 236 | .tools_btns { | ||
| 237 | padding: 0px 0 0; | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | .table_panel_wrap { | ||
| 242 | width: 100%; | ||
| 243 | height: calc(100% - 84px); | ||
| 244 | padding: 0px 8px 0; | ||
| 245 | } | ||
| 246 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | <script lang="ts" setup name="valuationModelCreate"> | ||
| 2 | import { | ||
| 3 | getAssetCatalog, | ||
| 4 | saveValuationMode, | ||
| 5 | updateValuationMode, | ||
| 6 | getValuationModelDetail | ||
| 7 | } from "@/api/modules/dataEntry"; | ||
| 8 | import { useValidator } from '@/hooks/useValidator'; | ||
| 9 | import useUserStore from "@/store/modules/user"; | ||
| 10 | import { | ||
| 11 | changeNum, | ||
| 12 | } from "@/utils/common"; | ||
| 13 | import moment from "moment"; | ||
| 14 | import useEntryStore from "@/store/modules/dataEntry"; | ||
| 15 | |||
| 16 | const userStore = useUserStore(); | ||
| 17 | const entryStore = useEntryStore(); | ||
| 18 | const { required } = useValidator(); | ||
| 19 | const { proxy } = getCurrentInstance() as any; | ||
| 20 | const router = useRouter(); | ||
| 21 | const route = useRoute(); | ||
| 22 | const fullPath = route.fullPath; | ||
| 23 | const fullscreenLoading = ref(false); | ||
| 24 | |||
| 25 | /** 数据产品列表 */ | ||
| 26 | const damProductList: any = ref([]); | ||
| 27 | |||
| 28 | const formRef = ref(); | ||
| 29 | const valuateFormItems: any = ref([ | ||
| 30 | { | ||
| 31 | label: "数据产品名称", | ||
| 32 | type: "select", | ||
| 33 | placeholder: "请选择,来自数据产品目录", | ||
| 34 | field: "damGuid", | ||
| 35 | default: '', | ||
| 36 | options: damProductList.value, | ||
| 37 | props: { | ||
| 38 | label: 'damName', | ||
| 39 | value: 'guid' | ||
| 40 | }, | ||
| 41 | disabled: false, | ||
| 42 | filterable: true, | ||
| 43 | clearable: true, | ||
| 44 | required: true, | ||
| 45 | }, | ||
| 46 | { | ||
| 47 | label: "基准日", | ||
| 48 | type: "date-month", | ||
| 49 | field: "evaluateBaseDate", | ||
| 50 | default: moment(new Date()).format('YYYY-MM'), | ||
| 51 | placeholder: "请选择", | ||
| 52 | clearable: true, | ||
| 53 | required: true, | ||
| 54 | style: { width: 'calc(33.33% - 70px)', 'margin-right': '8px' }, | ||
| 55 | popperClass: 'date-month-popper', | ||
| 56 | disabledDate: (date) => { | ||
| 57 | const curr = new Date(); | ||
| 58 | return date.getFullYear() == curr.getFullYear() ? date.getMonth() > curr.getMonth() : false; | ||
| 59 | }, | ||
| 60 | }, | ||
| 61 | { | ||
| 62 | type: "select", | ||
| 63 | field: "evaluateMethod", | ||
| 64 | default: "1", | ||
| 65 | label: "评估方法", | ||
| 66 | placeholder: "请选择", | ||
| 67 | required: true, | ||
| 68 | options: [ | ||
| 69 | { label: "成本法", value: "1" }, | ||
| 70 | { label: "收益法", value: "2" }, | ||
| 71 | ] | ||
| 72 | }, | ||
| 73 | { | ||
| 74 | type: "select", | ||
| 75 | label: "使用年限(1~10)", | ||
| 76 | field: "useYears", | ||
| 77 | default: 1, | ||
| 78 | options: [{ | ||
| 79 | value: 1, | ||
| 80 | label: '1' | ||
| 81 | }, { | ||
| 82 | value: 2, | ||
| 83 | label: '2' | ||
| 84 | }, { | ||
| 85 | value: 3, | ||
| 86 | label: '3' | ||
| 87 | }, { | ||
| 88 | value: 4, | ||
| 89 | label: '4' | ||
| 90 | }, { | ||
| 91 | value: 5, | ||
| 92 | label: '5' | ||
| 93 | }, { | ||
| 94 | value: 6, | ||
| 95 | label: '6' | ||
| 96 | }, { | ||
| 97 | value: 7, | ||
| 98 | label: '7' | ||
| 99 | }, { | ||
| 100 | value: 8, | ||
| 101 | label: '8' | ||
| 102 | }, { | ||
| 103 | value: 9, | ||
| 104 | label: '9' | ||
| 105 | }, { | ||
| 106 | value: 10, | ||
| 107 | label: '10' | ||
| 108 | }], | ||
| 109 | placeholder: "年限1~10", | ||
| 110 | clearable: false, | ||
| 111 | filterable: true, | ||
| 112 | required: true, | ||
| 113 | visible: false | ||
| 114 | }, | ||
| 115 | ]); | ||
| 116 | |||
| 117 | const valuateFormRules = ref({ | ||
| 118 | // damGuid: [required('请选择数据产品名称')], | ||
| 119 | evaluateBaseDate: [required('请选择基准日')], | ||
| 120 | evaluateMethod: [required('请选择评估方法')], | ||
| 121 | useYears: [{ type: 'number', min: 1, max: 10, message: "请填写年限1~10", trigger: "change", },] | ||
| 122 | }); | ||
| 123 | |||
| 124 | const handleValudateFormChange = (val, row, info) => { | ||
| 125 | if (row.field == 'evaluateMethod') { | ||
| 126 | valuateFormItems.value.forEach(item => { | ||
| 127 | item.default = info[item.field]; | ||
| 128 | if (item.field == 'useYears') { | ||
| 129 | item.visible = item.default != '1'; | ||
| 130 | item.default = info.useYears ? info.useYears : 1; | ||
| 131 | } | ||
| 132 | }) | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | /** 获取当月的最后一天。 */ | ||
| 137 | const getLastDayOfMonth = (month) => { | ||
| 138 | const year = parseInt(month.split('-')[0], 10); | ||
| 139 | const monthIndex = parseInt(month.split('-')[1], 10) - 1; // JavaScript 的月份是从0开始计数的 | ||
| 140 | const date = new Date(year, monthIndex + 1, 0); // 使用0可以得到前一个月的最后一天 | ||
| 141 | const yearString = date.getFullYear(); | ||
| 142 | const monthString = String(date.getMonth() + 1).padStart(2, '0'); // JavaScript 的月份是从0开始计数的 | ||
| 143 | const dayString = String(date.getDate()).padStart(2, '0'); | ||
| 144 | return `${yearString}-${monthString}-${dayString}`; | ||
| 145 | } | ||
| 146 | |||
| 147 | const costTableField: any = ref([ | ||
| 148 | { label: "环节", field: "link", width: 160 }, | ||
| 149 | { label: "一级指标", field: "primaryIndex", width: 160 }, | ||
| 150 | { label: "二级指标", field: "secondIndex", width: 160 }, | ||
| 151 | { label: '金额(元)', align: 'right', field: 'amount', type: 'input', width: 150, columClass: 'edit_cell' }, | ||
| 152 | { label: "通常包含的成本输入项", field: "costInput", width: 380 }, | ||
| 153 | { label: "费用科目", field: "expenseAccount", width: 220 }, | ||
| 154 | ]); | ||
| 155 | |||
| 156 | const costTableData = ref([{ | ||
| 157 | orderNum: 1, | ||
| 158 | link: '顺序性环节', | ||
| 159 | primaryIndex: '数据规划', | ||
| 160 | secondIndex: '数据规划', | ||
| 161 | amount: '', | ||
| 162 | costInput: '包含数据生存周期整体规划所投入的人员薪资、咨询费用及相关资源成本等', | ||
| 163 | expenseAccount: '咨询费/会议费/人工费(拆分)' | ||
| 164 | }, { | ||
| 165 | orderNum: 2, | ||
| 166 | link: '顺序性环节', | ||
| 167 | primaryIndex: '数据采集', | ||
| 168 | secondIndex: '人工采集', | ||
| 169 | amount: '', | ||
| 170 | costInput: '向数据持有人购买数据的价款、注册费、手续费、服务费等', | ||
| 171 | expenseAccount: '人工费、劳保费、劳务费、运输费' | ||
| 172 | }, { | ||
| 173 | orderNum: 3, | ||
| 174 | link: '顺序性环节', | ||
| 175 | primaryIndex: '数据采集', | ||
| 176 | secondIndex: '自动化采集', | ||
| 177 | amount: '', | ||
| 178 | costInput: '在数据采集阶段发生的人员薪酬、打印费、网络费等相关费用', | ||
| 179 | expenseAccount: '人工费、设备费、材料费' | ||
| 180 | }, { | ||
| 181 | orderNum: 4, | ||
| 182 | link: '顺序性环节', | ||
| 183 | primaryIndex: '数据汇聚', | ||
| 184 | secondIndex: '数据传输', | ||
| 185 | amount: '', | ||
| 186 | costInput: '', | ||
| 187 | expenseAccount: '' | ||
| 188 | }, { | ||
| 189 | orderNum: 5, | ||
| 190 | link: '顺序性环节', | ||
| 191 | primaryIndex: '数据汇聚', | ||
| 192 | secondIndex: '网络通讯', | ||
| 193 | amount: '', | ||
| 194 | costInput: '传输数据发生的管道成本', | ||
| 195 | expenseAccount: '网络费用' | ||
| 196 | }, { | ||
| 197 | orderNum: 6, | ||
| 198 | link: '顺序性环节', | ||
| 199 | primaryIndex: '数据加工', | ||
| 200 | secondIndex: '数据脱敏', | ||
| 201 | amount: '', | ||
| 202 | costInput: '对敏感数据进行变形处理所发生的人力成本、技术成本等', | ||
| 203 | expenseAccount: '人工费' | ||
| 204 | }, { | ||
| 205 | orderNum: 7, | ||
| 206 | link: '顺序性环节', | ||
| 207 | primaryIndex: '数据加工', | ||
| 208 | secondIndex: '数据清洗', | ||
| 209 | amount: '', | ||
| 210 | costInput: '去除重复数据、填补缺失值、处理异常值和转换数据格式等投入', | ||
| 211 | expenseAccount: '人工费' | ||
| 212 | }, { | ||
| 213 | orderNum: 8, | ||
| 214 | link: '顺序性环节', | ||
| 215 | primaryIndex: '数据加工', | ||
| 216 | secondIndex: '数据标注', | ||
| 217 | amount: '', | ||
| 218 | costInput: '对数据进行添加标签处理所发生的费用,人工或AI标注', | ||
| 219 | expenseAccount: '人工费、无形资产分摊' | ||
| 220 | }, { | ||
| 221 | orderNum: 9, | ||
| 222 | link: '顺序性环节', | ||
| 223 | primaryIndex: '数据加工', | ||
| 224 | secondIndex: '数据整合', | ||
| 225 | amount: '', | ||
| 226 | costInput: '数据整合成本是指合并整理来自不同数据源的数据所发生的成本', | ||
| 227 | expenseAccount: '人工费、材料费等' | ||
| 228 | }, { | ||
| 229 | orderNum: 10, | ||
| 230 | link: '顺序性环节', | ||
| 231 | primaryIndex: '数据分析', | ||
| 232 | secondIndex: '数据分析', | ||
| 233 | amount: '', | ||
| 234 | costInput: '采用适当的方法对数据进行分析整理所发生的成本费用', | ||
| 235 | expenseAccount: '人工费' | ||
| 236 | }, { | ||
| 237 | orderNum: 11, | ||
| 238 | link: '顺序性环节', | ||
| 239 | primaryIndex: '数据分析', | ||
| 240 | secondIndex: '数据可视化', | ||
| 241 | amount: '', | ||
| 242 | costInput: '通过图形化手段清晰有效地传达信息所发生的成本费用', | ||
| 243 | expenseAccount: '人工费' | ||
| 244 | }, { | ||
| 245 | orderNum: 12, | ||
| 246 | link: '顺序性环节', | ||
| 247 | primaryIndex: '数据产品开发', | ||
| 248 | secondIndex: '数据产品开发', | ||
| 249 | amount: '', | ||
| 250 | costInput: '面向数据应用和服务,开发、封装数据产品所产生的费用', | ||
| 251 | expenseAccount: '人工费,股份支付,生产成本外协技术费' | ||
| 252 | }, { | ||
| 253 | orderNum: 13, | ||
| 254 | link: '全流程环节', | ||
| 255 | primaryIndex: '计算与存储', | ||
| 256 | secondIndex: '数据存储', | ||
| 257 | amount: '', | ||
| 258 | costInput: '存储库的构建、优化等费用', | ||
| 259 | expenseAccount: '云存储资源使用费,数据库使用费' | ||
| 260 | }, { | ||
| 261 | orderNum: 14, | ||
| 262 | link: '全流程环节', | ||
| 263 | primaryIndex: '计算与存储', | ||
| 264 | secondIndex: '计算资源', | ||
| 265 | amount: '', | ||
| 266 | costInput: '按流量计费、云服务分摊', | ||
| 267 | expenseAccount: '计算资源采购费用' | ||
| 268 | }, { | ||
| 269 | orderNum: 15, | ||
| 270 | link: '全流程环节', | ||
| 271 | primaryIndex: '数据维护', | ||
| 272 | secondIndex: '数据维护', | ||
| 273 | amount: '', | ||
| 274 | costInput: '数据权属鉴证、质量评估、登记、交易成本、数据合规费用', | ||
| 275 | expenseAccount: '人工费、技术服务费' | ||
| 276 | }, { | ||
| 277 | orderNum: 16, | ||
| 278 | link: '全流程环节', | ||
| 279 | primaryIndex: '数据维护', | ||
| 280 | secondIndex: '数据维护', | ||
| 281 | amount: '', | ||
| 282 | costInput: '数据加工费用,包括数据调整、补全、标注、更新和脱敏等费用', | ||
| 283 | expenseAccount: '人工费、技术服务费' | ||
| 284 | }, { | ||
| 285 | orderNum: 17, | ||
| 286 | link: '全流程环节', | ||
| 287 | primaryIndex: '数据维护', | ||
| 288 | secondIndex: '数据维护', | ||
| 289 | amount: '', | ||
| 290 | costInput: '数据备份、数据迁移和应急处置等费用', | ||
| 291 | expenseAccount: '人工费、设备费、技术服务费' | ||
| 292 | }, { | ||
| 293 | orderNum: 18, | ||
| 294 | link: '全流程环节', | ||
| 295 | primaryIndex: '数据安全', | ||
| 296 | secondIndex: '信息安全', | ||
| 297 | amount: '', | ||
| 298 | costInput: '软性:等保认证等', | ||
| 299 | expenseAccount: '人工费、等保服务费、质量评价服务费、鉴权咨询费' | ||
| 300 | }, { | ||
| 301 | orderNum: 19, | ||
| 302 | link: '全流程环节', | ||
| 303 | primaryIndex: '数据安全', | ||
| 304 | secondIndex: '硬件或系统安全', | ||
| 305 | amount: '', | ||
| 306 | costInput: '硬件或系统:安全产品、安全管理技术或服务', | ||
| 307 | expenseAccount: '防火墙或安全软件等采购费用' | ||
| 308 | }, { | ||
| 309 | orderNum: 20, | ||
| 310 | link: '全流程环节', | ||
| 311 | primaryIndex: '间接成本', | ||
| 312 | secondIndex: '软硬件成本', | ||
| 313 | amount: '', | ||
| 314 | costInput: '与数据资产相关的软硬件采购或研发以及维护费用', | ||
| 315 | expenseAccount: '材料费,产品检测费,物料消耗费,修理费' | ||
| 316 | }, { | ||
| 317 | orderNum: 21, | ||
| 318 | link: '全流程环节', | ||
| 319 | primaryIndex: '间接成本', | ||
| 320 | secondIndex: '基础设施成本', | ||
| 321 | amount: '', | ||
| 322 | costInput: '包括机房、场地等建设或租赁以及维护费用', | ||
| 323 | expenseAccount: '机房建设,物业费,租金,物联网大数据中心建设费' | ||
| 324 | }, { | ||
| 325 | orderNum: 22, | ||
| 326 | link: '全流程环节', | ||
| 327 | primaryIndex: '间接成本', | ||
| 328 | secondIndex: '公共管理成本', | ||
| 329 | amount: '', | ||
| 330 | costInput: '水电、职工福利、差旅费、折旧费、办公费、通讯费', | ||
| 331 | expenseAccount: '水电、职工福利、差旅费、折旧费、办公费、通讯费' | ||
| 332 | }]); | ||
| 333 | |||
| 334 | const costTableSpanMethod = ({ row, column, rowIndex, columnIndex }) => { | ||
| 335 | if (columnIndex == 0) { //第一列环节 | ||
| 336 | let columnValue = costTableData.value[rowIndex].link; | ||
| 337 | if (rowIndex == 0 || columnValue != costTableData.value[rowIndex - 1].link) { | ||
| 338 | let cnt = costTableData.value.filter(d => d.link == columnValue).length; | ||
| 339 | return { | ||
| 340 | rowspan: cnt, | ||
| 341 | colspan: 1 | ||
| 342 | } | ||
| 343 | } else { | ||
| 344 | return { | ||
| 345 | rowspan: 0, | ||
| 346 | colspan: 0 | ||
| 347 | } | ||
| 348 | } | ||
| 349 | } else if (columnIndex == 1) {//第二列的合并 | ||
| 350 | let columnValue = costTableData.value[rowIndex].primaryIndex; | ||
| 351 | if (rowIndex == 0 || columnValue != costTableData.value[rowIndex - 1].primaryIndex) { | ||
| 352 | let cnt = costTableData.value.filter(d => d.primaryIndex == columnValue).length; | ||
| 353 | return { | ||
| 354 | rowspan: cnt, | ||
| 355 | colspan: 1 | ||
| 356 | } | ||
| 357 | } else { | ||
| 358 | return { | ||
| 359 | rowspan: 0, | ||
| 360 | colspan: 0 | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } else if (columnIndex == 2) {//二级指标,合并数据维护。 | ||
| 364 | let columnValue = costTableData.value[rowIndex].secondIndex; | ||
| 365 | if (columnValue == '数据维护') { | ||
| 366 | if (columnValue != costTableData.value[rowIndex - 1].secondIndex) { | ||
| 367 | return { | ||
| 368 | rowspan: 3, | ||
| 369 | colspan: 1 | ||
| 370 | } | ||
| 371 | } else { | ||
| 372 | return { | ||
| 373 | rowspan: 0, | ||
| 374 | colspan: 0 | ||
| 375 | } | ||
| 376 | } | ||
| 377 | } | ||
| 378 | } | ||
| 379 | return { | ||
| 380 | rowspan: 1, | ||
| 381 | colspan: 1 | ||
| 382 | } | ||
| 383 | } | ||
| 384 | |||
| 385 | const costTableSummaryValue: any = ref(0); | ||
| 386 | |||
| 387 | // 表格合计行 | ||
| 388 | const costTableSummaryMethod = ({ columns, data }) => { | ||
| 389 | let sums: any[] = []; | ||
| 390 | columns.forEach((column, index) => { | ||
| 391 | if (index === 0) { //需要显示'总金额'的列 坐标 :0 | ||
| 392 | sums[index] = '数据资产估值' | ||
| 393 | return | ||
| 394 | } else { | ||
| 395 | if (column.property == 'amount') { | ||
| 396 | const values = data.map(item => parseFloat(item[column.property] ? item[column.property].replace(/,/g, "") : 0)); | ||
| 397 | if (!values.every(value => isNaN(value))) { | ||
| 398 | const sum = values.reduce((prev, curr) => { | ||
| 399 | const value = parseFloat(curr || 0) | ||
| 400 | if (!isNaN(value)) { | ||
| 401 | return prev + curr | ||
| 402 | } else { | ||
| 403 | return prev | ||
| 404 | } | ||
| 405 | }, 0) | ||
| 406 | sums[index] = costTableSummaryValue.value = changeNum(sum, 2, true) | ||
| 407 | } else { | ||
| 408 | sums[index] = costTableSummaryValue.value = 'N/A' | ||
| 409 | } | ||
| 410 | } | ||
| 411 | } | ||
| 412 | }) | ||
| 413 | return sums | ||
| 414 | } | ||
| 415 | |||
| 416 | /** --------------------------- 收入法 --------------------------- */ | ||
| 417 | |||
| 418 | const incomeTableField: any = ref([ | ||
| 419 | { label: "指标名称", field: "indexName", width: 160 }, | ||
| 420 | { label: "单位", field: "unit", width: 100 }, | ||
| 421 | { label: "预测年限", field: "years", showChild: true, align: 'center' }, | ||
| 422 | { label: "说明", field: "instructions", width: 380 }, | ||
| 423 | ]); | ||
| 424 | |||
| 425 | const incomeYears = computed(() => { | ||
| 426 | let formInline = formRef.value.formInline; | ||
| 427 | if (formInline.evaluateMethod == '1') { | ||
| 428 | return []; | ||
| 429 | } | ||
| 430 | let evaluateBaseDate = formInline.evaluateBaseDate; | ||
| 431 | let useYears = formInline.useYears; | ||
| 432 | let infos = evaluateBaseDate.split('-'); | ||
| 433 | let year = parseInt(infos[0]); | ||
| 434 | let month = parseInt(infos[1]); | ||
| 435 | if (month == 12) { | ||
| 436 | let a = [{ | ||
| 437 | field: year + '', | ||
| 438 | label: year + '年' | ||
| 439 | }]; | ||
| 440 | for (var i = 1; i < useYears + 1; i++) { | ||
| 441 | a.push({ | ||
| 442 | field: year + i + '', | ||
| 443 | label: (year + i) + '年' | ||
| 444 | }); | ||
| 445 | } | ||
| 446 | return a; | ||
| 447 | } else if (month == 1) { | ||
| 448 | let a = [{ | ||
| 449 | field: evaluateBaseDate + '', | ||
| 450 | label: year + '年' + `(1)` | ||
| 451 | }]; | ||
| 452 | for (var i = 1; i < useYears + 1; i++) { | ||
| 453 | a.push({ | ||
| 454 | field: year + i + '', | ||
| 455 | label: i == useYears ? ((year + i) + '年' + `(1)`) : ((year + i) + '年') | ||
| 456 | }); | ||
| 457 | } | ||
| 458 | return a; | ||
| 459 | } else { | ||
| 460 | let a = [{ | ||
| 461 | field: evaluateBaseDate + '', | ||
| 462 | label: year + '年' + `(1~${month})` | ||
| 463 | }]; | ||
| 464 | for (var i = 1; i < useYears + 1; i++) { | ||
| 465 | a.push({ | ||
| 466 | field: year + i + '', | ||
| 467 | label: i == useYears ? ((year + i) + '年' + `(${month}~12)`) : ((year + i) + '年') | ||
| 468 | }); | ||
| 469 | } | ||
| 470 | return a; | ||
| 471 | } | ||
| 472 | }) | ||
| 473 | |||
| 474 | const incomeTableData: any = ref([{ | ||
| 475 | orderNum: 1, | ||
| 476 | indexName: '收入', | ||
| 477 | unit: '元', | ||
| 478 | instructions: '数据创造或者是数据所在应用场景下的收入' | ||
| 479 | }, { | ||
| 480 | orderNum: 2, | ||
| 481 | indexName: '毛利率', | ||
| 482 | unit: '%', | ||
| 483 | instructions: '数据创造或者是数据所在应用场景下的毛利率' | ||
| 484 | }, { | ||
| 485 | orderNum: 3, | ||
| 486 | indexName: '营业利润率', | ||
| 487 | unit: '%', | ||
| 488 | instructions: '数据创造或者是数据所在应用场景下的营业利润率' | ||
| 489 | }, { | ||
| 490 | orderNum: 4, | ||
| 491 | indexName: '净利润率', | ||
| 492 | unit: '%', | ||
| 493 | instructions: '数据创造或者是数据所在应用场景下的净利润率' | ||
| 494 | }, { | ||
| 495 | orderNum: 5, | ||
| 496 | indexName: '行业利润率水平', | ||
| 497 | unit: '%', | ||
| 498 | instructions: '参考同行业上市公司/企业历史年度细分业务利润率水平' | ||
| 499 | }, { | ||
| 500 | orderNum: 6, | ||
| 501 | indexName: '数据资产分成率', | ||
| 502 | unit: '%', | ||
| 503 | instructions: '即关于数据对于实现收入的贡献' | ||
| 504 | }, { | ||
| 505 | orderNum: 7, | ||
| 506 | indexName: '衰减率', | ||
| 507 | unit: '%', | ||
| 508 | instructions: '数据有效期为5年,衰减率可理解为每年20%' | ||
| 509 | }, { | ||
| 510 | orderNum: 8, | ||
| 511 | indexName: '综合分成率', | ||
| 512 | unit: '%', | ||
| 513 | auto: true, | ||
| 514 | instructions: '自动计算' | ||
| 515 | }, { | ||
| 516 | orderNum: 9, | ||
| 517 | indexName: '现金流', | ||
| 518 | unit: '元', | ||
| 519 | auto: true, | ||
| 520 | instructions: '自动计算' | ||
| 521 | }, { | ||
| 522 | orderNum: 10, | ||
| 523 | indexName: '折现率', | ||
| 524 | unit: '%', | ||
| 525 | instructions: '一般行业在12%-16%之间,根据数据资产可变现的情况确认' | ||
| 526 | }, { | ||
| 527 | orderNum: 11, | ||
| 528 | indexName: '折现年期', | ||
| 529 | unit: '年', | ||
| 530 | auto: true, | ||
| 531 | instructions: '自动计算' | ||
| 532 | }, { | ||
| 533 | orderNum: 12, | ||
| 534 | indexName: '折现因子', | ||
| 535 | unit: '', | ||
| 536 | auto: true, | ||
| 537 | instructions: '自动计算' | ||
| 538 | }, { | ||
| 539 | orderNum: 13, | ||
| 540 | indexName: '折现现值', | ||
| 541 | unit: '元', | ||
| 542 | auto: true, | ||
| 543 | instructions: '自动计算,收入*利润率*分成率*折现因子' | ||
| 544 | }, { | ||
| 545 | orderNum: 14, | ||
| 546 | indexName: '数据资产估值', | ||
| 547 | unit: '元', | ||
| 548 | auto: true, | ||
| 549 | instructions: '自动计算' | ||
| 550 | }]) | ||
| 551 | |||
| 552 | const inputChange = (val, scope, field) => { | ||
| 553 | let row = scope.row; | ||
| 554 | let strArr = val.split("."); | ||
| 555 | if (strArr.length > 1) { | ||
| 556 | let right = strArr[1]; | ||
| 557 | if (right === "" || right.length < 2) { | ||
| 558 | row[field] = val = parseFloat(val || 0).toFixed(2); | ||
| 559 | } | ||
| 560 | } else { | ||
| 561 | row[field] = val = parseFloat(val || 0).toFixed(2); | ||
| 562 | } | ||
| 563 | } | ||
| 564 | |||
| 565 | /** 输入框输入触发事件 */ | ||
| 566 | const inputEventChange = (val, scope, field, max: any = null) => { | ||
| 567 | let row = scope.row; | ||
| 568 | row[field] = row[field].toString().replace(/[^\d.]/g, "") | ||
| 569 | row[field] = row[field].toString().replace(/\.{2,}/g, ".") | ||
| 570 | row[field] = row[field].toString().replace(".", "$#$").replace(/\./g, "").replace("$#$", ".") | ||
| 571 | row[field] = row[field].toString().replace(/^(\-)*(\d+)\.(\d\d\d\d\d\d).*$/, "$1$2.$3") | ||
| 572 | row[field] = row[field].toString().replace(/^\D*(\d{0,12}(?:\.\d{0,2})?).*$/g, "$1") | ||
| 573 | if (max !== null && row[field] > max) { | ||
| 574 | row[field] = max; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | const incomeCalculateData = computed(() => { //响应式不生效 | ||
| 579 | let data = incomeTableData.value; | ||
| 580 | let resultInfo: any = {}; | ||
| 581 | resultInfo['综合分成率'] = []; | ||
| 582 | resultInfo['现金流'] = []; | ||
| 583 | resultInfo['折现年期'] = []; | ||
| 584 | resultInfo['折现因子'] = []; | ||
| 585 | resultInfo['折现现值'] = []; | ||
| 586 | resultInfo['数据资产估值'] = 0; | ||
| 587 | let transfer = (v, need = true) => { | ||
| 588 | return v ? (need ? parseFloat(v) / 100 : parseFloat(v)) : 0; | ||
| 589 | } | ||
| 590 | incomeYears.value.forEach((year, i) => { | ||
| 591 | let C6 = transfer(data[5][year.field]) | ||
| 592 | let C7 = transfer(data[6][year.field]) | ||
| 593 | let sumC7: any = i == 0 ? C7 : incomeYears.value.slice(0, i + 1).reduce(function (prev, curr, idx, arr) { | ||
| 594 | return transfer(data[6][prev.field]) + transfer(data[6][curr.field]); | ||
| 595 | }) | ||
| 596 | resultInfo['综合分成率'].push(changeNum(C6 * (1 - sumC7 + C7 / 2) * 100, 2, true)); //TODO综合分成率算法有问题 | ||
| 597 | let C1 = transfer(data[0][year.field], false) | ||
| 598 | let C5 = transfer(data[4][year.field]) | ||
| 599 | resultInfo['现金流'].push(changeNum(C1 * C5 * resultInfo['综合分成率'][i] / 100, 2, true)); | ||
| 600 | if (i == 0) { | ||
| 601 | resultInfo['折现年期'].push(changeNum(10 / 12 / 2, 2, true)); | ||
| 602 | } else { | ||
| 603 | resultInfo['折现年期'].push(changeNum(parseFloat(resultInfo['折现年期'][i - 1]) + 1, 2, true)) | ||
| 604 | } | ||
| 605 | let C10 = transfer(data[9][year.field]); | ||
| 606 | resultInfo['折现因子'].push(changeNum(1 / Math.pow((1 + C10), parseFloat(resultInfo['折现年期'][i])), 2, true)); | ||
| 607 | resultInfo['折现现值'].push(changeNum(parseFloat(resultInfo['折现因子'][i]) * parseFloat(resultInfo['现金流'][i]), 2, true)); | ||
| 608 | }) | ||
| 609 | resultInfo['数据资产估值'] = changeNum(resultInfo['折现现值'].reduce(function (prev, curr, idx, arr) { | ||
| 610 | return parseFloat(prev) + parseFloat(curr); | ||
| 611 | }), 2, true); | ||
| 612 | return resultInfo; | ||
| 613 | }) | ||
| 614 | |||
| 615 | const submit = () => { | ||
| 616 | formRef.value?.ruleFormRef?.validate((valid, errorItem) => { | ||
| 617 | if (valid) { | ||
| 618 | let params = formRef.value.formInline; | ||
| 619 | if (params.evaluateMethod == '1') { | ||
| 620 | params.valuationCostRQVOList = costTableData.value; | ||
| 621 | params.damValuation = costTableSummaryValue.value; | ||
| 622 | } else { | ||
| 623 | params.valuationEarningsRQVOList = incomeTableData.value; | ||
| 624 | params.damValuation = incomeCalculateData.value['数据资产估值']; | ||
| 625 | params.valuationEarningsRQVOList.forEach(d => { | ||
| 626 | let years: any = {}; | ||
| 627 | incomeYears.value.forEach(y => { | ||
| 628 | years[y.field] = d[y.field]; | ||
| 629 | }) | ||
| 630 | d.predictedYears = years; | ||
| 631 | }) | ||
| 632 | } | ||
| 633 | params.evaluateBaseDate = getLastDayOfMonth(params.evaluateBaseDate); | ||
| 634 | fullscreenLoading.value = true; | ||
| 635 | if (!route.query.guid) { | ||
| 636 | saveValuationMode(params).then((res: any) => { | ||
| 637 | fullscreenLoading.value = false; | ||
| 638 | if (res.code == proxy.$passCode) { | ||
| 639 | proxy.$ElMessage.success('新建估值模型提交保存成功'); | ||
| 640 | userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); | ||
| 641 | router.push({ | ||
| 642 | name: 'valuationModel' | ||
| 643 | }); | ||
| 644 | entryStore.setIsRefresh(true); | ||
| 645 | } else { | ||
| 646 | proxy.$ElMessage({ | ||
| 647 | type: 'error', | ||
| 648 | message: res.msg, | ||
| 649 | }) | ||
| 650 | } | ||
| 651 | }) | ||
| 652 | } else { | ||
| 653 | params.guid = route.query.guid; | ||
| 654 | updateValuationMode(params).then((res: any) => { | ||
| 655 | fullscreenLoading.value = false; | ||
| 656 | if (res.code == proxy.$passCode) { | ||
| 657 | proxy.$ElMessage.success('编辑估值模型提交成功'); | ||
| 658 | userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); | ||
| 659 | router.push({ | ||
| 660 | name: 'valuationModel' | ||
| 661 | }); | ||
| 662 | entryStore.setIsRefresh(true); | ||
| 663 | } else { | ||
| 664 | proxy.$ElMessage({ | ||
| 665 | type: 'error', | ||
| 666 | message: res.msg, | ||
| 667 | }) | ||
| 668 | } | ||
| 669 | }) | ||
| 670 | } | ||
| 671 | } else { | ||
| 672 | var obj = Object.keys(errorItem); | ||
| 673 | formRef.value.ruleFormRef.scrollToField(obj[0]) | ||
| 674 | } | ||
| 675 | }) | ||
| 676 | } | ||
| 677 | |||
| 678 | const cancel = () => { | ||
| 679 | proxy.$openMessageBox("当前页面尚未保存,确定放弃修改吗?", () => { | ||
| 680 | userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); | ||
| 681 | router.push({ | ||
| 682 | name: 'valuationModel' | ||
| 683 | }); | ||
| 684 | }, () => { | ||
| 685 | proxy.$ElMessage.info("已取消"); | ||
| 686 | }); | ||
| 687 | } | ||
| 688 | |||
| 689 | const getDamProductListData = () => { | ||
| 690 | getAssetCatalog({ | ||
| 691 | pageSize: -1 | ||
| 692 | }).then((res: any) => { | ||
| 693 | if (res.code == proxy.$passCode) { | ||
| 694 | damProductList.value = res.data || []; | ||
| 695 | valuateFormItems.value[0].options = damProductList.value; | ||
| 696 | } else { | ||
| 697 | proxy.$ElMessage({ | ||
| 698 | type: 'error', | ||
| 699 | message: res.msg, | ||
| 700 | }) | ||
| 701 | } | ||
| 702 | }) | ||
| 703 | } | ||
| 704 | |||
| 705 | onBeforeMount(() => { | ||
| 706 | getDamProductListData(); | ||
| 707 | if (route.query.guid) { | ||
| 708 | fullscreenLoading.value = true; | ||
| 709 | getValuationModelDetail({ guid: route.query.guid }).then((res: any) => { | ||
| 710 | fullscreenLoading.value = false; | ||
| 711 | if (res.code == proxy.$passCode) { | ||
| 712 | let detailData = res.data || {}; | ||
| 713 | valuateFormItems.value.forEach(item => { | ||
| 714 | item.default = detailData[item.field]; | ||
| 715 | if (item.field == 'evaluateMethod') { | ||
| 716 | valuateFormItems.value.at(-1).visible = item.default == '2'; | ||
| 717 | } else if (item.field == 'evaluateBaseDate') { | ||
| 718 | item.default = item.default.substring(0, 7); | ||
| 719 | } | ||
| 720 | }) | ||
| 721 | if (detailData.evaluateMethod == '2') { | ||
| 722 | incomeTableData.value = detailData.valuationEarningsRSVOList || []; | ||
| 723 | incomeTableData.value.forEach((d, index) => { | ||
| 724 | Object.assign(d, d.predictedYears || {}); | ||
| 725 | if (d.indexName == '综合分成率' || d.indexName == '现金流' || d.indexName == '折现年期' || d.indexName == '折现因子' || d.indexName == '折现现值' || d.indexName == '数据资产估值') { | ||
| 726 | d.auto = true; | ||
| 727 | } | ||
| 728 | }); | ||
| 729 | } else { | ||
| 730 | costTableData.value = detailData.valuationCostRSVOList || []; | ||
| 731 | costTableSummaryValue.value = detailData.damValuation || ''; | ||
| 732 | } | ||
| 733 | } else { | ||
| 734 | proxy.$ElMessage({ | ||
| 735 | type: 'error', | ||
| 736 | message: res.msg, | ||
| 737 | }) | ||
| 738 | } | ||
| 739 | }); | ||
| 740 | } | ||
| 741 | }) | ||
| 742 | |||
| 743 | onMounted(async () => { | ||
| 744 | await nextTick(); | ||
| 745 | await nextTick(); | ||
| 746 | const tables: any = document.querySelectorAll( | ||
| 747 | "#cost-table .el-table__footer-wrapper tr>td" | ||
| 748 | ); | ||
| 749 | tables[0].colSpan = 3; | ||
| 750 | tables[0].style.textAlign = "center"; | ||
| 751 | tables[1].style.display = "none"; | ||
| 752 | tables[2].style.display = "none"; | ||
| 753 | tables[4].style.display = "none"; | ||
| 754 | tables[5].style.display = "none"; | ||
| 755 | }) | ||
| 756 | |||
| 757 | </script> | ||
| 758 | |||
| 759 | <template> | ||
| 760 | <div class="container_wrap" v-loading="fullscreenLoading"> | ||
| 761 | <div class="content_main"> | ||
| 762 | <ContentWrap id="id-baseInfo" title="估值类型" instructions="" style="margin-top: 8px;"> | ||
| 763 | <Form ref="formRef" :itemList="valuateFormItems" :rules="valuateFormRules" formId="main-model-edit" | ||
| 764 | @select-change="handleValudateFormChange" col="col3" /> | ||
| 765 | </ContentWrap> | ||
| 766 | <ContentWrap id="id-grade-info" title="填写成本明细" | ||
| 767 | :instructions="formRef?.formInline?.evaluateMethod == '1' ? '填写时请按照所选数据产品的成本投入进行填写,跟数据产品产生的成本一致' : ''" | ||
| 768 | style="margin-top: 16px;"> | ||
| 769 | <el-table id="cost-table" v-show="formRef?.formInline?.evaluateMethod == '1'" ref="costTableRef" | ||
| 770 | :data="costTableData" :span-method="costTableSpanMethod" :summary-method="costTableSummaryMethod" show-summary | ||
| 771 | border tooltip-effect="light" :tooltip-options="{ placement: 'top', popperClass: 'table_cell_tooltip' }"> | ||
| 772 | <el-table-column v-for="(item, i) in costTableField" :label="item.label" :width="item.width" | ||
| 773 | :min-width="item.minWidth" :fixed="item.fixed" :align="item.align" :sortable="item.sortable ?? false" | ||
| 774 | :prop="item.field" :class-name="item.columClass" show-overflow-tooltip> | ||
| 775 | <template #default="scope"> | ||
| 776 | <div class="input_cell" v-if="item.type == 'input'"> | ||
| 777 | <el-input v-model.trim="scope.row[item.field]" placeholder="请输入" :maxlength="item.maxlength ?? ''" | ||
| 778 | @change="(val) => inputChange(val, scope, item.field)" | ||
| 779 | @input="(val) => inputEventChange(val, scope, item.field)" clearable></el-input> | ||
| 780 | </div> | ||
| 781 | <span v-else> | ||
| 782 | {{ item.getName ? item.getName(scope) : scope.row[item.field] !== 0 && !scope.row[item.field] ? | ||
| 783 | "--" : scope.row[item.field] }} | ||
| 784 | </span> | ||
| 785 | </template> | ||
| 786 | </el-table-column> | ||
| 787 | </el-table> | ||
| 788 | <el-table id="income-table" v-show="formRef?.formInline?.evaluateMethod != '1'" ref="costTableRef" | ||
| 789 | :data="incomeTableData" border tooltip-effect="light" | ||
| 790 | :tooltip-options="{ placement: 'top', popperClass: 'table_cell_tooltip' }"> | ||
| 791 | <el-table-column type="index" label="序号" width="80" align="center" /> | ||
| 792 | <el-table-column v-for="(item, i) in incomeTableField" :label="item.label" :width="item.width" | ||
| 793 | :min-width="item.minWidth" :fixed="item.fixed" :align="item.align" :sortable="item.sortable ?? false" | ||
| 794 | :prop="item.field" :class-name="item.columClass" show-overflow-tooltip> | ||
| 795 | <template #default="scope"> | ||
| 796 | <template v-if="item.showChild == true"> | ||
| 797 | <el-table-column v-for="(year, j) in incomeYears" :label="year.label" :width="150" align="right" | ||
| 798 | :prop="year.field" show-overflow-tooltip> | ||
| 799 | <template #default="scope"> | ||
| 800 | <div v-if="scope.row.auto != true" class="input_cell"> | ||
| 801 | <el-input v-model.trim="scope.row[year.field]" placeholder="请输入" | ||
| 802 | @change="(val) => inputChange(val, scope, year.field)" | ||
| 803 | @input="(val) => inputEventChange(val, scope, year.field, scope.row.unit == '%' ? 100 : null)" | ||
| 804 | clearable></el-input> | ||
| 805 | </div> | ||
| 806 | <span v-else> | ||
| 807 | {{ scope.row.indexName == '数据资产估值' ? (j > 0 ? '-' : incomeCalculateData[scope.row.indexName]) | ||
| 808 | : (incomeCalculateData[scope.row.indexName][j]) }} | ||
| 809 | </span> | ||
| 810 | </template> | ||
| 811 | </el-table-column> | ||
| 812 | </template> | ||
| 813 | <span v-else>{{ scope.row[item.field] || '-' }}</span> | ||
| 814 | </template> | ||
| 815 | </el-table-column> | ||
| 816 | </el-table> | ||
| 817 | </ContentWrap> | ||
| 818 | </div> | ||
| 819 | <div class="bottom_tool_wrap"> | ||
| 820 | <el-button @click="cancel">取消</el-button> | ||
| 821 | <el-button type="primary" @click="submit">提交</el-button> | ||
| 822 | </div> | ||
| 823 | </div> | ||
| 824 | </template> | ||
| 825 | |||
| 826 | <style lang="scss" scoped> | ||
| 827 | .container_wrap { | ||
| 828 | padding: 0px; | ||
| 829 | } | ||
| 830 | |||
| 831 | .content_main { | ||
| 832 | height: calc(100% - 44px); | ||
| 833 | padding: 10px 16px; | ||
| 834 | overflow: auto; | ||
| 835 | |||
| 836 | .table-top-btns { | ||
| 837 | margin-bottom: 12px; | ||
| 838 | } | ||
| 839 | } | ||
| 840 | |||
| 841 | .bottom_tool_wrap { | ||
| 842 | height: 44px; | ||
| 843 | padding: 0 16px; | ||
| 844 | border-top: 1px solid #d9d9d9; | ||
| 845 | display: flex; | ||
| 846 | justify-content: center; | ||
| 847 | align-items: center; | ||
| 848 | } | ||
| 849 | |||
| 850 | :deep(.el-table) { | ||
| 851 | td.el-table__cell { | ||
| 852 | padding: 2px 0; | ||
| 853 | height: 36px; | ||
| 854 | |||
| 855 | .el-input .el-input__inner { | ||
| 856 | text-align: right; | ||
| 857 | } | ||
| 858 | } | ||
| 859 | } | ||
| 860 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or sign in to post a comment