123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- <template>
- <div class="hc-layout-box">
- <div class="hc-layout-left-box" id="wbs-left-tree" :style="'width:' + leftWidth + 'px;'">
- <div class="hc-project-box">
- <div class="hc-project-icon-box">
- <HcIcon name="stack"/>
- </div>
- <div class="ml-2 project-name-box">
- <span class="text-xl text-cut project-alias">{{projectInfo['projectAlias']}}</span>
- <div class="text-xs text-cut project-name">{{projectInfo['name']}}</div>
- </div>
- </div>
- <div class="hc-tree-box">
- <div class="hc-search-tree-val">
- <el-input v-model="searchTreeVal" block size="large" placeholder="请输入名称关键词检索" clearable @keyup="searchTreeKeyUp">
- <template #suffix>
- <HcIcon name="search-2" ui="text-xl"/>
- </template>
- </el-input>
- </div>
- <div class="hc-tree-scrollbar" v-loading="treeLoading" element-loading-text="获取数据中...">
- <el-scrollbar>
- <KeepAlive>
- <template v-if="isSearchTree">
- <HcTreeData :datas="searchTreeData" :autoExpandKeys="treeAutoExpandKeys" isColor @nodeTap="wbsElTreeClick"/>
- </template>
- <template v-else>
- <WbsTree :autoExpandKeys="treeAutoExpandKeys" :projectId="projectId" :contractId="contractId" isColor @nodeTap="wbsElTreeClick"/>
- </template>
- </KeepAlive>
- </el-scrollbar>
- </div>
- </div>
- <div class="hc-tree-foot-tip-box">
- <div class="dot-view green">已审批</div>
- <div class="dot-view black">未填报</div>
- <div class="dot-view orange">已填报-待审批</div>
- <div class="dot-view blue">已填报-未上报</div>
- </div>
- <!--左右拖动-->
- <div class="horizontal-drag-line" @mousedown="onmousedown"/>
- </div>
- <div class="hc-layout-content-box">
- <HcCard :scrollbar="false" actionSize="lg">
- <template #header>
- <HcTooltip keys="query_report">
- <el-button type="primary" hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="reportLoading" @click="reportModalClick">
- <HcIcon name="send-plane-2"/>
- <span>上报</span>
- </el-button>
- </HcTooltip>
- <HcTooltip keys="query_download">
- <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="downloadLoading" @click="batchDownload">
- <HcIcon name="download"/>
- <span>下载</span>
- </el-button>
- </HcTooltip>
- <HcTooltip keys="query_print">
- <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="printLoading" @click="batchPrint">
- <HcIcon name="printer"/>
- <span>打印</span>
- </el-button>
- </HcTooltip>
- <HcTooltip keys="query_abolish">
- <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" @click="batchAbolishClick">
- <HcIcon name="delete-bin-3"/>
- <span>废除</span>
- </el-button>
- </HcTooltip>
- <HcTooltip keys="query_local_attestation">
- <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="localLoading" @click="batchLocal">
- <HcIcon name="folder-download"/>
- <span>本地验签</span>
- </el-button>
- </HcTooltip>
- <HcTooltip keys="query_online_attestation">
- <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="onlineLoading" @click="batchOnline">
- <HcIcon name="cloud"/>
- <span>在线验签</span>
- </el-button>
- </HcTooltip>
- </template>
- <template #search>
- <div class="flex items-center">
- <div class="w-40">
- <el-select v-model="searchForm.taskStatus" placeholder="流程状态" clearable>
- <el-option v-for="item in processStatusData" :key="item.value" :label="item['dictValue']" :value="item['dictKey']"/>
- </el-select>
- </div>
- <div class="w-40 ml-2">
- <el-select v-model="searchForm.fileUserIdAndName" placeholder="填报人" clearable>
- <el-option v-for="item in reportingPersonData" :key="item.value" :label="item['label']" :value="item['value']"/>
- </el-select>
- </div>
- <div class="w-40 ml-2">
- <el-select v-model="searchForm.sourceType" placeholder="文件类型" clearable>
- <el-option v-for="item in fileTypeData" :key="item.value" :label="item['dictValue']" :value="item['dictKey']"/>
- </el-select>
- </div>
- <div class="w-32 ml-2">
- <el-select v-model="searchForm.reportNumber" placeholder="上报批次" clearable>
- <el-option v-for="item in reportBatchData" :key="item.value" :label="item['label']" :value="item['value']"/>
- </el-select>
- </div>
- <div class="w-64 ml-2">
- <HcDatePicker :dates="betweenTime" clearable @change="betweenTimeUpdate"/>
- </div>
- <div class="w-60 ml-2">
- <el-input v-model="searchForm.queryValue" placeholder="请输入名称关键词检索" clearable @keyup="keyUpEvent"/>
- </div>
- <div class="ml-2">
- <el-button type="primary" @click="searchClick">
- <HcIcon name="search-2"/>
- <span>搜索</span>
- </el-button>
- </div>
- </div>
- </template>
- <template #extra>
- <template v-if="contractInfo?.contractType === 2 || contractInfo?.contractType === 3">
- <HcNewSwitch :datas="contractTypeTab" :keys="contractTypeTabKey" @change="contractTypeTabChange"/>
- </template>
- </template>
- <HcTable ref="tableListRef" :column="tableListColumn" :datas="tableListData" :loading="tableLoading" isCheck @selection-change="tableSelectionChange">
- <template #name="{row}">
- <span class="text-link" @click="tableRowName(row)">{{row?.name}}</span>
- </template>
- <template #waitingUserList="{row}">
- <template v-for="item in row['waitingUserList']">
- <el-tag :type="`${item.status === 2 ? 'success' : item.status === 3 ? 'warning' : item.status === 999 ? 'danger' : 'info'}`"
- class="mx-1" effect="dark" v-if="item['waitingUserName']">{{item['waitingUserName']}}</el-tag>
- </template>
- </template>
- </HcTable>
- <template #action>
- <div class="lr-dialog-footer">
- <div class="left">
- <span class="text-success">任务人员中:</span>
- <el-tag type="info" class="mx-1" effect="dark">未签字</el-tag>
- <el-tag type="success" class="mx-1" effect="dark">已签字</el-tag>
- <el-tag type="warning" class="mx-1" effect="dark">已废除</el-tag>
- <el-tag type="danger" class="mx-1" effect="dark">签字异常</el-tag>
- </div>
- <div class="right">
- <HcPages :pages="searchForm" @change="pageChange"/>
- </div>
- </div>
- </template>
- </HcCard>
- </div>
- <!--批量上报审批-->
- <HcReportModal title="批量上报审批"
- url="informationWriteQuery/batchTask"
- :show="showReportModal"
- :projectId="projectId"
- :contractId="contractId"
- :taskName="reportTaskName"
- :ids="reportIds"
- isDatas
- :datas="reportDatas"
- @hide="showReportModal = false"
- @finish="showReportFinish"
- @tagClose="reportTaskTagClose"
- />
- </div>
- </template>
- <script setup>
- import {ref, watch, onMounted} from "vue";
- import {useAppStore} from "~src/store";
- import WbsTree from "./components/WbsTree.vue"
- import HcTreeData from "./components/HcTreeData.vue"
- import {getStoreData, setStoreData} from '~src/utils/storage'
- import {isType, downloadBlob} from "vue-utils-plus"
- import queryApi from '~api/data-fill/query';
- import {eVisaTaskCheckApi} from "~api/other"
- //变量
- const useAppState = useAppStore()
- const {getObjValue, getArrValue, isObjNull} = isType()
- const projectId = ref(useAppState.getProjectId);
- const contractId = ref(useAppState.getContractId);
- const projectInfo = ref(useAppState.getProjectInfo);
- const contractInfo = ref(useAppState.getContractInfo);
- const isCollapse = ref(useAppState.getCollapse)
- //监听
- watch(() => [
- useAppState.getCollapse
- ], ([Collapse]) => {
- isCollapse.value = Collapse
- })
- //自动展开缓存
- const treeAutoExpandKeys = ref(getStoreData('wbsTreeExpandKeys') || [])
- //渲染完成
- onMounted(() => {
- getFileUser()
- getReportNumber()
- getFirstTaskStatus()
- getDictBizClassify()
- })
- //树搜索
- const isSearchTree = ref(false)
- const searchTreeVal = ref('')
- const searchTreeData = ref([])
- //回车
- const treeLoading = ref(false)
- const searchTreeKeyUp = (e) => {
- if (e.key === "Enter") {
- searchTreeClick()
- }
- }
- const searchTreeClick = async () => {
- if (searchTreeVal.value) {
- isSearchTree.value = true
- treeLoading.value = true
- const {error, code, data} = await queryApi.searchContractTree({
- contractId: contractId.value,
- queryValue: searchTreeVal.value
- })
- //判断状态
- if (!error && code === 200) {
- searchTreeData.value = getArrValue(data)
- treeLoading.value = false
- } else {
- treeLoading.value = false
- searchTreeData.value = []
- }
- } else {
- treeLoading.value = false
- isSearchTree.value = false
- }
- }
- //树相关的变量
- const primaryKeyId = ref('')
- const nodeItemInfo = ref({})
- const nodeDataInfo = ref({})
- //树被点击
- const wbsElTreeClick = ({node, data, keys}) => {
- nodeItemInfo.value = node
- nodeDataInfo.value = data
- primaryKeyId.value = data['primaryKeyId'] || ''
- //缓存自动展开
- treeAutoExpandKeys.value = keys
- setStoreData('wbsTreeExpandKeys',keys)
- //改变搜索表单数据
- searchForm.value.wbsId = data['primaryKeyId']
- searchForm.value.contractIdRelation = data['contractIdRelation']
- searchForm.value.current = 1;
- getTableData()
- }
- //搜索条件
- const processStatusData = ref([]) //流程状态
- const reportingPersonData = ref([]) //填报人
- const fileTypeData = ref([]) //文件类型
- const reportBatchData = ref([]) //上报批次
- //获取所有填报人
- const getFileUser = async () => {
- const {error, code, data} = await queryApi.getFileUser({
- contractId: contractId.value
- })
- //判断状态
- if (!error && code === 200) {
- let res = getArrValue(data), userArr = [];
- res.forEach(item => {
- userArr.push({label: item['userName'], value: `${item['userId']}-${item['userName']}`})
- })
- reportingPersonData.value = userArr
- } else {
- reportingPersonData.value = []
- }
- }
- //获取上报批次
- const getReportNumber = async () => {
- const {error, code, data} = await queryApi.getReportNumber({
- contractId: contractId.value
- })
- //判断状态
- if (!error && code === 200) {
- reportBatchData.value = getArrValue(data)
- } else {
- reportBatchData.value = []
- }
- }
- //获取流程状态
- const getFirstTaskStatus = async () => {
- const {error, code, data} = await queryApi.getFirstTaskStatus()
- //判断状态
- if (!error && code === 200) {
- processStatusData.value = getArrValue(data)
- } else {
- processStatusData.value = []
- }
- }
- //获取流程状态分类和文件类型分类
- const getDictBizClassify = async () => {
- const {error, code, data} = await queryApi.getDictBizClassify({
- contractId: contractId.value,
- code: 'fileType'
- })
- //判断状态
- if (!error && code === 200) {
- fileTypeData.value = getArrValue(data)
- } else {
- fileTypeData.value = []
- }
- }
- //搜索表单
- const searchForm = ref({
- taskStatus: null, fileUserIdAndName: null, sourceType: null, reportNumber: null, betweenTime: null,
- queryValue: null, contractIdRelation: null, wbsId: null, current: 1, size: 20, total: 0
- })
- //结构类型tab数据和相关处理
- const contractTypeTabKey = ref(1)
- const contractTypeTab = ref([
- {key:'1', name: '施工数据'},
- {key:'2', name: '监理数据'}
- ]);
- const contractTypeTabChange = (item) => {
- contractTypeTabKey.value = item?.key;
- searchClick()
- }
- //获取合同段类型
- const getContractTypeKey = () => {
- const { contractType } = contractInfo.value;
- if (contractType === 2 || contractType === 3) {
- return contractTypeTabKey.value ?? '1'
- } else {
- return null
- }
- }
- //日期时间被选择
- const betweenTime = ref(null)
- const betweenTimeUpdate = ({arr,query}) => {
- betweenTime.value = arr
- searchForm.value.betweenTime = query
- }
- //回车搜索
- const keyUpEvent = (e) => {
- if (e.key === "Enter") {
- searchForm.value.current = 1;
- getTableData()
- }
- }
- //搜索
- const searchClick = () => {
- searchForm.value.current = 1;
- getTableData()
- }
- //分页被点击
- const pageChange = ({current, size}) => {
- searchForm.value.current = current
- searchForm.value.size = size
- getTableData()
- }
- //获取数据
- const tableListRef = ref(null)
- const tableLoading = ref(false)
- const tableListColumn = ref([
- {key:'name', name: '文件名称'},
- {key:'startTime', name: '开始时间'},
- {key:'taskStatusStr', name: '流程状态'},
- {key:'reportNumber', name: '上报批次'},
- {key:'fileUserIdAndName', name: '填报人'},
- {key:'waitingUserList', name: '任务人'}
- ])
- const tableListData = ref([])
- const getTableData = async () => {
- if (!!searchForm.value.wbsId) {
- tableListRef.value?.clearSelection()
- tableCheckedKeys.value = []
- tableLoading.value = true
- const classifyType = getContractTypeKey();
- const { error, code, data } = await queryApi.getPageData({
- projectId: projectId.value,
- contractId: contractId.value,
- ...searchForm.value,
- classifyType: classifyType
- })
- //处理数据
- tableLoading.value = false
- if (!error && code === 200) {
- tableListData.value = getArrValue(data['records'])
- searchForm.value.total = data.total || 0
- } else {
- tableListData.value = []
- searchForm.value.total = 0
- }
- } else {
- window?.$message?.warning('请先选择一个树节点')
- }
- }
- //多选
- const tableCheckedKeys = ref([]);
- const tableSelectionChange = (rows) => {
- tableCheckedKeys.value = rows.filter((item) => {
- return (item??'') !== '';
- })
- }
- //名称被点击
- const tableRowName = (row) => {
- //如果 evisaPdfUrl 不为空,使用evisaPdfUrl,反之使用pdfUrl
- if (row['evisaPdfUrl']) {
- window.open(row['evisaPdfUrl'],'_blank')
- } else if (row['pdfUrl']) {
- window.open(row['pdfUrl'],'_blank')
- } else {
- window.$message?.warning('文件不存在')
- }
- }
- //上报
- const reportIds = ref('')
- const reportTaskName = ref('')
- const reportDatas = ref([])
- const showReportModal = ref(false)
- const reportLoading = ref(false)
- const reportModalClick = async () => {
- const rows = tableCheckedKeys.value;
- //判断是否满足条件
- const result = rows.every(({status})=> {
- return status === 0 || status === 3
- })
- //判断状态
- if (result) {
- reportLoading.value = true
- const taskCheck = await eVisaTaskCheckApi({
- projectId: projectId.value,
- contractId: contractId.value
- })
- if (taskCheck) {
- //初始ID
- const row = getObjValue(rows[0])
- reportIds.value = rowsToId(rows)
- //设置任务数据
- let reportDataArr = []
- rows.forEach(item => {
- reportDataArr.push({
- id: item?.id,
- name: item?.name
- })
- })
- reportDatas.value = reportDataArr
- //设置任务名称
- reportTaskName.value = rows.length > 1 ? `${row.name}等${rows.length}个文件` : row.name
- reportLoading.value = false
- showReportModal.value = true
- } else {
- reportLoading.value = false
- }
- } else {
- window.$message?.warning('已上报的文件不能进行再次上报,若要重新上报,要先撤回之前的上报,再重新上报')
- }
- }
- //上报的审批内容移除
- const reportTaskTagClose = (index) => {
- const row = tableCheckedKeys.value[index];
- tableListRef.value?.toggleRowSelection(row,false)
- }
- //上报完成
- const showReportFinish = () => {
- showReportModal.value = false
- getTableData()
- }
- //下载
- const downloadLoading = ref(false)
- const batchDownload = async () => {
- const rows = tableCheckedKeys.value;
- const ids = rowsToId(rows)
- //批量下载
- downloadLoading.value = true
- const { error, disposition, res } = await queryApi.batchDownloadFileToZip({ids: ids})
- //处理数据
- downloadLoading.value = false
- if (!error) {
- if (disposition) {
- downloadBlob(res,disposition)
- } else {
- window.$message?.error('数据异常')
- }
- }
- }
- //打印
- const printLoading = ref(false)
- const batchPrint = async () => {
- const rows = tableCheckedKeys.value;
- const ids = rowsToId(rows)
- //批量下载
- printLoading.value = true
- const { error, code, data } = await queryApi.batchPrint({ids: ids})
- //处理数据
- printLoading.value = false
- if (!error && code === 200) {
- console.log(data)
- }
- }
- //废除
- const batchAbolishClick = () => {
- const rows = tableCheckedKeys.value;
- //判断是否满足条件
- const result = rows.every(({status})=> {
- return status !== 0 && status !== 3
- })
- //判断状态
- if (result) {
- //拼接ID
- const ids = rowsToId(rows)
- window?.$messageBox?.alert('是否废除勾选的已上报文件?', '废除文件', {
- showCancelButton: true,
- confirmButtonText: '确定废除',
- cancelButtonText: '取消',
- callback: (action) => {
- if (action === 'confirm') {
- batchAbolishSave(ids)
- }
- }
- })
- } else {
- window.$message?.warning('未上报的文件不能废除')
- }
- }
- //废除勾选的已上报文件
- const batchAbolishSave = async (ids) => {
- const { error, code } = await queryApi.batchAbolish({ids: ids})
- //处理数据
- if (!error && code === 200) {
- window.$message?.success('批量废除成功')
- tableCheckedKeys.value = []
- getTableData()
- }
- }
- //本地验签
- const localLoading = ref(false)
- const batchLocal = async () => {
- const rows = tableCheckedKeys.value;
- //判断是否满足条件
- const result = rows.every(({status})=> {
- return status === 2
- })
- //判断状态
- if (result) {
- const ids = rowsToId(rows)
- //请求数据
- localLoading.value = true
- const { error, code, data } = await queryApi.localVerify({
- ids: ids
- })
- //处理数据
- localLoading.value = false
- if (!error && code === 200) {
- console.log(data)
- }
- } else {
- window.$message?.warning('存在未审批或未上报数据')
- }
- }
- //在线验签
- const onlineLoading = ref(false)
- const batchOnline = async () => {
- const rows = tableCheckedKeys.value;
- if (rows.length > 1) {
- window.$message?.warning('在线验签只能勾选一条数据进行验签')
- return;
- }
- if (rows[0].status !== 2) {
- window.$message?.warning('存在未审批或未上报数据')
- return;
- }
- //发起
- onlineLoading.value = true
- const { error, code, data } = await queryApi.onlineVerify({
- ids: rows[0]['id']
- })
- //处理数据
- localLoading.value = false
- if (!error && code === 200) {
- console.log(data)
- }
- }
- //拼接ID
- const rowsToId = (rows) => {
- return rows.map((obj) => {
- return obj.id;
- }).join(",")
- }
- //左右拖动,改变树形结构宽度
- const leftWidth = ref(382);
- const onmousedown = () => {
- const leftNum = isCollapse.value ? 142 : 272
- document.onmousemove = (ve) => {
- let diffVal = ve.clientX - leftNum;
- if(diffVal >= 310 && diffVal <= 900) {
- leftWidth.value = diffVal;
- }
- }
- document.onmouseup = () => {
- document.onmousemove = null;
- document.onmouseup = null;
- }
- }
- </script>
- <style lang="scss" scoped>
- @import "../../styles/data-fill/query.scss";
- </style>
|