diff --git a/.env.development b/.env.development index b59befd..ad65c33 100644 --- a/.env.development +++ b/.env.development @@ -5,7 +5,11 @@ VITE_APP_TITLE = 煤科建管平台 VITE_APP_ENV = 'development' # 开发环境 +<<<<<<< HEAD VITE_APP_BASE_API = 'http://192.168.110.180:8899' +======= +VITE_APP_BASE_API = 'http://192.168.110.149:8899' +>>>>>>> aab67593ebb8d9116738d0d867a6119ba61615c8 # 无人机接口地址 diff --git a/package.json b/package.json index 7053b13..67291cb 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "diagram-js": "12.3.0", "didi": "9.0.2", "echarts": "5.5.0", + "echarts-gl": "^2.0.9", "element-plus": "2.8.8", "esbuild": "^0.25.0", "ezuikit-js": "^8.1.10", diff --git a/src/api/tender/index.ts b/src/api/tender/index.ts new file mode 100644 index 0000000..2ebb22b --- /dev/null +++ b/src/api/tender/index.ts @@ -0,0 +1,44 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; + +//获取版本 +export const obtainAllVersionNumbers = (query: any): AxiosPromise => { + return request({ + url: '/tender/tenderPlanLimitList/obtainAllVersionNumbers', + method: 'get', + params: query + }); +}; +//获取sheet +export const sheetList = (query: any): AxiosPromise => { + return request({ + url: '/tender/tenderPlanLimitList/sheetList', + method: 'get', + params: query + }); +}; +//获取表格数据 +export const getTableList = (query: any): AxiosPromise => { + return request({ + url: '/tender/tenderPlanLimitList/list', + method: 'get', + params: query + }); +}; +//修改单价数据 +export const updatePrice = (query: any): AxiosPromise => { + return request({ + url: '/tender/tenderPlanLimitList', + method: 'put', + data: query + }); +}; +//导入 +export const importExcelFile = (query: any, data: any): AxiosPromise => { + return request({ + url: '/tender/tenderPlanLimitList/importExcelFile', + method: 'post', + params: query, + data + }); +}; diff --git a/src/components/EchartBox/index.vue b/src/components/EchartBox/index.vue new file mode 100644 index 0000000..1725eac --- /dev/null +++ b/src/components/EchartBox/index.vue @@ -0,0 +1,169 @@ + + + + + diff --git a/src/views/contract/division/index.vue b/src/views/contract/division/index.vue index d5ae5b2..bb6c8d0 100644 --- a/src/views/contract/division/index.vue +++ b/src/views/contract/division/index.vue @@ -463,7 +463,16 @@ const getDetails = (row: any) => { } }); }; - +//监听项目id刷新数据 +const listeningProject = watch( + () => currentProject.value?.id, + (nid, oid) => { + getTabsList(); + } +); +onUnmounted(() => { + listeningProject(); +}); onMounted(() => { getTabsList(); }); diff --git a/src/views/largeScreen/components/optionList.ts b/src/views/largeScreen/components/optionList.ts index 7d9486f..b0ba838 100644 --- a/src/views/largeScreen/components/optionList.ts +++ b/src/views/largeScreen/components/optionList.ts @@ -249,9 +249,10 @@ export const getOption2 = (data: any) => { }; return option; }; -//食堂周报图 +//z折线 export const getLineOption = (lineData: any) => { - const maxData = Math.ceil(Math.max(...lineData.line1)); + const maxData = Math.max(...lineData.line1.flat()); + const option = { backgroundColor: '', tooltip: { @@ -263,37 +264,41 @@ export const getLineOption = (lineData: any) => { }, borderColor: '#7ec7ff' }, - // legend: { - // align: 'left', - // right: '5%', - // top: '1%', - // type: 'plain', - // textStyle: { - // color: '#fff', - // fontSize: 12 - // }, - // // icon:'rect', - // itemGap: 15, - // itemWidth: 18, - // data: [ - // { - // name: '上周销售量' - // }, - // { - // name: '本周销售量' - // } - // ] - // }, + legend: { + align: 'left', + right: '5%', + top: '1%', + type: 'plain', + textStyle: { + color: '#fff', + fontSize: 12 + }, + // icon:'rect', + itemGap: 15, + itemWidth: 18, + data: [ + { + name: '收款金额' + }, + { + name: '付款金额' + }, + { + name: '净现金流' + } + ] + }, grid: { top: '12%', left: '1%', right: '3%', - bottom: '12%', + bottom: '5%', containLabel: true }, xAxis: { type: 'category', data: lineData.xLabel, + boundaryGap: false, axisLine: { show: false }, @@ -318,21 +323,21 @@ export const getLineOption = (lineData: any) => { } } }, - dataZoom: [ - { - // show: true, - start: 0, - end: 30, - bottom: 2, // 下滑块距离x轴底部的距离 - height: 23 - }, - { - type: 'inside' - } - ], + // dataZoom: [ + // { + // // show: true, + // start: 0, + // end: 30, + // bottom: 2, // 下滑块距离x轴底部的距离 + // height: 23 + // }, + // { + // type: 'inside' + // } + // ], series: [ { - name: '逆变器功率', + name: '收款金额', type: 'line', symbol: 'circle', // 默认是空心圆(中间是白色的),改成实心圆 showAllSymbol: false, @@ -373,7 +378,95 @@ export const getLineOption = (lineData: any) => { shadowColor: 'rgba(25,163,223, 0.5)', //阴影颜色 shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。 }, - data: lineData.line1 + data: lineData.line1[0] + }, + { + name: '付款金额', + type: 'line', + symbol: 'none', // 默认是空心圆(中间是白色的),改成实心圆 + showAllSymbol: false, + symbolSize: 0, + smooth: true, + lineStyle: { + width: 1, + color: 'rgba(255, 224, 179, 1)', // 线条颜色 + borderColor: 'rgba(0,0,0,.4)' + }, + itemStyle: { + color: 'rgba(255, 224, 179, 1)', + borderWidth: 2, + show: true + }, + tooltip: { + show: true + }, + areaStyle: { + //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。 + color: new echarts.graphic.LinearGradient( + 0, + 0, + 0, + 1, + [ + { + offset: 0, + color: 'rgba(255, 224, 179, 0.4)' + }, + { + offset: 1, + color: 'rgba(255, 224, 179, 0)' + } + ], + false + ), + shadowColor: 'rgba(255, 224, 179, 0.6)', //阴影颜色 + shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。 + }, + data: lineData.line1[1] + }, + { + name: '净现金流', + type: 'line', + symbol: 'none', // 默认是空心圆(中间是白色的),改成实心圆 + showAllSymbol: false, + symbolSize: 0, + smooth: true, + lineStyle: { + width: 1, + color: 'rgba(39, 255, 252, 1)', // 线条颜色 + borderColor: 'rgba(0,0,0,.4)' + }, + itemStyle: { + color: 'rgba(39, 255, 252, 1)', + borderWidth: 2, + show: false + }, + tooltip: { + show: true + }, + areaStyle: { + //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。 + color: new echarts.graphic.LinearGradient( + 0, + 0, + 0, + 1, + [ + { + offset: 0, + color: 'rgba(39, 255, 252, 0.4)' + }, + { + offset: 1, + color: 'rgba(39, 255, 252, 0)' + } + ], + false + ), + shadowColor: 'rgba(39, 255, 252, 0.5)', //阴影颜色 + shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。 + }, + data: lineData.line1[2] } ] }; diff --git a/src/views/largeScreen/components/rightPage.vue b/src/views/largeScreen/components/rightPage.vue index 247c4ce..a87ed17 100644 --- a/src/views/largeScreen/components/rightPage.vue +++ b/src/views/largeScreen/components/rightPage.vue @@ -1,13 +1,71 @@ - + diff --git a/src/views/tender/bidd/index.vue b/src/views/tender/bidd/index.vue new file mode 100644 index 0000000..e32016c --- /dev/null +++ b/src/views/tender/bidd/index.vue @@ -0,0 +1,279 @@ + + + + + diff --git a/src/views/tender/plan/index.vue b/src/views/tender/plan/index.vue index 3302bf8..9ab63c0 100644 --- a/src/views/tender/plan/index.vue +++ b/src/views/tender/plan/index.vue @@ -1,5 +1,6 @@ +======= + 新增 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 一键展开 + + + 一键收起 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>>>>>>> aab67593ebb8d9116738d0d867a6119ba61615c8 @@ -221,6 +360,7 @@ import { PlanVO, PlanQuery, PlanForm } from '@/api/plan/plan/types'; import { getCurrentInstance, onMounted, ref, reactive, toRefs, computed, watch } from 'vue'; import type { ElFormInstance } from 'element-plus'; import { useUserStoreHook } from '@/store/modules/user'; +<<<<<<< HEAD import { UploadFilled } from '@element-plus/icons-vue'; import type { UploadFile, UploadRawFile } from 'element-plus'; import { listByIds } from '@/api/system/oss'; @@ -336,10 +476,81 @@ const getList = async () => { } catch (error) { console.error('获取招标计划列表失败', error); proxy?.$modal.msgError('获取招标计划列表失败'); +======= +import { getDicts } from '@/api/system/dict/data'; +import { Plus } from '@element-plus/icons-vue'; +import { FormInstance } from 'element-plus'; +import { treeList, sheetList, segmentedIndicatorPlanning, getPlanningList, updatePlanning, delPlanning, getDetailsList } from '@/api/contract/index'; + +const userStore = useUserStoreHook(); +const currentProject = computed(() => userStore.selectedProject); +const tabList = ref([]); +const tableData = ref([]); +const queryFormRef = ref(); +const formRef = ref(); +const activeTab = ref(); +const queryParams = ref({ + pageNum: 1, + pageSize: 10 +}); +const total = ref(0); +const queryForm = ref({ + name: '', + content: '' +}); +const dialogVisible = ref(false); +const form = ref({ + name: '', + content: '' +}); + +const rules = ref({ + name: [{ required: true, message: '请输入名称', trigger: 'blur' }], + content: [{ required: true, message: '请输入内容', trigger: 'blur' }] +}); +const loading = ref(false); + +//字典获取数据 +const getTabsList = async () => { + const res = await getDicts('subcontracting_type'); + if (res.code == 200) { + activeTab.value = res.data[0].dictValue; + tabList.value = res.data.map((item: any) => { + return { + label: item.dictLabel, + value: item.dictValue + }; + }); + getList(); + } +}; +//获取表格数据 +const getList = async () => { + try { + loading.value = true; + const params = { + projectId: currentProject.value?.id, + ...queryParams.value, + ...queryForm.value, + dictName: activeTab.value + }; + const res = await getPlanningList(params); + if (res.code == 200) { + tableData.value = res.rows; + total.value = res.total; + } + } catch (error) { + console.log(error); + ElMessage({ + message: '获取数据失败', + type: 'error' + }); +>>>>>>> aab67593ebb8d9116738d0d867a6119ba61615c8 } finally { loading.value = false; } }; +<<<<<<< HEAD // const handleSuccess = (list, res, fileType) => { // console.log(list); @@ -374,6 +585,12 @@ const reset = () => { planFormRef.value?.resetFields(); }; +======= +const handleTabChange = (tabs: any) => { + activeTab.value = tabs; + getList(); +}; +>>>>>>> aab67593ebb8d9116738d0d867a6119ba61615c8 /** 搜索按钮操作 */ const handleQuery = () => { queryParams.value.pageNum = 1; @@ -382,6 +599,7 @@ const handleQuery = () => { /** 重置按钮操作 */ const resetQuery = () => { +<<<<<<< HEAD queryFormRef.value?.resetFields(); queryParams.value.projectId = currentProjectId.value; handleQuery(); @@ -454,10 +672,248 @@ const submitForm = () => { } finally { buttonLoading.value = false; } +======= + queryForm.value.content = ''; + queryForm.value.name = ''; + handleQuery(); +}; + +const openDialog = () => { + dialogVisible.value = true; + getSheetName(); +}; +const closeDialog = () => { + dialogVisible.value = false; + form.value = { + name: '', + content: '' + }; + formRef.value?.resetFields(); +}; +const treeData = ref([]); +const treeForm = ref({ + sheet: '' +}); +const sheets = ref([]); +const treeTableRef = ref(); +const isExpandAll = ref(false); +const treeLoading = ref(false); +const selectionData = ref([]); +//获取表名 +const getSheetName = async () => { + try { + const params = { + projectId: currentProject.value?.id + // versions: queryForm.value.versions + }; + const res = await sheetList(params); + if (res.code == 200) { + sheets.value = res.data; + if (res.data.length > 0) { + treeForm.value.sheet = res.data[0]; + } else { + treeForm.value.sheet = ''; + ElMessage({ + message: '获取表名失败', + type: 'warning' + }); + } + getTreeList(); + } + } catch (error) { + console.log(error); + ElMessage({ + message: '获取表名失败', + type: 'warning' + }); + } +}; +const handleSelection = (selection: any) => { + selectionData.value = selection; +}; +const handleNumberChange = (row: any) => { + const selectedIds = selectionData.value.map((item) => item.id); + nextTick(() => { + treeTableRef.value.toggleRowSelection(row, true); + }); + restoreSelections(treeData.value, selectedIds); +}; + +//寻找节点选择 +const restoreSelections = (data, selectedIds) => { + const traverse = (nodes) => { + nodes.forEach((node) => { + if (selectedIds.includes(node.id)) { + nextTick(() => { + treeTableRef.value.toggleRowSelection(node, true); + }); + } + if (node.children && node.children.length > 0) { + traverse(node.children); + } + }); + }; + traverse(data); +}; +watch( + () => selectionData.value, + (newVal, oldVal) => { + console.log(newVal, 55555555555555555); + } +); + +//选择表名 +const changeSheet = () => { + getTreeList(); +}; + +const toggleExpandAll = (isExpand: boolean) => { + treeData.value.forEach((row) => { + treeTableRef.value.toggleRowExpansion(row, isExpand); + }); + isExpandAll.value = isExpand; +}; +//打开获取表数据 +const getTreeList = async () => { + try { + treeLoading.value = true; + const params = { + projectId: currentProject.value?.id, + sheet: treeForm.value.sheet + }; + const res = await treeList(params); + if (res.code == 200) { + res.data.forEach((item: any) => { + item.selectNum = ''; + }); + treeData.value = res.data; + } + } catch (error) { + console.log(error); + ElMessage({ + message: '获取表格失败', + type: 'error' + }); + } finally { + treeLoading.value = false; + } +}; + +const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + try { + if (selectionData.value.length == 0) { + ElMessage({ + message: '请选择项目材料', + type: 'warning' + }); + return; + } + const newSelectionData = selectionData.value.filter((item) => item.quantity != '' && item.quantity != null); + if (newSelectionData.some((item) => item.selectNum == '' || item.selectNum == null)) { + ElMessage.error('存在未填写数量的工程或费用名称,请检查'); + return; + } + const limitListBos = newSelectionData.map((item: any) => { + return { + limitListId: item.id, + num: item.selectNum + }; + }); + const params = { + projectId: currentProject.value?.id, + ...form.value, + dictName: activeTab.value, + limitListBos, + type: activeTab.value == '2' ? '3' : '2' + }; + return; + const res = await segmentedIndicatorPlanning(params); + if (res.code == 200) { + ElMessage({ + message: '新增成功', + type: 'success' + }); + closeDialog(); + getList(); + } + } catch (error) { + console.log(error); + } + } else { + console.log('error submit!', fields); + } + }); +}; +//确定修改 +const handleSave = (row: any) => { + try { + if (!row.plannedBiddingTime) { + ElMessage({ + message: '请输入计划招标时间', + type: 'warning' + }); + return; + } + updatePlanning(row).then((res) => { + if (res.code == 200) { + ElMessage({ + message: '修改成功', + type: 'success' + }); + getList(); + } + }); + } catch (error) { + console.log(error); + ElMessage({ + message: '修改失败', + type: 'error' + }); + } +}; +//删除 +const delHandle = (row: any) => { + try { + const params = { ids: row.id }; + delPlanning(params).then((res) => { + if (res.code == 200) { + ElMessage({ + message: '删除成功', + type: 'success' + }); + getList(); + } + }); + } catch (error) { + console.log(error); + ElMessage({ + message: '删除失败', + type: 'error' + }); + } +}; +const detailDialog = ref(); +const detailData = ref([]); +const detailLoading = ref(false); + +//详情 +const handleDetail = (row: any) => { + detailDialog.value = true; + getDetails(row); +}; +const getDetails = (row: any) => { + getDetailsList({ id: row.id }).then((res) => { + if (res.code == 200) { + detailData.value = res.data; +>>>>>>> aab67593ebb8d9116738d0d867a6119ba61615c8 } }); }; +<<<<<<< HEAD /** 删除按钮操作(原代码存在但模板未引用,保留逻辑) */ const handleDelete = async (row?: PlanVO) => { const _ids = row?.id || ids.value; @@ -559,10 +1015,15 @@ const handleFileRemove = (file: UploadFile) => { onMounted(() => { getList(); +======= +onMounted(() => { + getTabsList(); +>>>>>>> aab67593ebb8d9116738d0d867a6119ba61615c8 });