Commit 74a830a3 authored by tanyang's avatar tanyang

Merge remote-tracking branch 'origin/V20231129-中建一局二公司' into V20231129-中建一局二公司

parents 4306bc7a 340af9a4
...@@ -64,7 +64,7 @@ public class CbDirectExpenseController extends BaseController { ...@@ -64,7 +64,7 @@ public class CbDirectExpenseController extends BaseController {
/*** /***
* 删除直接费费用项 * 删除直接费费用项
*/ */
@GetMapping("/deleteExpense/{id}") @DeleteMapping("/deleteExpense/{id}")
public R<Void> deleteExpense(@NotNull(message = "ID不能为空") @PathVariable Long id) { public R<Void> deleteExpense(@NotNull(message = "ID不能为空") @PathVariable Long id) {
return toAjax(baseService.deleteExpense(id)); return toAjax(baseService.deleteExpense(id));
} }
......
...@@ -54,6 +54,15 @@ public class CbQuantitySummaryController extends BaseController { ...@@ -54,6 +54,15 @@ public class CbQuantitySummaryController extends BaseController {
return R.ok(baseService.subjectList(bo)); return R.ok(baseService.subjectList(bo));
} }
/**
* 实体工程材料-单位换算提示
*/
@GetMapping(value = "/conversionNotice")
public R conversionNotice(CbQuantitySummaryListBo bo) {
baseService.conversionNotice(bo);
return R.ok();
}
/** /**
* 更新月成本信息 * 更新月成本信息
*/ */
......
...@@ -30,7 +30,12 @@ public interface CbQuantitySummaryMapper extends BaseMapperPlus<CbQuantitySummar ...@@ -30,7 +30,12 @@ public interface CbQuantitySummaryMapper extends BaseMapperPlus<CbQuantitySummar
List<CbQuantitySummaryListVo> selectListBySubject(CbQuantitySummaryListBo bo); List<CbQuantitySummaryListVo> selectListBySubject(CbQuantitySummaryListBo bo);
/**
* 未换算数据
* @param bo
* @return
*/
List<CbQuantitySummaryListVo> unconvertedList(CbQuantitySummaryListBo bo);
} }
...@@ -278,7 +278,9 @@ public class CbDirectExpenseServiceImpl extends ServiceImpl<CbDirectExpenseMappe ...@@ -278,7 +278,9 @@ public class CbDirectExpenseServiceImpl extends ServiceImpl<CbDirectExpenseMappe
directExpense.setIsImport(false); directExpense.setIsImport(false);
//取编码前两位字母,ZY代表专,LW代表劳,FG代表材 //取编码前两位字母,ZY代表专,LW代表劳,FG代表材
String code = directExpense.getCode().substring(0, 2); String originCode = directExpense.getCode();
Assert.isFalse(originCode.length() < 2, "编码长度不足");
String code = originCode.substring(0, 2);
switch (code) { switch (code) {
case CbProjectConstants.DIRECT_EXPENSE_CODE_ZHUAN: case CbProjectConstants.DIRECT_EXPENSE_CODE_ZHUAN:
directExpense.setExpenseCategoryTag(CbProjectConstants.DIRECT_EXPENSE_CATEGORY_TAG_ZHUAN); directExpense.setExpenseCategoryTag(CbProjectConstants.DIRECT_EXPENSE_CATEGORY_TAG_ZHUAN);
......
...@@ -11,7 +11,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; ...@@ -11,7 +11,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.core.domain.PageQuery; import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.page.TableDataInfo; import com.dsk.common.core.page.TableDataInfo;
import com.dsk.common.exception.ServiceException;
import com.dsk.common.helper.LoginHelper; import com.dsk.common.helper.LoginHelper;
import com.dsk.common.utils.StringUtils; import com.dsk.common.utils.StringUtils;
import com.dsk.component.DataAnalysisComponent; import com.dsk.component.DataAnalysisComponent;
...@@ -25,6 +24,7 @@ import com.dsk.cscec.mapper.CbProjectFileMapper; ...@@ -25,6 +24,7 @@ import com.dsk.cscec.mapper.CbProjectFileMapper;
import com.dsk.cscec.mapper.CbProjectRecordMapper; import com.dsk.cscec.mapper.CbProjectRecordMapper;
import com.dsk.cscec.service.*; import com.dsk.cscec.service.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
...@@ -122,24 +122,7 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe ...@@ -122,24 +122,7 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_SUMMARY, CbProjectConstants.CB_TYPE_SUMMARY_NAME)); projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_SUMMARY, CbProjectConstants.CB_TYPE_SUMMARY_NAME));
//修改文件和项目解析状态为解析中 //修改文件和项目解析状态为解析中
transactionTemplate.execute(status -> { ((CbProjectRecordServiceImpl) AopContext.currentProxy()).editParseStatus(projectRecord, projectFileList);
try {
//修改项目状态:解析中
projectRecord.setProjectFileStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
baseMapper.updateById(projectRecord);
//修改所有该项目的项目文件状态:解析中
CbProjectFileServiceImpl projectFileService = new CbProjectFileServiceImpl();
projectFileService.updateBatchById(projectFileList.stream().peek(projectFile -> {
projectFile.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
projectFile.setFailRemark(null);
}).collect(Collectors.toList()));
} catch (Exception e) {
status.setRollbackOnly();
e.printStackTrace();
throw new ServiceException("解析状态更新出错,请联系系统管理员");
}
return Boolean.TRUE;
});
//调各个成本类型的解析文件方法 //调各个成本类型的解析文件方法
Integer cbStage = projectRecord.getCbStage(); Integer cbStage = projectRecord.getCbStage();
...@@ -162,6 +145,19 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe ...@@ -162,6 +145,19 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe
cbSummaryService.importCbSummary(projectId); cbSummaryService.importCbSummary(projectId);
} }
@Transactional(rollbackFor = Exception.class)
public void editParseStatus(CbProjectRecord projectRecord, List<CbProjectFile> projectFileList) {
//修改项目状态:解析中
projectRecord.setProjectFileStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
baseMapper.updateById(projectRecord);
//修改所有该项目的项目文件状态:解析中
CbProjectFileServiceImpl projectFileService = new CbProjectFileServiceImpl();
projectFileService.updateBatchById(projectFileList.stream().peek(projectFile -> {
projectFile.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
projectFile.setFailRemark(null);
}).collect(Collectors.toList()));
}
/** /**
* 校验各个成本类型是否至少有1个文件 * 校验各个成本类型是否至少有1个文件
* *
......
package com.dsk.cscec.service.impl; package com.dsk.cscec.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.constant.GlobalConstants;
import com.dsk.common.exception.ServiceException; import com.dsk.common.exception.ServiceException;
import com.dsk.common.helper.LoginHelper; import com.dsk.common.helper.LoginHelper;
import com.dsk.common.utils.redis.RedisUtils;
import com.dsk.cscec.domain.CbQuantitySummary; import com.dsk.cscec.domain.CbQuantitySummary;
import com.dsk.cscec.domain.CbQuantitySummaryActual; import com.dsk.cscec.domain.CbQuantitySummaryActual;
import com.dsk.cscec.domain.CbSubject; import com.dsk.cscec.domain.CbSubject;
...@@ -17,6 +26,7 @@ import com.dsk.cscec.mapper.CbSubjectMapper; ...@@ -17,6 +26,7 @@ import com.dsk.cscec.mapper.CbSubjectMapper;
import com.dsk.cscec.service.ICbQuantitySummaryActualService; import com.dsk.cscec.service.ICbQuantitySummaryActualService;
import com.dsk.cscec.service.ICbQuantitySummaryService; import com.dsk.cscec.service.ICbQuantitySummaryService;
import jodd.bean.BeanException; import jodd.bean.BeanException;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -24,10 +34,8 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -24,10 +34,8 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.time.Duration;
import java.util.HashMap; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -145,5 +153,35 @@ public class CbQuantitySummaryServiceImpl extends ServiceImpl<CbQuantitySummaryM ...@@ -145,5 +153,35 @@ public class CbQuantitySummaryServiceImpl extends ServiceImpl<CbQuantitySummaryM
int i = baseMapper.batchInsert(list); int i = baseMapper.batchInsert(list);
return i == list.size(); return i == list.size();
} }
@Override
public void conversionNotice(CbQuantitySummaryListBo bo) {
if (StringUtil.isBlank(bo.getRecordDate())) {
//默认当前月
bo.setRecordDate(DatePattern.SIMPLE_MONTH_FORMAT.format(new Date()));
}
//是否是实体工程材料
CbSubject cbSubject = cbSubjectMapper.selectOne(new LambdaQueryWrapper<CbSubject>().eq(CbSubject::getCbSubjectName, bo.getCbSubjectName()));
if (ObjectUtil.isNull(cbSubject)) {
return;
}
if (cbSubject.getCbSubjectNo().startsWith("FG") || cbSubject.getCbSubjectNo().startsWith("JD")) {
//是否存在未换算数据
List<CbQuantitySummaryListVo> unconvertedList = baseMapper.unconvertedList(bo);
if (CollectionUtil.isEmpty(unconvertedList)) {
return;
}
//是否提示
String key = GlobalConstants.UNIT_CONVERSION_NOTICE + LoginHelper.getUserId() + "_" + bo.getProjectId() + "_" + bo.getCbSubjectName() + "_" + bo.getRecordDate();
if (ObjectUtil.isNull(RedisUtils.getCacheObject(key))) {
Date now = new Date();
long expireTime = DateUtil.between(now, DateUtil.endOfDay(now), DateUnit.SECOND);
RedisUtils.setCacheObject(key, "noticed", Duration.ofSeconds(expireTime));
Assert.isTrue(false, "系统检测到您近期未进行物料单位换算,请立即进行换算。");
}
}
}
} }
...@@ -76,4 +76,21 @@ ...@@ -76,4 +76,21 @@
order by a.`number` asc order by a.`number` asc
</select> </select>
<select id="unconvertedList" resultType="com.dsk.cscec.domain.vo.CbQuantitySummaryListVo">
select
cqs.id, cqs.cb_subject_name, cqs.company_no, cqs.org_no, cqs.cb_name, cqs.job_content, cqs.calculation_rule,
cqs.unit, cqs.material_description, cqs.guide_price, cqs.bid_unit_price, cqs.unit_price_difference, cqs.quantity,
cqs.combined_price, cqs.combined_price_tax, cqs.brand_name, cqs.bid_source, cqs.remark, cqs.`number`, cqsa.quantities,
cqsa.quantities_unit, cqsa.conversion_quantities, cqsa.conversion_unit, cqsa.purchase_unit_price, cqsa.create_time,
cqsa.id actualId, cqsa.ipm_project_code, cqsa.ipm_contract_code, cqsa.ipm_biz_code, cqsa.push_quantities
from cb_quantity_summary cqs
left join cb_quantity_summary_actual cqsa on cqs.id = cqsa.cb_quantity_summary_id
where cqs.del_falg = 0
and cqsa.quantities is not null
and (cqsa.conversion_unit is null or cqsa.conversion_unit = '')
and cqs.project_id = #{projectId}
and cqs.cb_stage = #{cbStage}
and cqsa.record_date = #{recordDate}
and cqs.cb_subject_name = #{cbSubjectName}
</select>
</mapper> </mapper>
\ No newline at end of file
...@@ -4,7 +4,14 @@ ...@@ -4,7 +4,14 @@
:min-width="item.minWidth" :align="item.align?item.align:'left'" :fixed="item.fixed" :min-width="item.minWidth" :align="item.align?item.align:'left'" :fixed="item.fixed"
:sortable="item.sortable ?item.sortable=='custom'? 'custom':true : false" :resizable="false" :show-overflow-tooltip="item.showOverflowTooltip"> :sortable="item.sortable ?item.sortable=='custom'? 'custom':true : false" :resizable="false" :show-overflow-tooltip="item.showOverflowTooltip">
<template v-for="(child,index) of item.children"> <template v-for="(child,index) of item.children">
<table-list-column :key="child.uid ? child.uid : index" :item="child"></table-list-column> <table-list-column :key="child.uid ? child.uid : index" :item="child">
<template v-for="(index, name) in $slots" :slot="name">
<slot :name="name" />
</template>
<template v-for="(index, name) in $scopedSlots" :slot="name" slot-scope="{row,$index}">
<slot :name="name" :data="child" :row="row" :index="$index"></slot>
</template>
</table-list-column>
</template> </template>
</el-table-column> </el-table-column>
<!-- 复选框列 --> <!-- 复选框列 -->
...@@ -18,9 +25,9 @@ ...@@ -18,9 +25,9 @@
<template slot-scope="scope">{{pagingHandler(hasQueryParams,queryParams,scope)}}</template> <template slot-scope="scope">{{pagingHandler(hasQueryParams,queryParams,scope)}}</template>
</el-table-column> </el-table-column>
<!-- 正常列 --> <!-- 正常列 -->
<el-table-column v-else :label="item.label" :prop="item.prop" :width="item.width" :min-width="item.minWidth" :align="item.align?item.align:'left'" <el-table-column v-else :label="item.label" :prop="item.prop" :width="item.width ? item.width : 'auto'" :min-width="item.minWidth"
:fixed="item.fixed" :sortable="item.sortable ?item.sortable=='custom'? 'custom':true : false" :resizable="false" :align="item.align?item.align:'left'" :fixed="item.fixed" :sortable="item.sortable ?item.sortable=='custom'? 'custom':true : false"
:show-overflow-tooltip="item.showOverflowTooltip"> :resizable="false" :show-overflow-tooltip="item.showOverflowTooltip">
<!-- 自定义表头 --> <!-- 自定义表头 -->
<template v-if="item.slotHeader" slot="header"> <template v-if="item.slotHeader" slot="header">
<slot :name="item.slotName"></slot> <slot :name="item.slotName"></slot>
...@@ -28,12 +35,15 @@ ...@@ -28,12 +35,15 @@
<!-- 非自定义表头 --> <!-- 非自定义表头 -->
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 有自定义插槽 --> <!-- 有自定义插槽 -->
<slot v-if="item.slot" :name="item.prop" :row="scope.row" :index="scope.$index" :data="item"></slot> <slot v-if="item.slot" :name="item.prop" :row="scope.row" :index="scope.$index" :data="item">
<!-- 操作栏 --> <!-- 默认取值 -->
{{ scope.row[item.prop] || scope.row[item.prop] == '0' ? scope.row[item.prop] : '-' }}
</slot>
<!-- 操作栏 不需要设置slot-->
<slot v-else-if="item.prop == 'action-field-bar'" name="action-field-bar" :row="scope.row" :index="scope.$index" :data="item"></slot> <slot v-else-if="item.prop == 'action-field-bar'" name="action-field-bar" :row="scope.row" :index="scope.$index" :data="item"></slot>
<!-- 没有插槽 --> <!-- 没有插槽 -->
<div v-else> <div v-else>
{{ scope.row[item.prop] || '-' }} {{ scope.row[item.prop] || scope.row[item.prop] == '0' ? scope.row[item.prop] : '-' }}
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
......
...@@ -13,8 +13,15 @@ ...@@ -13,8 +13,15 @@
</el-table-column> </el-table-column>
<!-- 列二次封装 --> <!-- 列二次封装 -->
<template v-for="(item,index) of formColum"> <template v-for="(item,index) of formColum">
<table-list-column v-if="item.use !== false" :key="item.uid ? item.uid : index" :tableData="tableData" :item="item" <table-list-column v-if="item.use !== false" :key="item.uid ? item.uid : index" :tableData="tableData" :item="item">
:queryParams="queryParams" :hasQueryParams="hasQueryParams"></table-list-column> <!-- 根据透传属性创建插槽 -->
<template v-for="(index, name) in $slots" :slot="name">
<slot :name="name" />
</template>
<template v-for="(index, name) in $scopedSlots" :slot="name" slot-scope="{row,index}">
<slot :name="name" :data="item" :row="row" :index="index"></slot>
</template>
</table-list-column>
</template> </template>
<!-- <template v-for="(item,index) in formColum"> <!-- <template v-for="(item,index) in formColum">
......
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
:style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<logo v-if="showLogo" :collapse="isCollapse" /> <logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper"> <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
<el-menu :default-active="activeMenu" :collapse="isCollapse" :background-color="variables.menuBg" :text-color="variables.menuText" <el-menu :default-active="activeMenu" :default-openeds="comDefaultOpeneds" :collapse="isCollapse" :background-color="variables.menuBg"
:unique-opened="true" :active-text-color="settings.theme" :collapse-transition="false" mode="vertical"> :text-color="variables.menuText" :unique-opened="false" :active-text-color="settings.theme" :collapse-transition="false" mode="vertical">
<sidebar-item v-for="(route, index) in hidechildren" :key="route.path + index" :is-collapse="isCollapse" :active-menu="activeMenu" <sidebar-item v-for="(route, index) of sideBarMenu" :key="route.path + index" :is-collapse="isCollapse" :active-menu="activeMenu"
:item="route" :base-path="route.path" :class="route.fixed&&route.fixed.isFixed?'sideFoot':''" :item="route" :base-path="route.path" :class="route.fixed&&route.fixed.isFixed?'sideFoot':''"
:style="route.fixed&&route.fixed.isFixed?{'bottom': route.fixed.number*50+'px'}: bottomMenu&&index==routes.length-bottomMenu-2?{'padding-bottom': bottomMenu*50+'px'}:''" class="secondary-menu"/> :style="route.fixed&&route.fixed.isFixed?{'bottom': route.fixed.number*50+'px'}: bottomMenu&&index==routes.length-bottomMenu-2?{'padding-bottom': bottomMenu*50+'px'}:''"
class="secondary-menu" />
</el-menu> </el-menu>
</el-scrollbar> </el-scrollbar>
<div v-show="isExpand" class="side-expand" @click="toggleSideBar"> <div v-show="isExpand" class="side-expand" @click="toggleSideBar">
...@@ -21,30 +22,24 @@ import { mapGetters, mapState } from "vuex"; ...@@ -21,30 +22,24 @@ import { mapGetters, mapState } from "vuex";
import Logo from "./Logo"; import Logo from "./Logo";
import SidebarItem from "./SidebarItem"; import SidebarItem from "./SidebarItem";
import variables from "@/assets/styles/variables.scss"; import variables from "@/assets/styles/variables.scss";
import { addTreeLevel } from "@/utils";
import { cloneDeep } from "lodash-es";
import { isExternal } from '@/utils/validate';
import path from 'path';
export default { export default {
components: { SidebarItem, Logo }, components: { SidebarItem, Logo },
data() { data() {
return { return {
isExpand: false isExpand: false,
comDefaultOpeneds: [],
sideBarMenu: []
}; };
}, },
computed: { computed: {
...mapState(["settings"]), ...mapState(["settings"]),
...mapGetters(["sidebarRouters", "sidebar"]), ...mapGetters(["sidebarRouters", "sidebar"]),
hidechildren() {
return this.sidebarRouters.map(item => {
if (item.children?.length) {
item.children = item.children.filter(i => {
if (typeof (i.hidden) == 'boolean' && i.hidden == false || i.path == "index") {
return i;
}
});
}
return item;
});
},
activeMenu() { activeMenu() {
const route = this.$route; const route = this.$route;
const { meta, path } = route; const { meta, path } = route;
...@@ -72,7 +67,83 @@ export default { ...@@ -72,7 +67,83 @@ export default {
return !this.sidebar.opened; return !this.sidebar.opened;
}, },
}, },
watch: {
sidebarRouters: {
handler(newValue) {
const result = this.hidechildren(newValue ? newValue : []);
this.sideBarMenu = result;
this.comDefaultOpeneds = this.findSubMenuIndex(result);
},
deep: true,
immediate: true
},
},
methods: { methods: {
hidechildren(routes = []) {
let temp = cloneDeep(routes);
temp = addTreeLevel(temp);
const result = temp.map(item => {
if (item.children?.length) {
item.children = item.children.filter(i => {
if (typeof (i.hidden) == 'boolean' && i.hidden == false || i.path == "index") {
return i;
}
});
}
return item;
});
return result;
},
findSubMenuIndex(menu) {
let openeds = this.openTargetAllSubMenu(menu);
if (openeds instanceof Array) {
// 去重
openeds = Array.from(new Set(openeds));
}
return openeds;
},
// 展开所有指定层级的菜单 默认二级
openTargetAllSubMenu(_tempTree = [], level = 2) {
// 组件外传入了值 使用传入值,否则默认获取二级菜单打开二级
if (_tempTree instanceof Array && _tempTree.length) {
// 递归查找当前二级目录index
const result = this.findTargetLevelIndex(_tempTree, level, []);
return result;
}
},
findTargetLevelIndex(data = [], level = 2, result = []) {
if (data.length) {
for (const item of data) {
// level大于传入level直接跳出循环
if (item.level > level) break;
// 确保打开菜单为目录
if (item.level <= level && item.children instanceof Array) {
if (item.path) {
const path = this.resolvePath(item.path, item.path);
path ? result.push(path) : null;
}
}
if (item.children instanceof Array && item.children.length) {
this.findTargetLevelIndex(item.children, level, result);
}
}
}
return result.map(item => this.createMenuIndex(item));
},
createMenuIndex(index) {
if (index || index == "0") {
return index.toString();
}
},
resolvePath(routePath, basePath) {
if (isExternal(routePath)) {
return routePath;
}
if (isExternal(basePath)) {
return basePath;
}
return path.resolve(basePath, routePath);
},
toggleSideBar() { toggleSideBar() {
this.$emit('handleBar', this.isCollapse ? '-96' : '96'); // 96为展开宽度和收起宽度之差 this.$emit('handleBar', this.isCollapse ? '-96' : '96'); // 96为展开宽度和收起宽度之差
this.$store.dispatch('app/toggleSideBar'); this.$store.dispatch('app/toggleSideBar');
......
<template> <template>
<div class="directCost-container"> <div class="directCost-container">
<div class="directCost-main"> <div class="directCost-main">
<div class="search"> <!--<div class="search">-->
<el-select v-model="date" placeholder="请选择"> <!--<el-select v-model="date" placeholder="请选择">-->
<el-option v-for="(item,index) in datelist" :label="item.dictLabel" :value="item.dictValue" :key="index"></el-option> <!--<el-option v-for="(item,index) in datelist" :label="item.dictLabel" :value="item.dictValue" :key="index"></el-option>-->
</el-select> <!--</el-select>-->
</div> <!--</div>-->
<div class="directCost-cont"> <div class="directCost-cont">
<div class="left"> <div class="left">
<div class="left-side-menu"> <div class="left-side-menu">
...@@ -79,13 +79,13 @@ ...@@ -79,13 +79,13 @@
<el-input v-model="ruleForm.unit" placeholder="请输入单位"></el-input> <el-input v-model="ruleForm.unit" placeholder="请输入单位"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="招标控制价单价" prop="tenderControlUnitPrice"> <el-form-item label="招标控制价单价" prop="tenderControlUnitPrice">
<el-input v-model="ruleForm.tenderControlUnitPrice" placeholder="请输入招标控制价单价"></el-input> <el-input v-model="ruleForm.tenderControlUnitPrice" oninput="value=value.replace(/[^\d]/g,'')" placeholder="请输入招标控制价单价"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="不含税成本单价" prop="excludeTaxCbUnitPrice"> <el-form-item label="不含税成本单价" prop="excludeTaxCbUnitPrice">
<el-input v-model="ruleForm.excludeTaxCbUnitPrice" placeholder="请输入不含税成本单价"></el-input> <el-input v-model="ruleForm.excludeTaxCbUnitPrice" oninput="value=value.replace(/[^\d]/g,'')" placeholder="请输入不含税成本单价"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="含税成本单价" prop="includeTaxCbUnitPrice"> <el-form-item label="含税成本单价" prop="includeTaxCbUnitPrice">
<el-input v-model="ruleForm.includeTaxCbUnitPrice" placeholder="请输入含税成本单价"></el-input> <el-input v-model="ruleForm.includeTaxCbUnitPrice" oninput="value=value.replace(/[^\d]/g,'')" placeholder="请输入含税成本单价"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="特征描述"> <el-form-item label="特征描述">
<el-input type="textarea" v-model="ruleForm.projectFeature" placeholder="请输入特征描述"></el-input> <el-input type="textarea" v-model="ruleForm.projectFeature" placeholder="请输入特征描述"></el-input>
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible=false">取消</el-button> <el-button @click="dialogVisible=false">取消</el-button>
<el-button type="primary">确定增加</el-button> <el-button type="primary" @click="handleAdd">确定增加</el-button>
</div> </div>
</el-dialog> </el-dialog>
</div> </div>
...@@ -161,13 +161,13 @@ export default { ...@@ -161,13 +161,13 @@ export default {
nodeValue: "menuId", nodeValue: "menuId",
children : "childrenList" children : "childrenList"
}, },
detailsId:'',
}; };
}, },
watch: { watch: {
projectDetailInfo: { projectDetailInfo: {
handler(newValue) { handler(newValue) {
this.comProjectDetailInfo = newValue ? newValue : {}; this.comProjectDetailInfo = newValue ? newValue : {};
this.getCbDirectExpenseMenuTreeApi('1760222923030876161')
this.getCbDirectExpenseList('1763446872284012544') this.getCbDirectExpenseList('1763446872284012544')
// this.getProjectOtherStatistics(this.comProjectDetailInfo.projectId) // this.getProjectOtherStatistics(this.comProjectDetailInfo.projectId)
// this.getProjectOtherStatistics('1762014527685136385') // this.getProjectOtherStatistics('1762014527685136385')
...@@ -185,7 +185,7 @@ export default { ...@@ -185,7 +185,7 @@ export default {
}, },
//可访问data属性 //可访问data属性
created() { created() {
this.getCbDirectExpenseMenuTreeApi('1760222923030876161')
}, },
mounted() { mounted() {
...@@ -203,6 +203,11 @@ export default { ...@@ -203,6 +203,11 @@ export default {
const _tempArray = result.data; const _tempArray = result.data;
this.menuDetails=_tempArray this.menuDetails=_tempArray
this.menuTreeList.push(_tempArray); this.menuTreeList.push(_tempArray);
const defaultCurrent = this.findMenuNode(this.menuTreeList, "土石方部分");
console.log(defaultCurrent)
if (defaultCurrent) {
this.defaultActive = defaultCurrent.menuName;
}
} }
} catch (error) { } catch (error) {
...@@ -210,6 +215,7 @@ export default { ...@@ -210,6 +215,7 @@ export default {
}, },
async getCbDirectExpenseList(params) { async getCbDirectExpenseList(params) {
try { try {
const result = await getCbDirectExpenseList(params); const result = await getCbDirectExpenseList(params);
if (result.code == 200) { if (result.code == 200) {
const _dataArray = result.data; const _dataArray = result.data;
...@@ -232,7 +238,19 @@ export default { ...@@ -232,7 +238,19 @@ export default {
return ''; return '';
}, },
handleDialogVisible(row){ handleDialogVisible(row){
this.dialogVisible=true this.dialogVisible=true;
console.log(row)
this.detailsId=row.id;
},
handleAdd(){
this.ruleForm.qingId = this.detailsId
cbDirectExpenseAdd(JSON.stringify(this.ruleForm)).then(res=>{
if(res.code == 200){
this.dialogVisible = false
this.getCbDirectExpenseList('1763446872284012544')
}
})
}, },
handleDelete(row){ handleDelete(row){
this.$confirm('是否删除费用项?', '提示', { this.$confirm('是否删除费用项?', '提示', {
...@@ -256,6 +274,16 @@ export default { ...@@ -256,6 +274,16 @@ export default {
}); });
}); });
}, },
findMenuNode(tree, nodeName) {
console.log(tree)
for (const item of tree) {
if (item.menuName == nodeName) return item;
if (item.childrenList instanceof Array) {
const result = this.findMenuNode(item.childrenList, nodeName);
if (result) return result;
}
}
},
}, },
} }
</script> </script>
......
...@@ -38,7 +38,11 @@ ...@@ -38,7 +38,11 @@
<dsk-skeleton v-if="tableLoading"></dsk-skeleton> <dsk-skeleton v-if="tableLoading"></dsk-skeleton>
<table-list-com :tableData="tableDataList" :formColum="formColum" v-else-if="!tableLoading" :maxHeight="true" :tableDataTotal="total" <table-list-com :tableData="tableDataList" :formColum="formColum" v-else-if="!tableLoading" :maxHeight="true" :tableDataTotal="total"
:paging="false"> :paging="false">
<template slot="action-field-bar" slot-scope="scope">
<div class="project-action-field-bar">
<span class="push-project">推送工程量</span>
</div>
</template>
</table-list-com> </table-list-com>
</div> </div>
</div> </div>
...@@ -104,7 +108,7 @@ export default { ...@@ -104,7 +108,7 @@ export default {
// 列表表头 // 列表表头
formColum: [ formColum: [
{ label: '序号', prop: "staticSerialNumber", type: "index", lock: true, width: "53", fixed: false, uid: v4() }, { label: '序号', prop: "staticSerialNumber", type: "index", lock: true, width: "53", fixed: false, uid: v4() },
{ label: '成本科目', prop: "cbSubjectName", width: "137", uid: v4() }, { label: '成本科目', prop: "cbSubjectName", width: "137", uid: v4(),slot : true },
{ label: '公司编码', prop: "companyNo", width: "137", uid: v4() }, { label: '公司编码', prop: "companyNo", width: "137", uid: v4() },
{ label: '集团编码', prop: "orgNo", width: "137", uid: v4() }, { label: '集团编码', prop: "orgNo", width: "137", uid: v4() },
{ label: '名称', prop: "cbName", width: "232", uid: v4() }, { label: '名称', prop: "cbName", width: "232", uid: v4() },
...@@ -113,10 +117,28 @@ export default { ...@@ -113,10 +117,28 @@ export default {
{ label: '单位', prop: "unit", width: "57", uid: v4() }, { label: '单位', prop: "unit", width: "57", uid: v4() },
{ label: '甲供材料说明', prop: "materialDescription", width: "137", uid: v4() }, { label: '甲供材料说明', prop: "materialDescription", width: "137", uid: v4() },
{ {
label: '计划成本', prop: "jhcb", width: "809", align: "center", uid: v4(), children: [ label: '计划成本', prop: "jhcb", align: "center", uid: v4(), children: [
{ label: '指导价格', prop: "guidePrice", width: "81", uid: v4() } { label: '指导价格', prop: "guidePrice", minWidth: "81", uid: v4() },
{ label: '投标选用单价(不含税)', prop: "bidUnitPrice", minWidth: "179", uid: v4() },
{ label: '单价差额', prop: "unitPriceDifference", minWidth: "81", uid: v4() },
{ label: '数量', prop: "quantity", minWidth: "53", uid: v4() },
{ label: '合价(不含税)', prop: "combinedPrice", minWidth: "123", uid: v4() },
{ label: '合价(含税)', prop: "combinedPriceTax", minWidth: "109", uid: v4() },
{ label: '品牌名称', prop: "brandName", minWidth: "81", uid: v4() },
{ label: '投标选用来源', prop: "bidSource", minWidth: "109", uid: v4() },
] ]
}, },
{
label: '实际成本', prop: "sjcb", align: "center", uid: v4(), children: [
{ label: '本月工程量', prop: "quantities", minWidth: "95", uid: v4() },
{ label: '截止本月工程量', prop: "totalQuantities", minWidth: "123", uid: v4() },
{ label: '本月采购单价', prop: "purchaseUnitPrice", minWidth: "109", uid: v4() },
{ label: '填写时间', prop: "createTime", minWidth: "109", uid: v4() },
]
},
{ label: '推送工程量', prop: "pushQuantities", width: "95", uid: v4() },
{ label: '备注', prop: "remark", width: "115", uid: v4(), slot: true },
{ label: '操作', prop: "action-field-bar", width: "99", uid: v4() },
], ],
// 已记录月份集合 // 已记录月份集合
monthList: [], monthList: [],
...@@ -415,7 +437,7 @@ export default { ...@@ -415,7 +437,7 @@ export default {
.table-item { .table-item {
.el-table { .el-table {
th { th {
height: 80px; height: 40px;
} }
.cell { .cell {
font-size: 14px; font-size: 14px;
...@@ -424,6 +446,18 @@ export default { ...@@ -424,6 +446,18 @@ export default {
} }
} }
} }
.project-action-field-bar {
display: flex;
align-items: center;
.push-project {
color: #0081ff;
font-size: 14px;
font-weight: 350;
cursor: pointer;
}
}
} }
} }
} }
......
...@@ -277,8 +277,6 @@ export default { ...@@ -277,8 +277,6 @@ export default {
} }
}, },
select(menuPath, menuPathArray){ select(menuPath, menuPathArray){
console.log(menuPath)
console.log(menuPathArray)
this.defaultActive=menuPath; this.defaultActive=menuPath;
let param = { let param = {
projectId:this.comProjectDetailInfo.projectId, projectId:this.comProjectDetailInfo.projectId,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
</div> </div>
</template> </template>
<!-- 子集递归 --> <!-- 子集递归 -->
<project-menu-item v-for="(child,index) of menuItem.children" :menuItem="child" :key="child.nodeValue"></project-menu-item> <project-menu-item v-for="(child,index) of menuItem.children" :menuItem="child" :key="`${child.nodeValue}-${child.level}`"></project-menu-item>
</el-submenu> </el-submenu>
</template> </template>
<!-- 无子集菜单 --> <!-- 无子集菜单 -->
......
<template> <template>
<div class="project-side-menu-container"> <div class="project-side-menu-container">
<el-menu mode="vertical" class="project-side-menu-instance" :unique-opened="uniqueOpened" :default-active="createMenuIndex(comDefaultActive)" <el-menu mode="vertical" class="project-side-menu-instance" :unique-opened="uniqueOpened" :default-active="createMenuIndex(comDefaultActive)"
@select="menuSelect" @open="subMenuOpen" @close="subMenuClose" ref="customElMenu"> :default-openeds="comDefaultOpeneds" @select="menuSelect" @open="subMenuOpen" @close="subMenuClose" ref="customElMenu">
<template v-for="(item,index) of tempMenuTree"> <template v-for="(item,index) of tempMenuTree">
<project-menu-item :menuItem="item" :key="item.nodeValue"> <project-menu-item :menuItem="item" :key="`${item.nodeValue}-${item.level}`">
<template :slot="`${item.nodeName}-${item.level}`" slot-scope="scope"> <template :slot="`${item.nodeName}-${item.level}`" slot-scope="scope">
<slot :name="`${scope.data.nodeName}-${scope.data.level}`" :data="scope.data"></slot> <slot :name="`${scope.data.nodeName}-${scope.data.level}`" :data="scope.data"></slot>
</template> </template>
...@@ -46,6 +46,11 @@ export default { ...@@ -46,6 +46,11 @@ export default {
defaultActive: { defaultActive: {
type: [String, Number], type: [String, Number],
default: "" default: ""
},
// 默认展开的二级菜单
defaultOpeneds: {
type: Array,
default: () => []
} }
}, },
watch: { watch: {
...@@ -61,6 +66,11 @@ export default { ...@@ -61,6 +66,11 @@ export default {
handler(newValue) { handler(newValue) {
this.comDefaultActive = newValue; this.comDefaultActive = newValue;
} }
},
defaultOpeneds: {
handler(newValue) {
this.comDefaultOpeneds = newValue ? newValue : [];
}
} }
}, },
data() { data() {
...@@ -75,12 +85,13 @@ export default { ...@@ -75,12 +85,13 @@ export default {
tempMenuOptions: {}, tempMenuOptions: {},
tempMenuTree: [], tempMenuTree: [],
comMenuTree: this.menuTree, comMenuTree: this.menuTree,
comDefaultActive: this.defaultActive comDefaultActive: this.defaultActive,
comDefaultOpeneds: this.defaultOpeneds
}; };
}, },
//可访问data属性 //可访问data属性
created() { created() {
this.openTargetAllSubMenu(this.comDefaultOpeneds);
}, },
//计算集 //计算集
computed: { computed: {
...@@ -90,6 +101,35 @@ export default { ...@@ -90,6 +101,35 @@ export default {
}, },
//方法集 //方法集
methods: { methods: {
// 展开所有指定层级的菜单 默认二级
openTargetAllSubMenu(openeds = [], level = 2) {
// 组件外传入了值 使用传入值,否则默认获取二级菜单打开二级
if (openeds instanceof Array && openeds.length) {
// 转换为字符串
this.comDefaultOpeneds = openeds.map(item => this.createMenuIndex(item));
} else {
// 递归查找当前二级目录index
const _tempTree = this.tempMenuTree;
const result = this.findTargetLevelIndex(_tempTree, 2, []);
this.comDefaultOpeneds = result;
}
},
findTargetLevelIndex(data = [], level = level, result = []) {
if (data.length) {
for (const item of data) {
// level大于传入level直接跳出循环
if (item.level > level) break;
// 确保打开菜单为目录
if (item.level <= level && item.children instanceof Array) {
result.push(item.nodeValue);
}
if (item.children instanceof Array && item.children.length) {
this.findTargetLevelIndex(item.children, level, result);
}
}
}
return result.map(item => this.createMenuIndex(item));
},
// 事件订阅 // 事件订阅
subMenuOpen(menuPath, menuPathArray) { subMenuOpen(menuPath, menuPathArray) {
this.$emit("open", menuPath, menuPathArray); this.$emit("open", menuPath, menuPathArray);
...@@ -126,7 +166,7 @@ export default { ...@@ -126,7 +166,7 @@ export default {
return null; return null;
}, },
// 初始化树形结构 // 初始化树形结构
initMenuTree(array = []) { async initMenuTree(array = []) {
if (array?.length) { if (array?.length) {
// 合并默认配置 // 合并默认配置
const _options = this.mergeMenuOptions(JSON.parse(JSON.stringify(this.menuOptions))); const _options = this.mergeMenuOptions(JSON.parse(JSON.stringify(this.menuOptions)));
...@@ -135,6 +175,8 @@ export default { ...@@ -135,6 +175,8 @@ export default {
const resultData = this.mapDataByMenuOptions(JSON.parse(JSON.stringify(this.comMenuTree)), _options); const resultData = this.mapDataByMenuOptions(JSON.parse(JSON.stringify(this.comMenuTree)), _options);
if (resultData) { if (resultData) {
this.tempMenuTree = resultData; this.tempMenuTree = resultData;
await this.$nextTick();
this.openTargetAllSubMenu(this.comDefaultOpeneds);
} }
} }
}, },
......
<template>
<div class="app-container enterprise_contatiner">
<!--<div class="header">-->
<!--<div class="title_wrap">-->
<!--<div class="enterprise_title">-->
<!--评标助手-->
<!--</div>-->
<!--</div>-->
<!--<el-tabs v-model="activeName" >-->
<!--<el-tab-pane label="查资质" name="first"></el-tab-pane>-->
<!--<el-tab-pane label="现行资质标准" name="second"></el-tab-pane>-->
<!--<el-tab-pane label="历史批量查询结果" name="third"></el-tab-pane>-->
<!--</el-tabs>-->
<!--</div>-->
<!--<SearchAptitude @changeActiveName="activeName = 'third'" v-if="activeName === 'first'"></SearchAptitude>-->
<AptitudeStandard></AptitudeStandard>
<!--<SearchResult v-if="activeName === 'third'"></SearchResult>-->
</div>
</template>
<script>
import AptitudeStandard from '../components/AptitudeStandard'
export default {
name: 'AptitudeStandard',
components: {
AptitudeStandard
},
data() {
return {
activeName: 'first'
}
},
}
</script>
<style lang="scss" scoped>
.header{
justify-content: space-between;
background: #FFFFFF;
border-radius: 4px 4px 0 0 ;
border-bottom: 1px solid #EEEEEE;
color: #232323;
position: sticky;
top: -16px;
z-index: 999;
::v-deep .el-tabs{
height: 48px;
line-height: 48px;
.el-tabs__nav-wrap::after {
position: static !important;
}
.el-tabs__header{
margin: 0;
.el-tabs__item{
padding: 0 16px;
font-size: 16px;
}
.is-active{
font-weight: bold;
}
}
.el-tabs__content{
width: 100%;
}
}
.location{
font-size: 14px;
color: #0081FF;
i{
margin-right: 6px;
font-size: 16px;
}
}
}
</style>
<template>
<div class="app-container enterprise_contatiner">
<!--<div class="header">-->
<!--<div class="title_wrap">-->
<!--<div class="enterprise_title">-->
<!--评标助手-->
<!--</div>-->
<!--</div>-->
<!--<el-tabs v-model="activeName" >-->
<!--<el-tab-pane label="查资质" name="first"></el-tab-pane>-->
<!--<el-tab-pane label="现行资质标准" name="second"></el-tab-pane>-->
<!--<el-tab-pane label="历史批量查询结果" name="third"></el-tab-pane>-->
<!--</el-tabs>-->
<!--</div>-->
<SearchAptitude @changeActiveName="activeName = 'third'" v-if="activeName === 'first'"></SearchAptitude>
<!--<AptitudeStandard v-if="activeName === 'second'"></AptitudeStandard>-->
<!--<SearchResult v-if="activeName === 'third'"></SearchResult>-->
</div>
</template>
<script>
import SearchAptitude from '../components/SearchAptitude'
export default {
name: 'SearchAptitude',
components: {
SearchAptitude
},
data() {
return {
activeName: 'first'
}
},
}
</script>
<style lang="scss" scoped>
.header{
justify-content: space-between;
background: #FFFFFF;
border-radius: 4px 4px 0 0 ;
border-bottom: 1px solid #EEEEEE;
color: #232323;
position: sticky;
top: -16px;
z-index: 999;
::v-deep .el-tabs{
height: 48px;
line-height: 48px;
.el-tabs__nav-wrap::after {
position: static !important;
}
.el-tabs__header{
margin: 0;
.el-tabs__item{
padding: 0 16px;
font-size: 16px;
}
.is-active{
font-weight: bold;
}
}
.el-tabs__content{
width: 100%;
}
}
.location{
font-size: 14px;
color: #0081FF;
i{
margin-right: 6px;
font-size: 16px;
}
}
}
</style>
<template>
<div class="app-container enterprise_contatiner">
<!--<div class="header">-->
<!--<div class="title_wrap">-->
<!--<div class="enterprise_title">-->
<!--评标助手-->
<!--</div>-->
<!--</div>-->
<!--<el-tabs v-model="activeName" >-->
<!--<el-tab-pane label="查资质" name="first"></el-tab-pane>-->
<!--<el-tab-pane label="现行资质标准" name="second"></el-tab-pane>-->
<!--<el-tab-pane label="历史批量查询结果" name="third"></el-tab-pane>-->
<!--</el-tabs>-->
<!--</div>-->
<!--<SearchAptitude @changeActiveName="activeName = 'third'" v-if="activeName === 'first'"></SearchAptitude>-->
<!--<AptitudeStandard></AptitudeStandard>-->
<SearchResult></SearchResult>
</div>
</template>
<script>
import SearchResult from '../components/SearchResult'
export default {
name: 'SearchAptitude',
components: {
SearchResult
},
data() {
return {
activeName: 'first'
}
},
}
</script>
<style lang="scss" scoped>
.header{
justify-content: space-between;
background: #FFFFFF;
border-radius: 4px 4px 0 0 ;
border-bottom: 1px solid #EEEEEE;
color: #232323;
position: sticky;
top: -16px;
z-index: 999;
::v-deep .el-tabs{
height: 48px;
line-height: 48px;
.el-tabs__nav-wrap::after {
position: static !important;
}
.el-tabs__header{
margin: 0;
.el-tabs__item{
padding: 0 16px;
font-size: 16px;
}
.is-active{
font-weight: bold;
}
}
.el-tabs__content{
width: 100%;
}
}
.location{
font-size: 14px;
color: #0081FF;
i{
margin-right: 6px;
font-size: 16px;
}
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment