优化代码

This commit is contained in:
wcq 2023-09-08 16:41:42 +08:00
parent 7995fbfbec
commit 794bf4b7a5
24 changed files with 6891 additions and 3144 deletions

View File

@ -51,6 +51,7 @@
"mitt": "^3.0.0",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"openapi-fetch": "^0.7.6",
"path": "^0.12.7",
"pinia": "^2.1.4",
"pinyin-pro": "^3.15.2",

View File

@ -67,6 +67,9 @@ dependencies:
nprogress:
specifier: ^0.2.0
version: 0.2.0
openapi-fetch:
specifier: ^0.7.6
version: registry.npmmirror.com/openapi-fetch@0.7.6
path:
specifier: ^0.12.7
version: 0.12.7
@ -7239,6 +7242,20 @@ packages:
version: 2.4.13
dev: false
registry.npmmirror.com/openapi-fetch@0.7.6:
resolution: {integrity: sha512-TmHTmzMqNmVUlRasfaSVsOYnFHHu0L31VGxbk75rk9P7RfOj70kc+Tiuu548koOpB5zs8yiUwW5wsYjeQifHcA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/openapi-fetch/-/openapi-fetch-0.7.6.tgz}
name: openapi-fetch
version: 0.7.6
dependencies:
openapi-typescript-helpers: registry.npmmirror.com/openapi-typescript-helpers@0.0.2
dev: false
registry.npmmirror.com/openapi-typescript-helpers@0.0.2:
resolution: {integrity: sha512-r5Z4tlGa2l6jYO1ENT9Giqo/ZWzWPmsYUR41O01kjYr7vg4iBFaMh0W0g8Ef72SpeU2F+TY6CAdKxTv7aq+WXA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.2.tgz}
name: openapi-typescript-helpers
version: 0.0.2
dev: false
registry.npmmirror.com/picomodal@3.0.0:
resolution: {integrity: sha512-FoR3TDfuLlqUvcEeK5ifpKSVVns6B4BQvc8SDF6THVMuadya6LLtji0QgUDSStw0ZR2J7I6UGi5V2V23rnPWTw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picomodal/-/picomodal-3.0.0.tgz}
name: picomodal

71
src/api/smebiz/apis.ts Normal file
View File

@ -0,0 +1,71 @@
import createClient from "openapi-fetch";
import {paths} from "./schema";
import {formatToken, getToken} from "@/utils/auth";
import {useUserStoreHook} from "@/store/modules/user";
import {FilterKeys, PathsWithMethod} from "openapi-typescript-helpers";
import {FetchOptions} from "openapi-fetch/src";
let timeoutPromise = (timeout: number) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('服务器地址不可用');
}, timeout)
})
};
function createSmebizClient<Paths extends {}>(clientOptions: Parameters<typeof createClient>[0] = {}, timeout?: number) {
const baseClient = createClient<Paths>(clientOptions);
return {
...baseClient,
async post<P extends PathsWithMethod<Paths, "post">>(url: P, body?: FetchOptions<FilterKeys<Paths[P], "post">>['body'], init?: FetchOptions<FilterKeys<Paths[P], "post">>) {
if (!init) init = {} as FetchOptions<FilterKeys<Paths[P], "post">>
if (body) init.body = body
if (!init.headers) init.headers = {}
const data = getToken();
if (data) {
const now = new Date().getTime();
const expired = parseInt(data.expires) - now <= 0;
if (expired) {
useUserStoreHook().logOut();
} else {
init.headers["Authorization"] = formatToken(data.accessToken);
}
}
if (timeout) {
let controller = new AbortController();
init.signal = controller.signal;
setTimeout(() => {
// 当时间到达之后运行 abort
controller.abort();
}, timeout);
}
return baseClient.POST(url, init)
}
}
}
export const sapi = createSmebizClient<paths>({baseUrl: ""}, 10000)
//
// export const sApi = new Proxy(baseClient, {
// get(_, key: keyof typeof baseClient) {
// const headers = {}
// const data = getToken();
// if (data) {
// const now = new Date().getTime();
// const expired = parseInt(data.expires) - now <= 0;
// if (expired) {
// useUserStoreHook().logOut();
// } else {
// headers["Authorization"] = formatToken(data.accessToken);
// }
// }
// const newClient = createClient<paths>({
// headers: headers,
// baseUrl: "",
// });
// return newClient[key];
// },
// });
// sPost('/wd-smebiz/rate/rate_serve/get')

7
src/api/smebiz/index.ts Normal file
View File

@ -0,0 +1,7 @@
import {sapi} from "./apis"
import {components} from "./schema";
type st = components['schemas']
const spost = sapi.post
export {sapi, spost}
export type {st}

4613
src/api/smebiz/schema.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

10
src/utils/format.ts Normal file
View File

@ -0,0 +1,10 @@
import dayjs from "dayjs";
const formatDate = (date, ifNull = '-') => {
return date && dayjs(date).format("YYYY/MM/DD") || ifNull
}
const formatDatetime = (datetime, ifNull = '-') => {
return datetime && dayjs(datetime).format("YYYY/MM/DD HH:mm") || ifNull
}
export {formatDatetime, formatDate}

View File

@ -78,6 +78,7 @@ const dashboardData = ref<DashboardData>({
})
const getData = () => {
return
api.post<any, { data: DashboardData }>('/wd-smebiz/smebiz_rate/company_rate/get_dashboard_data', {}).then(res => {
dashboardData.value = res.data
}).catch(e => {

View File

@ -10,7 +10,7 @@
</div>
<div>
<span>申请时间</span>
<span>{{ rateServe.create_time || emptyText }}</span>
<span>{{ formatDatetime(rateServe.create_time) }}</span>
</div>
<div>
<span>服务编号</span>
@ -18,7 +18,7 @@
</div>
<div>
<span>完成时间</span>
<span>{{ rateServe.finish_time || emptyText }}</span>
<span>{{ formatDatetime(rateServe.finish_time) }}</span>
</div>
</div>
<el-text :type="RateServeStateLevelDic[rateServe.status]" class="rate-serve-state">
@ -38,9 +38,9 @@
<table class="w-full fill-sheet-node-table" style="table-layout: fixed;">
<tr>
<th><span>填报数据</span>
<el-button type="primary" link class="!text-[1rem] ml-1" style="vertical-align:baseline"
@click="showFillSheetUpload">导入
</el-button>
<!-- <el-button type="primary" link class="!text-[1rem] ml-1" style="vertical-align:baseline"-->
<!-- @click="showFillSheetUpload">导入-->
<!-- </el-button>-->
</th>
<th><span>备注</span>
<el-button type="primary" link class="!text-[1rem] ml-1" style="vertical-align:baseline"
@ -53,18 +53,18 @@
<tr>
<td>
<el-button size="small" @click="showOriginFillSheet">原件</el-button>
<el-button type="primary" size="small">审核</el-button>
<el-button type="primary" size="small" @click="showFillSheetDataExamine">审核</el-button>
</td>
<td>
{{rateServe.rate_post_data_check_node?.remark || emptyText}}
{{ rateServe.rate_post_data_check_node?.remark || emptyText }}
</td>
<td>
<el-popconfirm
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认通过?"
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认通过?"
>
<template #reference>
<el-button type="primary" size="small">通过</el-button>
@ -88,10 +88,10 @@
<tr>
<th><span>接口数据</span>
<el-popconfirm
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
title="导入三方接口数据?"
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
title="导入三方接口数据?"
>
<template #reference>
<el-button type="primary" link class="!text-[1rem] ml-1" style="vertical-align:baseline">导入
@ -113,15 +113,15 @@
<el-button type="primary" size="small">审核</el-button>
</td>
<td>
{{rateServe.rate_data_preparation_node?.remark || emptyText}}
{{ rateServe.rate_data_preparation_node?.remark || emptyText }}
</td>
<td>
<el-popconfirm
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认通过?"
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认通过?"
>
<template #reference>
<el-button type="primary" size="small">通过</el-button>
@ -161,11 +161,11 @@
</td>
<td>
<el-popconfirm
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认通过?"
width="220"
confirm-button-text="确定"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认通过?"
>
<template #reference>
<el-button type="primary" size="small">通过</el-button>
@ -244,6 +244,9 @@
</div>
</template>
</el-dialog>
<el-dialog title="填报审核" class="dialog-page" v-model="fillSheetDataExamineVisible">
<sheet-plus :work-book="rateServe.rate_post_data_check_node.data" @save="updateFillSheetData"/>
</el-dialog>
</div>
</el-card>
</template>
@ -258,12 +261,18 @@ import {
import {ref} from "vue";
import {ElMessage} from "element-plus";
import FileUploadMd from "@/components/EditTabel/fileUploadMd.vue";
import dayjs from "dayjs";
import {formatDatetime} from "@/utils/format";
import {sapi, spost} from "@/api/smebiz";
import {downloadByUrl} from "@pureadmin/utils";
import SheetPlus from "@/wcq-components/SheetPlus/SheetPlus.vue";
const prop = defineProps<{ rateServe: RateServe }>()
const emptyText='-'
const emptyText = '-'
const cancelWorkVisible = ref(false)
const deleteWorkVisible = ref(false)
const finishWorkVisible = ref(false)
const fillSheetDataExamineVisible = ref(false)
const cancelRemark = ref('资料审核不通过,请重新申请')
const deleteRemark = ref('该作业已删除')
const finishRemark = ref('资料审核已通过')
@ -323,9 +332,33 @@ const confirmNodeRemarkEdit = () => {
}
const showOriginFillSheet = () => {
window.open('https://view.officeapps.live.com/op/view.aspx?src=newteach.pbworks.com%2Ff%2Fele%2Bnewsletter.docx', '_blank')
spost('/wd-smebiz/rate/rate_post_data_check_node/get', {serve_id: prop.rateServe.serve_id}).then(res => {
prop.rateServe.rate_post_data_check_node = res.data
if (res.data.file?.path) {
const originFillSheetFileUrl = '/wd-smebiz' + res.data.file.path
downloadByUrl(originFillSheetFileUrl, `${prop.rateServe.company.name}-${prop.rateServe.serve_id}-填报原件.xlsx`)
// window.open(`https://view.officeapps.live.com/op/view.aspx?src=${originFillSheetFileUrl}`, '_blank',)
} else {
ElMessage.warning("未上传文件")
}
})
}
const showFillSheetDataExamine = () => {
spost('/wd-smebiz/rate/rate_post_data_check_node/get', {serve_id: prop.rateServe.serve_id}).then(res => {
prop.rateServe.rate_post_data_check_node = res.data
fillSheetDataExamineVisible.value = true
})
}
const updateFillSheetData = () => {
spost('/wd-smebiz/rate/rate_post_data_check_node/update', {serve_id: prop.rateServe.serve_id, data: prop.rateServe.rate_post_data_check_node.data}).then(res => {
prop.rateServe.rate_post_data_check_node = res.data
// fillSheetDataExamineVisible.value = false
ElMessage.success('保存成功')
})
}
</script>
<style lang="scss">
.rate-workflow {

View File

@ -10,7 +10,7 @@
</div>
<div>
<span>申请时间</span>
<span>{{ rateServe.create_time || emptyText}}</span>
<span>{{ formatDatetime(rateServe.create_time) }}</span>
</div>
<div>
<span>服务编号</span>
@ -18,7 +18,7 @@
</div>
<div>
<span>完成时间</span>
<span>{{ rateServe.finish_time || emptyText }}</span>
<span>{{ formatDatetime(rateServe.finish_time) }}</span>
</div>
</div>
<el-text :type="RateServeStateLevelDic[rateServe.status]" class="rate-serve-state">
@ -58,32 +58,32 @@
{{ rateServe.rate_work_node?.rank || emptyText }}
</td>
<td class="font-bold text-2xl">
{{ rateServe.rate_work_node?.scope ? `${rateServe.rate_work_node?.scope}/100` : emptyText}}
{{ rateServe.rate_work_node?.scope ? `${rateServe.rate_work_node?.scope}/100` : emptyText }}
</td>
<td>{{ rateServe.rate_work_node?.rate_time || emptyText}}</td>
<td>{{ formatDatetime(rateServe.rate_work_node?.rate_time) || emptyText }}</td>
<td>
<el-button type="primary" size="small">查看</el-button>
</td>
<td colspan="2">{{ rateServe.rate_work_node?.remark || emptyText}}</td>
<td colspan="2">{{ rateServe.rate_work_node?.remark || emptyText }}</td>
<td>
<el-popconfirm
width="220"
icon-color="#626AEF"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认通过?"
width="220"
icon-color="#626AEF"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认通过?"
>
<template #reference>
<el-button type="primary" size="small">通过</el-button>
</template>
</el-popconfirm>
<el-popconfirm
width="220"
:icon="WarningFilled as any"
:icon-color="'red'"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认重置?"
width="220"
:icon="WarningFilled as any"
:icon-color="'red'"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认重置?"
>
<template #reference>
<el-button type="danger" size="small">重置</el-button>
@ -131,37 +131,37 @@
<el-button type="primary" size="small">下载</el-button>
</td>
<td>
{{ rateServe.report_work_node?.origin_create_time || emptyText}}
{{ formatDatetime(rateServe.report_work_node?.origin_create_time) || emptyText }}
</td>
<td>
<el-button size="small">预览</el-button>
<el-button type="primary" size="small">下载</el-button>
</td>
<td>
{{ rateServe.report_work_node?.final_create_time || emptyText }}
{{ formatDatetime(rateServe.report_work_node?.final_create_time) || emptyText }}
</td>
<td colspan="2">
{{ rateServe.report_work_node?.remark || emptyText}}
{{ rateServe.report_work_node?.remark || emptyText }}
</td>
<td>
<el-popconfirm
width="220"
icon-color="#626AEF"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认通过?"
width="220"
icon-color="#626AEF"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认通过?"
>
<template #reference>
<el-button type="primary" size="small">通过</el-button>
</template>
</el-popconfirm>
<el-popconfirm
width="220"
:icon="WarningFilled as any"
:icon-color="'red'"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认重置?"
width="220"
:icon="WarningFilled as any"
:icon-color="'red'"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认重置?"
>
<template #reference>
<el-button type="danger" size="small">重置</el-button>
@ -206,7 +206,7 @@
<el-button type="primary" size="small">下载</el-button>
</td>
<td>
{{ rateServe.cert_work_node?.create_time || emptyText }}
{{ formatDatetime(rateServe.cert_work_node?.cert_create_time) || emptyText }}
</td>
<td></td>
<td></td>
@ -215,23 +215,23 @@
</td>
<td>
<el-popconfirm
width="220"
icon-color="#626AEF"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认通过?"
width="220"
icon-color="#626AEF"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认通过?"
>
<template #reference>
<el-button type="primary" size="small">通过</el-button>
</template>
</el-popconfirm>
<el-popconfirm
width="220"
:icon="WarningFilled as any"
:icon-color="'red'"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认重置?"
width="220"
:icon="WarningFilled as any"
:icon-color="'red'"
confirm-button-text="确定"
cancel-button-text="取消"
title="确认重置?"
>
<template #reference>
<el-button type="danger" size="small">重置</el-button>
@ -363,9 +363,12 @@ import {ref} from "vue";
import {ElMessage} from "element-plus";
import {WarningFilled, View} from '@element-plus/icons-vue'
import FileUploadMd from "@/components/EditTabel/fileUploadMd.vue";
import dayjs from "dayjs";
import {formatDatetime} from "@/utils/format";
import {st} from "@/api/smebiz";
const prop = defineProps<{ rateServe: RateServe }>()
const emptyText='-'
const prop = defineProps<{ rateServe: st['RateServeInfo'] }>()
const emptyText = '-'
const cancelWorkVisible = ref(false)
const deleteWorkVisible = ref(false)
const finishWorkVisible = ref(false)

View File

@ -11,12 +11,13 @@ import {RateServe} from "@/views/smebiz/types";
import {api} from "@/api/api";
import {ElMessage} from "element-plus";
import {useMultiTagsStoreHook} from "@/store/modules/multiTags";
import {spost, st} from "@/api/smebiz";
defineOptions({
name: "examineWorkPage"
})
const serveId = ref("")
const rateServe = ref<RateServe>({
const rateServe = ref<st['RateServeInfo']>({
serve_id: "", status: "finish"
})
const route = useRoute()
@ -31,77 +32,9 @@ onMounted(() => {
const getData = () => {
rateServe.value =
{
serve_id: "XP2308120617EMHJL",
status: 'examining',
company_id: "QWEQASDASD",
rate_work_node: {
serve_id: "XP2308120617EMHJL",
rank: "AAA",
scope: 99,
status: 'finish',
rate_time: "2023-8-12 16:00"
},
company: {id: "QWEQASDASD", name: "远东资信评估有限公司"},
rate_post_data_check_node: {
serve_id: "XP2308120617EMHJL",
file_id: null,
file: null,
data: null,
parse_data: null,
status: 'incomplete',
remark: '',
create_time: null,
finish_time: null,
},
rate_data_preparation_node: {
serve_id: "XP2308120617EMHJL",
data: {},
status: "incomplete",
remark: "",
rate_time: null,
create_time: null,
finish_time: null
},
cert_work_node: {
serve_id: "XP2308120617EMHJL",
file: null,
file_id: null,
status: "incomplete",
remark: "",
create_time: null,
finish_time: null
},
report_work_node: {
serve_id: "XP2308120617EMHJL",
origin_create_time: null,
origin_file: null,
origin_file_id: null,
final_create_time: null,
final_file: null,
final_file_id: null,
status: "incomplete",
remark: "",
create_time: null,
finish_time: null
},
create_time: "2023-08-12",
finish_time: null
}
// api
// .post("/wd-smebiz/rate/rate_serve/query", exincludeNull(query.value))
// .then(res => {
// data.value = res.data.items;
// count.value = res.data.count;
// })
// .catch(e => {
// console.error(e);
// ElMessage.warning(e.response?.data?.detail || "");
// });
spost('/wd-smebiz/rate/rate_serve/get', {serve_id: serveId.value}).then(res => {
rateServe.value = res.data
})
}
</script>

View File

@ -6,16 +6,16 @@
</div>
<div class="flex">
<el-input
placeholder="请输入公司名称"
size="small"
@change="getData"
v-model="query.company_name"
placeholder="请输入公司名称"
size="small"
@change="getData"
v-model="query.company_name"
/>
<el-button
circle
:icon="Search as any"
class="mx-4"
@click="getData"
circle
:icon="Search as any"
class="mx-4"
@click="getData"
></el-button>
</div>
</div>
@ -29,8 +29,16 @@
</template>
</el-table-column>
<el-table-column prop="rate_work_node.rank" label="信用级别" align="center"/>
<el-table-column prop="create_time" label="申请时间" align="center"/>
<el-table-column prop="finish_time" label="完成时间" align="center"/>
<el-table-column prop="create_time" label="申请时间" align="center">
<template #default="scope:{row:RateServe}">
{{ formatDatetime(scope.row.create_time) }}
</template>
</el-table-column>
<el-table-column prop="finish_time" label="完成时间" align="center">
<template #default="scope:{row:RateServe}">
{{ formatDatetime(scope.row.finish_time) }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="300">
<template #default="scope">
<div class="flex flex-c">
@ -47,9 +55,9 @@
<!-- >作业-->
<!-- </el-button>-->
<el-button
type="primary"
size="small"
@click="showServeWorkPage(scope.row)"
type="primary"
size="small"
@click="showServeWorkPage(scope.row)"
>作业
</el-button>
</div>
@ -58,14 +66,14 @@
</el-table>
<div class="flex justify-center mt-1.5">
<el-pagination
v-model:current-page="query.page"
v-model:page-size="query.page_size"
@size-change="getData"
:page-sizes="[10, 20,30,40]"
:small="false"
layout="total,sizes,prev, pager, next"
:total="count"
@current-change="getData"
v-model:current-page="query.page"
v-model:page-size="query.page_size"
@size-change="getData"
:page-sizes="[10, 20,30,40]"
:small="false"
layout="total,sizes,prev, pager, next"
:total="count"
@current-change="getData"
/>
</div>
<el-dialog title="中小商企评级服务审核" center class="dialog-page" v-model="examinePageVisible">
@ -90,11 +98,14 @@ import ExamineWork from "@/views/smebiz/components/ExamineWork.vue";
import RateWork from "@/views/smebiz/components/RateWork.vue";
import {useRouter} from "vue-router";
import {useMultiTagsStoreHook} from "@/store/modules/multiTags";
import {spost, st} from "@/api/smebiz";
import dayjs from "dayjs";
import {formatDatetime} from "../../utils/format";
defineOptions({
name: "rateServeManage"
})
const data = ref<RateServe[]>([
const data = ref<st['RateServeInfo'][]>([
{
serve_id: "XP2308120617EMHJL",
status: 'examining',
@ -113,7 +124,7 @@ const data = ref<RateServe[]>([
file_id: null,
file: null,
data: null,
parse_data: null,
parsed_data: null,
status: 'incomplete',
remark: '',
create_time: null,
@ -124,7 +135,6 @@ const data = ref<RateServe[]>([
data: {},
status: "incomplete",
remark: "",
rate_time: null,
create_time: null,
finish_time: null
},
@ -172,7 +182,7 @@ const data = ref<RateServe[]>([
file_id: null,
file: null,
data: null,
parse_data: null,
parsed_data: null,
status: 'incomplete',
remark: '',
create_time: null,
@ -183,7 +193,6 @@ const data = ref<RateServe[]>([
data: {},
status: "incomplete",
remark: "",
rate_time: null,
create_time: null,
finish_time: null
},
@ -226,17 +235,21 @@ const rateWorkPageVisible = ref(false)
const selectRow = ref<RateServe | null>(data.value[0])
const previewShow = ref(false)
function exincludeNull(obj: {}) {
function exincludeNull(obj) {
const newVal = {}
Object.keys(obj).forEach(key => {
if (["", null, undefined].indexOf(obj[key]) === -1) {
newVal[key] = obj[key]
}
})
return newVal
return newVal as typeof obj
}
const getData = () => {
spost('/wd-smebiz/rate/rate_serve/query', exincludeNull(query.value)).then(res => {
data.value = res.data.items
count.value = res.data.count
})
return
// api
// .post("/wd-smebiz/rate/rate_serve/query", exincludeNull(query.value))

View File

@ -11,12 +11,13 @@ import {api} from "@/api/api";
import {ElMessage} from "element-plus";
import {useMultiTagsStoreHook} from "@/store/modules/multiTags";
import RateWork from "@/views/smebiz/components/RateWork.vue";
import {spost, st} from "@/api/smebiz";
defineOptions({
name: "rateWorkPage"
})
const serveId = ref("")
const rateServe = ref<RateServe>({
const rateServe = ref<st['RateServeInfo']>({
serve_id: "", status: "finish"
})
const route = useRoute()
@ -31,77 +32,9 @@ onMounted(() => {
const getData = () => {
rateServe.value =
{
serve_id: "XP2308120617EMHJL",
status: 'examining',
company_id: "QWEQASDASD",
rate_work_node: {
serve_id: "XP2308120617EMHJL",
rank: "AAA",
scope: 99,
status: 'finish',
rate_time: "2023-8-12 16:00"
},
company: {id: "QWEQASDASD", name: "远东资信评估有限公司"},
rate_post_data_check_node: {
serve_id: "XP2308120617EMHJL",
file_id: null,
file: null,
data: null,
parse_data: null,
status: 'incomplete',
remark: '',
create_time: null,
finish_time: null,
},
rate_data_preparation_node: {
serve_id: "XP2308120617EMHJL",
data: {},
status: "incomplete",
remark: "",
rate_time: null,
create_time: null,
finish_time: null
},
cert_work_node: {
serve_id: "XP2308120617EMHJL",
file: null,
file_id: null,
status: "incomplete",
remark: "",
create_time: null,
finish_time: null
},
report_work_node: {
serve_id: "XP2308120617EMHJL",
origin_create_time: null,
origin_file: null,
origin_file_id: null,
final_create_time: null,
final_file: null,
final_file_id: null,
status: "incomplete",
remark: "",
create_time: null,
finish_time: null
},
create_time: "2023-08-12",
finish_time: null
}
// api
// .post("/wd-smebiz/rate/rate_serve/query", exincludeNull(query.value))
// .then(res => {
// data.value = res.data.items;
// count.value = res.data.count;
// })
// .catch(e => {
// console.error(e);
// ElMessage.warning(e.response?.data?.detail || "");
// });
spost('/wd-smebiz/rate/rate_serve/get', {serve_id: serveId.value}).then(res => {
rateServe.value = res.data
})
}
</script>

View File

@ -23,13 +23,14 @@ import {RateServe} from "@/views/smebiz/types";
import {ElMessage, TabsPaneContext} from "element-plus";
import RateWork from "@/views/smebiz/components/RateWork.vue";
import ExamineWork from "@/views/smebiz/components/ExamineWork.vue";
import {spost, st} from "@/api/smebiz";
defineOptions({
name: "serveWorkPage"
})
const activeName = ref('examine')
const serveId = ref("")
const rateServe = ref<RateServe>({
const rateServe = ref<st['RateServeInfo']>({
serve_id: "", status: "finish"
})
const route = useRoute()
@ -42,67 +43,9 @@ onMounted(() => {
}
})
const getData = () => {
rateServe.value =
{
serve_id: "XP2308120617EMHJL",
status: 'examining',
company_id: "QWEQASDASD",
rate_work_node: {
serve_id: "XP2308120617EMHJL",
rank: "AAA",
scope: 99,
status: 'finish',
rate_time: "2023-8-12 16:00"
},
company: {id: "QWEQASDASD", name: "远东资信评估有限公司"},
rate_post_data_check_node: {
serve_id: "XP2308120617EMHJL",
file_id: null,
file: null,
data: null,
parse_data: null,
status: 'incomplete',
remark: '',
create_time: null,
finish_time: null,
},
rate_data_preparation_node: {
serve_id: "XP2308120617EMHJL",
data: {},
status: "incomplete",
remark: "",
rate_time: null,
create_time: null,
finish_time: null
},
cert_work_node: {
serve_id: "XP2308120617EMHJL",
file: null,
file_id: null,
status: "incomplete",
remark: "",
create_time: null,
finish_time: null
},
report_work_node: {
serve_id: "XP2308120617EMHJL",
origin_create_time: null,
origin_file: null,
origin_file_id: null,
final_create_time: null,
final_file: null,
final_file_id: null,
status: "incomplete",
remark: "",
create_time: null,
finish_time: null
},
create_time: "2023-08-12",
finish_time: null
}
spost('/wd-smebiz/rate/rate_serve/get', {serve_id: serveId.value}).then(res => {
rateServe.value = res.data
})
}
const handleClick = (tab: TabsPaneContext, event: Event) => {

View File

@ -3,33 +3,33 @@ type NodeState = "incomplete" | "finish"
interface Company {
id: string
name: string
id?: string
name?: string
create_time?: string
update_time?: string
}
interface CompanyUser {
id: string
name: string
id?: string
name?: string
company?: Company
email: string
phone: string
email?: string
phone?: string
passwd?: string
enable: boolean
enable?: boolean
config?: object
company_id: string
create_time: string
company_id?: string
create_time?: string
}
interface RateServe {
serve_id: string
apply_user?: CompanyUser
serve_id?: string
// apply_user?: CompanyUser
apply_user_id?: string
company_id?: string
company?: Company
project?: string
status: RateServeState
status?: RateServeState
create_time?: string
finish_time?: string
status_logs?: RateServeStatusLog[]
@ -41,38 +41,38 @@ interface RateServe {
}
interface UploadFile {
id: string
name: string
path: string
type: string
id?: string
name?: string
path?: string
type?: string
sub_type?: string
user_id?: string
}
interface CertWorkNode {
serve_id: string
serve_id?: string
file_id?: string
file?: UploadFile
status: NodeState
status?: NodeState
remark?: string
create_time?: string
finish_time?: string
}
interface RatePostDataCheckNode {
serve_id: string
serve_id?: string
file_id?: string
file?: UploadFile
data?: any
parse_data?: any
status: NodeState
parsed_data?: any
status?: NodeState
remark?: string
create_time?: string
finish_time?: string
}
interface ReportWorkNode {
serve_id: string
serve_id?: string
origin_file_id?: string
origin_file?: UploadFile
origin_create_time?: string
@ -80,19 +80,19 @@ interface ReportWorkNode {
final_file_id?: string
final_file?: UploadFile
final_create_time?: string
status: NodeState
status?: NodeState
remark?: string
finish_time?: string
}
type RateRank = "AAA" | "AA" | "A" | "B" | "C"
type RateRank = "AAA" | "AA" | "A" | "B" | "C" | string
interface RateWorkNode {
serve_id: string
serve_id?: string
rank?: RateRank
scope?: number
data?: any
status: NodeState
status?: NodeState
remark?: string
rate_time?: string
create_time?: string
@ -100,20 +100,19 @@ interface RateWorkNode {
}
interface RateDataPreparationNode {
serve_id: string
serve_id?: string
data?: any
status: NodeState
status?: NodeState
remark?: string
rate_time?: string
create_time?: string
finish_time?: string
}
interface RateServeStatusLog {
serve_id: string
detail: string
create_time: string
serve_id?: string
detail?: string
create_time?: string
}
export type {

View File

@ -14,7 +14,7 @@
<span class="mr-2 opacity-80" style="font-size: 1rem">编辑</span>
<el-switch v-model="editEnable"></el-switch>
</span>
<el-button size="small" type="primary" class="mx-4">保存</el-button>
<el-button size="small" type="primary" class="mx-4" @click="$emit('save')">保存</el-button>
<div class="inline-flex ml-2">
<span class="ml-auto">数据状态</span>
<div style="font-size: 1rem" class="flex-c">
@ -48,6 +48,7 @@ import {Check, WarningFilled} from "@element-plus/icons-vue";
const active = ref('')
const editEnable = ref(false)
const props = defineProps<{ workBook: WorkBook }>()
const emit=defineEmits(['save'])
onMounted(() => {
active.value = Object.values(props.workBook.sheets)[0].name + '0'
})

View File

@ -1,10 +1,10 @@
<template>
<div style="width: 100%;height: 100%">
<el-table
v-if="sheet"
height="100%"
:span-method="arraySpanMethod"
:data="rowIndexArray" border style="width: 100%">
v-if="sheet"
height="100%"
:span-method="arraySpanMethod"
:data="rowIndexArray" border style="width: 100%">
<el-table-column fixed align="center" label="" width="60">
<template #default="scope">
{{ scope.row }}
@ -35,7 +35,7 @@
</div>
</template>
<script setup lang="ts">
import {onMounted, ref, watch} from "vue";
import {nextTick, onMounted, ref, watch} from "vue";
import {Cell, CellMap, CellSpan, Letter, Sheet} from "../types";
import InputColumn from "@/wcq-components/TablePlus/components/InputColumn/index.vue";
//AZ
@ -60,6 +60,9 @@ function parseSheetConfig(sheet: Sheet) {
columnIndexArray.value = columnIndexArrayTemp
rowIndexArray.value = rowIndexArrayTemp
cellMap.value = sheet.cellMap
nextTick(() => {
cellSpan.value = cellSpanTemp
})
}
@ -79,18 +82,33 @@ function getCellState(cell: Cell) {
function cellStyle({column, columnIndex, row, rowIndex}) {
const key = column.label + row
const state = getCellState(cellMap.value[key])
if(!props.editEnable){
if (!props.editEnable) {
return state ? {} : ({background: '#ff000063'})
}
}
function parseCellSpan(cellMap: CellMap) {
const cellMapCopy = JSON.parse(JSON.stringify(cellMap))
const cellSpan = {}
for (let key in cellMap) {
const item = cellMap[key]
for (let key in cellMapCopy) {
const item = cellMapCopy[key]
if (item.rowSpan === undefined) {
item.rowSpan = 1
}
if (item.colSpan === undefined) {
item.colSpan = 1
}
cellSpan[key] = {
rowSpan: item.rowSpan,
colSpan: item.colSpan,
}
}
for (let key in cellMapCopy) {
const item = cellMapCopy[key]
cellSpan[item] = {
rowSpan: item.rowSpan === undefined ? 1 : item.rowSpan,
colSpan: item.colSpan === undefined ? 1 : item.colSpan
colSpan: item.colSpan === undefined ? 1 : item.colSpan,
}
if (item.rowSpan > 1 || item.colSpan > 1) {
for (let i = 0; i < item.colSpan; i++) {

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ type Letter =
type SheetKey = `${Letter}${number}`
interface Cell {
type: string | 'value' | 'label'
type?: string | 'value' | 'label'
value: any
config?: Column
rowSpan?: number

View File

@ -1,86 +0,0 @@
<template>
<div style="width: 100%;height: 100%;" class="!py-2 overflow-y-hidden">
<div class="h-full w-full">
<el-tabs type="border-card" class="workbook-tab flex flex-col h-full w-full" v-if="workBook" v-model="active">
<el-tab-pane class=" flex-1" style="height: calc(100% - 2rem)"
v-for="(sheet,index) in Object.values(workBook.sheets)"
:label="sheet.name"
:name="sheet.name+index">
<sheet :edit-enable="editEnable" :sheet="sheet"></sheet>
</el-tab-pane>
<div class="my-2 flex">
<div class="ml-auto">
<span class="flex-c inline-flex mx-2">
<span class="mr-2 opacity-80" style="font-size: 1rem">编辑</span>
<el-switch v-model="editEnable"></el-switch>
</span>
<el-button size="small" type="primary" class="mx-4">保存</el-button>
<div class="inline-flex ml-2">
<span class="ml-auto">数据状态</span>
<div style="font-size: 1rem" class="flex-c">
<el-icon
v-if="dataState"
class="mx-2"
style="color: green"
>
<Check
/>
</el-icon>
<el-icon v-else class="mx-2" style="color: red"
>
<WarningFilled
/>
</el-icon>
</div>
</div>
</div>
</div>
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import {onMounted, ref, watch} from "vue";
import {WorkBook} from "./types";
import Sheet from "./components/Sheet.vue";
import {Check, WarningFilled} from "@element-plus/icons-vue";
const active = ref('')
const editEnable = ref(false)
const props = defineProps<{ workBook: WorkBook }>()
onMounted(() => {
active.value = Object.values(props.workBook.sheets)[0].name + '0'
})
const dataState = ref(true)
function checkDataState(workBook: WorkBook) {
if (!workBook.sheets || Object.keys(workBook.sheets).length === 0) {
return true
}
return !(Object.values(workBook.sheets).find(sheet => {
const d = Object.values(sheet.cellMap).find(cell => (cell.config?.required === true) && (['', null, undefined].indexOf(cell.value) !== -1))
if (d) {
console.log(d)
}
return !!d
}
))
}
watch(() => props.workBook, (newVal) => {
dataState.value = checkDataState(newVal)
}, {
immediate: true, deep: true
})
</script>
<style scoped lang="scss">
.workbook-tab {
:deep(.el-tabs__content) {
height: 100%;
}
}
</style>

View File

@ -1,17 +0,0 @@
<template>
<sheet-plus :work-book="workBook"/>
</template>
<script setup lang="ts">
import SheetPlus from "@/wcq-components/SheetPlus/SheetPlus.vue";
import {ref} from "vue";
import {WorkBook} from "@/wcq-components/SheetPlus/types";
import {workBookTestData} from "@/wcq-components/SheetPlus/components/mock";
const workBook = ref<WorkBook>(
workBookTestData
)
</script>
<style scoped lang="scss">
</style>

View File

@ -1,133 +0,0 @@
<template>
<div style="width: 100%;height: 100%">
<el-table
v-if="sheet"
height="100%"
:span-method="arraySpanMethod"
:data="rowIndexArray" border style="width: 100%">
<el-table-column fixed align="center" label="" width="60">
<template #default="scope">
{{ scope.row }}
</template>
</el-table-column>
<el-table-column align="center"
v-for="item in sheet.hiddeCols?columnIndexArray.filter(key=>sheet.hiddeCols?.indexOf(key)===-1):columnIndexArray"
:label="item">
<template #default="scope : {row:number}">
<div>
<div v-if="cellMap[item + scope.row]?.config&& editEnable">
<span class="require-item-sign" v-if="cellMap[item + scope.row]?.config?.required"></span>
<input-column :prop="{style:{width:'100%'},placeholder:''}" :size="'small'" :ctx="{}"
:column="cellMap[item + scope.row].config"
:model-value="cellMap[item + scope.row].value"
@update:model-value="(val)=>cellMap[item+scope.row].value=val"></input-column>
</div>
<div v-else>
<div v-if="getCellState(cellMap[item+scope.row])===false" class="text-red-500">必填</div>
<div v-else>
{{ cellMap[item + scope.row]?.value }}
</div>
</div>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import {onMounted, ref, watch} from "vue";
import {Cell, CellMap, CellSpan, Letter, Sheet} from "../types";
import InputColumn from "@/wcq-components/TablePlus/components/InputColumn/index.vue";
//AZ
const props = defineProps<{ sheet: Sheet, editEnable?: boolean }>()
const cellMap = ref<CellMap>({})
const cellSpan = ref<CellSpan>({})
const columnIndexArray = ref<Letter[]>(['A', "B", "C", "D", "E"])
const rowIndexArray = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
const A2Z = Array(26).fill(0).map((_, i) => String.fromCharCode(65 + i))
watch(() => props.sheet, (newVal) => {
parseSheetConfig(newVal)
}, {immediate: true})
function parseSheetConfig(sheet: Sheet) {
const cellSpanTemp = parseCellSpan(sheet.cellMap)
const {start, end} = sheet
const columnIndexArrayTemp = A2Z.slice(A2Z.indexOf(start[0]), A2Z.indexOf(end[0]) + 1) as unknown as Letter[]
const rowIndexArrayTemp = new Array(1 + Number(end.slice(1)) - Number(start.slice(1))).fill(0).map((_, i) => Number(Number(start.slice(1))) + i)
cellSpan.value = cellSpanTemp
columnIndexArray.value = columnIndexArrayTemp
rowIndexArray.value = rowIndexArrayTemp
cellMap.value = sheet.cellMap
}
function getCellStateClass(cell: Cell) {
return (cell?.config?.required === true) && (['', null, undefined].indexOf(cell?.value) !== -1) ? 'bg-opacity-30 bg-red-500' : ''
}
function getCellState(cell: Cell) {
if (cell?.config?.required === true) {
return (['', null, undefined].indexOf(cell?.value) == -1)
} else {
}
return true
}
function cellStyle({column, columnIndex, row, rowIndex}) {
const key = column.label + row
const state = getCellState(cellMap.value[key])
if(!props.editEnable){
return state ? {} : ({background: '#ff000063'})
}
}
function parseCellSpan(cellMap: CellMap) {
const cellSpan = {}
for (let key in cellMap) {
const item = cellMap[key]
cellSpan[key] = {
rowSpan: item.rowSpan === undefined ? 1 : item.rowSpan,
colSpan: item.colSpan === undefined ? 1 : item.colSpan
}
if (item.rowSpan > 1 || item.colSpan > 1) {
for (let i = 0; i < item.colSpan; i++) {
for (let j = 0; j < item.rowSpan; j++) {
if (i == 0 && j == 0) {
continue
}
cellSpan[A2Z[A2Z.indexOf(key[0]) + i] + (Number(key.slice(1)) + j)] = {
rowSpan: 0,
colSpan: 0
}
}
}
}
}
return cellSpan
}
const arraySpanMethod = ({row, column}) => {
const index = column.label + row
if (cellSpan.value[index]) {
return {
rowspan: cellSpan.value[index].rowSpan,
colspan: cellSpan.value[index].colSpan
}
}
}
onMounted(() => {
})
</script>
<style scoped lang="scss">
.require-item-sign {
transform: translateX(-10px) translateY(4px);
@apply after:content-['*'] after:ml-0.5 after:text-red-500 absolute
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +0,0 @@
import {Column} from "@/wcq-components/TablePlus/types";
type Letter =
'A'
| 'B'
| 'C'
| 'D'
| 'E'
| 'F'
| 'G'
| 'H'
| 'I'
| 'J'
| 'K'
| 'L'
| 'M'
| 'N'
| 'O'
| 'P'
| 'Q'
| 'R'
| 'S'
| 'T'
| 'U'
| 'V'
| 'W'
| 'X'
| 'Y'
| 'Z';
type SheetKey = `${Letter}${number}`
interface Cell {
config?: Partial<Column>
value: any
}
interface CellSpan {
[key: SheetKey]: {
r: number
c: number
}
}
interface CellMap {
[key: SheetKey]: Cell
}
interface Sheet {
name?: string
labels: {
[key: SheetKey]: string
}
spans: CellSpan
values: CellMap
config: {
start: SheetKey
end: SheetKey
hiddeCols?: Letter[]
}
}
interface WorkBook {
sheets: { [key: string]: Sheet }
}
export type {
Letter,
SheetKey,
Cell,
Sheet,
WorkBook,
CellMap,
CellSpan
}

View File

@ -48,7 +48,7 @@ export default ({command, mode}: ConfigEnv): UserConfigExport => {
target: "http://127.0.0.1:8008",
// target: "http://122.9.155.209",
changeOrigin: true
},
}
}
},
plugins: getPluginsList(command, VITE_CDN, VITE_COMPRESSION),