合并
This commit is contained in:
@ -58,18 +58,18 @@
|
||||
<el-card shadow="never" class="mb8">
|
||||
<el-table ref="tableRef" v-loading="loading" :data="tableData" row-key="id" border lazy default-expand-all>
|
||||
<el-table-column prop="num" label="编号" />
|
||||
<el-table-column prop="name" label="工程或费用名称" />
|
||||
<el-table-column prop="name" label="工程或费用名称" />
|
||||
<el-table-column prop="unit" label="单位" align="center" />
|
||||
<el-table-column prop="quantity" label="数量" align="center" />
|
||||
<el-table-column prop="specification" label="规格" align="center" />
|
||||
<el-table-column prop="remark" label="单价" align="center">
|
||||
<el-table-column label="单价" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.unitPrice }}</span>
|
||||
{{ proxy.formatPrice(scope.row.unitPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price }}
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="price" label="操作" align="center">
|
||||
@ -92,7 +92,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { BiddingImportExcelFile, getTreeLimit, biddingLimitListUpdate, sheetList, obtainAllVersionNumbers } from '@/api/bidding/biddingLimit';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
|
||||
const userStore = useUserStoreHook();
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
|
@ -77,8 +77,8 @@
|
||||
changePrice(scope.row);
|
||||
}
|
||||
"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
:min="0"
|
||||
:precision="4"
|
||||
:controls="false"
|
||||
v-if="scope.row.quantity && scope.row.quantity != 0"
|
||||
/>
|
||||
@ -86,7 +86,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operate" label="操作" align="center">
|
||||
|
@ -25,7 +25,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="名称" align="center" />
|
||||
<el-table-column prop="content" label="内容" align="center" />
|
||||
<el-table-column prop="price" label="限价" align="center" />
|
||||
<el-table-column prop="price" label="限价" align="center">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="plannedBiddingTime" align="center">
|
||||
<template #header> <span style="color: red">*</span>计划招标时间 </template>
|
||||
<template #default="scope">
|
||||
@ -158,22 +162,28 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="unitPrice" label="单价" align="center" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.unitPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{
|
||||
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice) ==
|
||||
0
|
||||
? ''
|
||||
: (
|
||||
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
proxy.formatPrice(
|
||||
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice) ==
|
||||
0
|
||||
? ''
|
||||
: ((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice)
|
||||
).toFixed(2)
|
||||
Number(scope.row.unitPrice),
|
||||
false
|
||||
)
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -207,6 +217,7 @@ import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { getDicts } from '@/api/system/dict/data';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
const { proxy } = getCurrentInstance();
|
||||
import {
|
||||
treeList,
|
||||
sheetList,
|
||||
|
@ -79,18 +79,16 @@
|
||||
changePrice(scope.row);
|
||||
}
|
||||
"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
:min="0"
|
||||
:precision="4"
|
||||
:controls="false"
|
||||
v-if="scope.row.quantity && scope.row.quantity != 0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center" >
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
<!-- {{ scope.row.children.length > 0 ? scope.row.children.reduce((sum, child) => sum + child.price, 0) : scope.row.price }} -->
|
||||
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
|
||||
<!-- {{ scope.row.price }} -->
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operate" label="操作" align="center">
|
||||
|
@ -41,10 +41,14 @@
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center" />
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<el-table-column prop="unitPrice" label="单价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
|
||||
{{ proxy.formatPrice(scope.row.unitPrice, false) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center" width="150">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -70,8 +74,12 @@
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer p-4 border-t border-gray-100 flex justify-end space-x-3">
|
||||
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors">取消</el-button>
|
||||
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors">确认</el-button>
|
||||
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
|
||||
>确认</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
@ -1,54 +1,19 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<el-tabs type="border-card" v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="变更单" name="1"
|
||||
><el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAddApp" v-hasPermi="['quality:qualityInspection:add']"
|
||||
>上传变更单模版</el-button
|
||||
>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<EngineeringChangeApplicationForm
|
||||
@selection-change="handleSelectionChange"
|
||||
:data="tableData"
|
||||
:thumbnail="projectTypeOptions[1].thumbnail"
|
||||
@delete="handleDelete"
|
||||
></EngineeringChangeApplicationForm>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/> </el-card
|
||||
></el-tab-pane>
|
||||
<el-tab-pane label="外部联系单" name="0"
|
||||
><el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAdd" v-hasPermi="['quality:qualityInspection:add']"
|
||||
>上传外部联系单模版</el-button
|
||||
>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<Contactform @selection-change="handleSelectionChange" :data="tableData" @delete="handleDelete"></Contactform>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/> </el-card
|
||||
></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAdd" v-hasPermi="['quality:qualityInspection:add']"
|
||||
>上传外部联系单模版</el-button
|
||||
>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<Contactform @selection-change="handleSelectionChange" :data="tableData" @delete="handleDelete"></Contactform>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
<el-dialog title="新增模板" v-model="dialogVisible" width="800">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="110px">
|
||||
<div class="flex">
|
||||
@ -109,14 +74,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import type { FormInstance } from 'element-plus';
|
||||
import Contactform from './components/contactform.vue';
|
||||
import EngineeringChangeApplicationForm from './components/engineeringChangeApplicationForm.vue';
|
||||
import { listContactTypeformtemplate } from '@/api/cory/contactformtemplate';
|
||||
import { addContactnotice, delContactnotice, listContactnotice } from '@/api/cory/contactnotice';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wf_business_status } = toRefs(proxy?.useDict('wf_business_status'));
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
|
@ -1,79 +1,80 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<el-steps style="max-width: 100%" :active="active" finish-status="success" align-center>
|
||||
<el-step title="选择合同类型" />
|
||||
<el-step title="修改合同内容" />
|
||||
<el-step title="修改收款方式" />
|
||||
</el-steps>
|
||||
<div class="content">
|
||||
<template v-if="active == 1">
|
||||
<h1>修改收入合同</h1>
|
||||
<el-form ref="incomeContractFormRef" :model="form" :rules="incomeContractFormRules" label-width="80px">
|
||||
<el-form-item label="合同编号" prop="contractCode">
|
||||
<el-input v-model="form.contractCode" placeholder="请输入合同编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同类型" prop="contractType">
|
||||
<el-select v-model="form.contractType" placeholder="请选择合同类型">
|
||||
<el-option v-for="item in income_contract_type" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="业主单位" prop="contractOwner">
|
||||
<el-input v-model="form.contractOwner" placeholder="请输入业主单位" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="承包内容" v-if="contract_type !== 'income'">
|
||||
<editor v-model="form.contractedContent" :min-height="192" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同内容" v-else>
|
||||
<editor v-model="form.contractedContent" :min-height="192" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同金额" prop="amount">
|
||||
<el-input v-model="form.amount" placeholder="请输入合同金额"
|
||||
oninput="value=value.replace(/[^0-9.]/g,'').replace(/\.{2,}/g,'.').replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件">
|
||||
<FileUpload :multiple="true" :fileType="['pdf']" :onUploadSuccess="onUploadSuccess"
|
||||
:ref="fileRef" :defaultFileList="tempFileList" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div>
|
||||
<el-button type="primary" @click="next">下一步</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="active == 2">
|
||||
<h1>修改收入合同</h1>
|
||||
<el-form :model="form" :rules="payMentRules" label-width="150" ref="payMentRef">
|
||||
<el-form-item label="支付方式" placeholder="请选择支付方式" prop="payType">
|
||||
<el-select v-model="form.payType">
|
||||
<el-option :value="1" label="月结算">月结算</el-option>
|
||||
<el-option :value="2" label="形象节点">形象节点</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="预付款比例(%)" prop="advancePayRatio">
|
||||
<el-input-number v-model="form.advancePayRatio" :max="100" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="尾款比例(%)" prop="balancePayRatio">
|
||||
<el-input-number v-model="form.balancePayRatio" :max="100" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="质保金比例(%)" prop="assuranceDepositRatio">
|
||||
<el-input-number v-model="form.assuranceDepositRatio" :max="100" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="付款比例(%)" prop="payRatio">
|
||||
<el-input-number v-model="payRatioComputed" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div>
|
||||
<el-button @click="back(false)">上一步</el-button>
|
||||
<el-button type="success" @click="submitForm">提交</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<div class="container">
|
||||
<el-steps style="max-width: 100%" :active="active" finish-status="success" align-center>
|
||||
<el-step title="选择合同类型" />
|
||||
<el-step title="修改合同内容" />
|
||||
<el-step title="修改收款方式" />
|
||||
</el-steps>
|
||||
<div class="content">
|
||||
<template v-if="active == 1">
|
||||
<h1>修改收入合同</h1>
|
||||
<el-form ref="incomeContractFormRef" :model="form" :rules="incomeContractFormRules" label-width="80px">
|
||||
<el-form-item label="合同编号" prop="contractCode">
|
||||
<el-input v-model="form.contractCode" placeholder="请输入合同编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同类型" prop="contractType">
|
||||
<el-select v-model="form.contractType" placeholder="请选择合同类型">
|
||||
<el-option v-for="item in income_contract_type" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="业主单位" prop="contractOwner">
|
||||
<el-input v-model="form.contractOwner" placeholder="请输入业主单位" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="承包内容" v-if="contract_type !== 'income'">
|
||||
<editor v-model="form.contractedContent" :min-height="192" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同内容" v-else>
|
||||
<editor v-model="form.contractedContent" :min-height="192" />
|
||||
</el-form-item>
|
||||
<el-form-item label="合同金额" prop="amount">
|
||||
<el-input
|
||||
v-model="form.amount"
|
||||
placeholder="请输入合同金额"
|
||||
oninput="value=value.replace(/[^0-9.]/g,'').replace(/\.{2,}/g,'.').replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件">
|
||||
<FileUpload :multiple="true" :fileType="['pdf']" :onUploadSuccess="onUploadSuccess" :ref="fileRef" :defaultFileList="tempFileList" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div>
|
||||
<el-button type="primary" @click="next">下一步</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="active == 2">
|
||||
<h1>修改收入合同</h1>
|
||||
<el-form :model="form" :rules="payMentRules" label-width="150" ref="payMentRef">
|
||||
<el-form-item label="支付方式" placeholder="请选择支付方式" prop="payType">
|
||||
<el-select v-model="form.payType">
|
||||
<el-option :value="1" label="月结算">月结算</el-option>
|
||||
<el-option :value="2" label="形象节点">形象节点</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="预付款比例(%)" prop="advancePayRatio">
|
||||
<el-input-number v-model="form.advancePayRatio" :max="100" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="尾款比例(%)" prop="balancePayRatio">
|
||||
<el-input-number v-model="form.balancePayRatio" :max="100" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="质保金比例(%)" prop="assuranceDepositRatio">
|
||||
<el-input-number v-model="form.assuranceDepositRatio" :max="100" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="付款比例(%)" prop="payRatio">
|
||||
<el-input-number v-model="payRatioComputed" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div>
|
||||
<el-button @click="back(false)">上一步</el-button>
|
||||
<el-button type="success" @click="submitForm">提交</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
@ -95,140 +96,140 @@ const incomeContractFormRef = ref(null);
|
||||
const expensesContractFormRef = ref(null);
|
||||
const payMentRef = ref(null);
|
||||
const incomeContractFormRules = {
|
||||
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
|
||||
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
|
||||
contractOwner: [{ required: true, message: '请输入业主单位', trigger: 'blur' }],
|
||||
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
|
||||
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
|
||||
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
|
||||
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
|
||||
contractOwner: [{ required: true, message: '请输入业主单位', trigger: 'blur' }],
|
||||
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
|
||||
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
|
||||
};
|
||||
const expensesContractFormRules = {
|
||||
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
|
||||
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
|
||||
contractCode: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
|
||||
contractType: [{ required: true, message: '请选择合同类型', trigger: 'change' }],
|
||||
|
||||
contractSupplier: [{ required: true, message: '请输入供应商', trigger: 'blur' }],
|
||||
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
|
||||
tenderId: [{ required: true, message: '请选择招标计划', trigger: 'blur' }],
|
||||
contractSupplier: [{ required: true, message: '请输入供应商', trigger: 'blur' }],
|
||||
amount: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
|
||||
tenderId: [{ required: true, message: '请选择招标计划', trigger: 'blur' }],
|
||||
|
||||
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
|
||||
remark: [{ required: false, message: '请输入备注', trigger: 'blur' }]
|
||||
};
|
||||
const payMentRules = {
|
||||
payType: [{ required: true, message: '请选择支付方式', trigger: 'change' }],
|
||||
advancePayRatio: [{ required: true, message: '请输入预付款比例', trigger: 'blur' }],
|
||||
balancePayRatio: [{ required: true, message: '请输入尾款比例', trigger: 'blur' }],
|
||||
assuranceDepositRatio: [{ required: true, message: '请输入质保金比例', trigger: 'blur' }]
|
||||
payType: [{ required: true, message: '请选择支付方式', trigger: 'change' }],
|
||||
advancePayRatio: [{ required: true, message: '请输入预付款比例', trigger: 'blur' }],
|
||||
balancePayRatio: [{ required: true, message: '请输入尾款比例', trigger: 'blur' }],
|
||||
assuranceDepositRatio: [{ required: true, message: '请输入质保金比例', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
const project = computed(() => {
|
||||
return JSON.parse(localStorage.getItem('selectedProject'));
|
||||
return JSON.parse(localStorage.getItem('selectedProject'));
|
||||
});
|
||||
|
||||
const payRatioComputed = computed({
|
||||
get: () => {
|
||||
const { advancePayRatio = 0, balancePayRatio = 0, assuranceDepositRatio = 0 } = form.value;
|
||||
const total = 100 - (advancePayRatio + balancePayRatio + assuranceDepositRatio);
|
||||
// form.value.payRatio = total;
|
||||
return total;
|
||||
},
|
||||
// 只读
|
||||
set: () => { }
|
||||
get: () => {
|
||||
const { advancePayRatio = 0, balancePayRatio = 0, assuranceDepositRatio = 0 } = form.value;
|
||||
const total = 100 - (advancePayRatio + balancePayRatio + assuranceDepositRatio);
|
||||
// form.value.payRatio = total;
|
||||
return total;
|
||||
},
|
||||
// 只读
|
||||
set: () => {}
|
||||
});
|
||||
|
||||
const onUploadSuccess = (data) => {
|
||||
fileList.value = data;
|
||||
fileList.value = data;
|
||||
};
|
||||
|
||||
const next = async () => {
|
||||
if (contract_type.value === 'income') {
|
||||
await incomeContractFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
active.value++;
|
||||
} else {
|
||||
ElMessage.error('请填写完整的收入合同信息');
|
||||
}
|
||||
});
|
||||
} else if (contract_type.value === 'expenses') {
|
||||
await expensesContractFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
active.value++;
|
||||
} else {
|
||||
ElMessage.error('请填写完整的支出合同信息');
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log(active.value);
|
||||
if (contract_type.value === 'income') {
|
||||
await incomeContractFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
active.value++;
|
||||
} else {
|
||||
ElMessage.error('请填写完整的收入合同信息');
|
||||
}
|
||||
});
|
||||
} else if (contract_type.value === 'expenses') {
|
||||
await expensesContractFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
active.value++;
|
||||
} else {
|
||||
ElMessage.error('请填写完整的支出合同信息');
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log(active.value);
|
||||
|
||||
form.value.step = active.value;
|
||||
form.value.step = active.value;
|
||||
};
|
||||
const submitForm = async () => {
|
||||
await payMentRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (payRatioComputed.value < 0) {
|
||||
ElMessage.error('四项付款比例之和必须等于100%');
|
||||
return;
|
||||
}
|
||||
form.value.payRatio = payRatioComputed.value;
|
||||
await payMentRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (payRatioComputed.value < 0) {
|
||||
ElMessage.error('四项付款比例之和必须等于100%');
|
||||
return;
|
||||
}
|
||||
form.value.payRatio = payRatioComputed.value;
|
||||
|
||||
// 提交付款信息逻辑
|
||||
console.log('提交付款信息', form.value, fileList.value);
|
||||
// 这里可以调用API提交数据
|
||||
form.value.projectId = project.value.id;
|
||||
form.value.fileList = fileList.value.map((data) => {
|
||||
return {
|
||||
...data,
|
||||
fileName: data.name,
|
||||
fileUrl: data.url
|
||||
};
|
||||
});
|
||||
if (contract_type.value === 'income') {
|
||||
await updateIncomeContract({ ...form.value });
|
||||
}
|
||||
ElMessage.success('合同修改成功');
|
||||
} else {
|
||||
ElMessage.error('请填写完整的付款信息');
|
||||
}
|
||||
});
|
||||
// 提交付款信息逻辑
|
||||
console.log('提交付款信息', form.value, fileList.value);
|
||||
// 这里可以调用API提交数据
|
||||
form.value.projectId = project.value.id;
|
||||
form.value.fileList = fileList.value.map((data) => {
|
||||
return {
|
||||
...data,
|
||||
fileName: data.name,
|
||||
fileUrl: data.url
|
||||
};
|
||||
});
|
||||
if (contract_type.value === 'income') {
|
||||
await updateIncomeContract({ ...form.value });
|
||||
}
|
||||
ElMessage.success('合同修改成功');
|
||||
} else {
|
||||
ElMessage.error('请填写完整的付款信息');
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleChoose = async () => {
|
||||
if (!form.value.contractType) {
|
||||
ElMessage.error('请先选择合同类型');
|
||||
return;
|
||||
}
|
||||
const formData = {
|
||||
projectId: userStore.selectedProject.id,
|
||||
dictName: form.value.contractType,
|
||||
status: 1
|
||||
};
|
||||
const { data } = await getTenderPlan(formData);
|
||||
if (data.length === 0) {
|
||||
ElMessage.warning('当前没有招标计划,请先创建招标计划');
|
||||
return;
|
||||
}
|
||||
planList.value = data;
|
||||
dialogVisible.value = true;
|
||||
if (!form.value.contractType) {
|
||||
ElMessage.error('请先选择合同类型');
|
||||
return;
|
||||
}
|
||||
const formData = {
|
||||
projectId: userStore.selectedProject.id,
|
||||
dictName: form.value.contractType,
|
||||
status: 1
|
||||
};
|
||||
const { data } = await getTenderPlan(formData);
|
||||
if (data.length === 0) {
|
||||
ElMessage.warning('当前没有招标计划,请先创建招标计划');
|
||||
return;
|
||||
}
|
||||
planList.value = data;
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
const id = route.query.id;
|
||||
if (id) {
|
||||
const { data } = await getIncomeContract(id);
|
||||
form.value.id = data.id;
|
||||
form.value.contractOwner = data.contractOwner
|
||||
} else {
|
||||
router.push('/ctr/incomeContract');
|
||||
}
|
||||
})
|
||||
const id = route.query.id;
|
||||
if (id) {
|
||||
const { data } = await getIncomeContract(id);
|
||||
form.value.id = data.id;
|
||||
form.value.contractOwner = data.contractOwner;
|
||||
} else {
|
||||
router.push('/ctr/incomeContract');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
padding: 20px;
|
||||
padding: 20px;
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30px;
|
||||
flex-direction: column;
|
||||
}
|
||||
.content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 30px;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -145,7 +145,13 @@
|
||||
></el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="费用" prop="costEstimation">
|
||||
<el-input min="0" v-model="form.costEstimation" type="number" placeholder="请输入费用" /> </el-form-item
|
||||
<el-input-number
|
||||
:min="0"
|
||||
:precision="4"
|
||||
v-model="form.costEstimation"
|
||||
:controls="false"
|
||||
placeholder="请输入费用"
|
||||
/> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="变更费用估算表" label-width="110px" prop="costEstimationFile">
|
||||
|
@ -0,0 +1,396 @@
|
||||
<template>
|
||||
<div class="content-box">
|
||||
<el-table :data="data" style="width: 100%" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="index" width="55" label="序号" align="center" />
|
||||
<el-table-column align="center" prop="projectName" label="工程名称" />
|
||||
<el-table-column align="center" prop="submitUnit" label="提出单位" />
|
||||
<el-table-column align="center" prop="specialty" label="专业">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="des_user_major" :value="row.specialty" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="submitDate" label="提出日期">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.submitDate) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="volumeName" label="卷册名称" />
|
||||
<el-table-column align="center" prop="volumeNumber" label="卷册号" />
|
||||
<el-table-column align="center" prop="content" label="变更内容" />
|
||||
<el-table-column align="center" prop="costEstimation" label="变更费用估算" />
|
||||
<el-table-column label="流程状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="wf_business_status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="content" label="操作" width="240">
|
||||
<template #default="scope">
|
||||
<el-button link type="warning" v-if="scope.row.status === 'draft'" icon="Edit" @click="handleUpdate(scope.row)" class="ml-3"
|
||||
>审批
|
||||
</el-button>
|
||||
<el-button link type="primary" icon="View" @click="handleViewInfo(scope.row)" class="ml-3"> 查看流程 </el-button>
|
||||
<el-button link type="success" icon="View" @click="handleDetail(scope.row)" class="ml-3"> 详情 </el-button>
|
||||
<!-- <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"> 删除 </el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 详情 -->
|
||||
<el-dialog title="变更单详情" v-model="detailVisible" width="1000">
|
||||
<div class="w[850px] ma word-export-wrapper" ref="exportRef">
|
||||
<div class="w80% ma">
|
||||
<h2 style="text-align: center; margin-top: 5px; font-weight: bold">变更单</h2>
|
||||
<el-row>
|
||||
<el-col :span="12">编号:{{ tableDetail.id }}</el-col>
|
||||
</el-row>
|
||||
<el-descriptions :column="2" border style="margin-top: 8px" label-width="160px" size="large">
|
||||
<el-descriptions-item label-align="center" label="工程名称" class-name="zebra"> {{ tableDetail.projectName }} </el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="提出单位" class-name="zebra"> {{ tableDetail.submitUnit }} </el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="专业" label-class-name="white"
|
||||
><dict-tag :options="des_user_major" :value="tableDetail.specialty" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="提出日期" label-class-name="white">
|
||||
{{ dayjs(tableDetail.submitDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="卷册名称" class-name="zebra"> {{ tableDetail.volumeName }} </el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="卷册号" class-name="zebra"> {{ tableDetail.volumeNumber }} </el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="附图" :span="2" label-class-name="white">
|
||||
<img :src="item.url" v-for="item in tableDetail.attachmentsImgList" alt="" style="width: 200px; height: auto" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="变更原因" :span="2" class-name="zebra">
|
||||
<el-checkbox-group v-model="tableDetail.changeReasons">
|
||||
<el-checkbox
|
||||
v-for="(item, index) in radioList"
|
||||
:class="index % 2 == 0 ? 'w45%' : ''"
|
||||
:label="item.label"
|
||||
:value="item.label"
|
||||
disabled
|
||||
/>
|
||||
</el-checkbox-group>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="内容" :span="2" label-class-name="white">
|
||||
{{ tableDetail.content }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="附件" :span="2" label-class-name="white">
|
||||
<el-link type="primary" :underline="false" :href="tableDetail.attachmentsList?.url" target="_blank">{{
|
||||
tableDetail.attachmentsList?.originalName
|
||||
}}</el-link>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="变更费用估算" :span="2" class-name="zebra">
|
||||
{{ tableDetail.costEstimation }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions border direction="vertical" size="large">
|
||||
<el-descriptions-item label-align="center" label="施工承包单位" class-name="none"></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions :column="2" border label-width="160px" size="large">
|
||||
<el-descriptions-item label-align="center" label="项目经理 " label-class-name="white">
|
||||
{{ tableDetail.contractorLeader }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="日期" label-class-name="white">
|
||||
{{ dayjs(tableDetail.contractorDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<!-- <el-descriptions border direction="vertical" size="large">
|
||||
<el-descriptions-item label-align="center" label="总承包单位" class-name="none"></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions :column="2" border label-width="160px" size="large">
|
||||
<el-descriptions-item label-align="center" label="项目技术负责人" label-class-name="white">{{
|
||||
tableDetail.bsupervisorLeader
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="日期" label-class-name="white">
|
||||
{{ dayjs(tableDetail.bsupervisorDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions border direction="vertical" size="large">
|
||||
<el-descriptions-item label-align="center" label="设计单位" class-name="none"></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions :column="2" border label-width="160px" size="large">
|
||||
<el-descriptions-item label-align="center" label="设计代表" label-class-name="white">{{
|
||||
tableDetail.csupervisorLeader
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="日期" label-class-name="white">
|
||||
{{ dayjs(tableDetail.csupervisorDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions> -->
|
||||
<el-descriptions border direction="vertical" size="large">
|
||||
<el-descriptions-item label-align="center" label="项目监理单位" class-name="none"></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- 单独插入整行占用的内容 -->
|
||||
<el-descriptions :column="2" border label-width="160px" size="large">
|
||||
<el-descriptions-item label="总监理工程师" label-align="center" label-class-name="white">
|
||||
{{ tableDetail.supervisorLeader }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="日期" label-align="center" label-class-name="white">
|
||||
{{ dayjs(tableDetail.supervisorDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<!-- 一组完整两列 -->
|
||||
<!-- <el-descriptions :column="2" border label-width="160px" size="large">
|
||||
<el-descriptions-item label="监理工程师" label-align="center" label-class-name="white">
|
||||
{{ tableDetail.dsupervisorLeader }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="日期" label-align="center" label-class-name="white">
|
||||
{{ dayjs(tableDetail.supervisorDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions> -->
|
||||
<el-descriptions border direction="vertical" size="large">
|
||||
<el-descriptions-item label-align="center" label="建设单位" class-name="none"></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions :column="2" border label-width="160px" size="large">
|
||||
<!-- <el-descriptions-item label-align="center" label="会签" :span="2" label-class-name="white"> {{ tableDetail.esupervisorLeader }} </el-descriptions-item> -->
|
||||
<el-descriptions-item label-align="center" label="负责人" label-class-name="white">
|
||||
{{ tableDetail.ownerRep }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label-align="center" label="日期" label-class-name="white">
|
||||
{{ dayjs(tableDetail.ownerDate).format('YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<div class="btn-item" @click="handleDownload">
|
||||
<img src="@/assets/icons/svg/derived.png" />
|
||||
<span>下载</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { listByIds } from '@/api/system/oss';
|
||||
import { dayjs } from 'element-plus';
|
||||
import { saveAs } from 'file-saver';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
thumbnail: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
|
||||
const tableDetail = ref<any>({ attachmentsImgList: [], attachmentsList: [] });
|
||||
|
||||
const exportRef = ref<HTMLElement>();
|
||||
const radioList = ref([
|
||||
{ value: 0, label: '设计漏项' },
|
||||
{ value: 1, label: '设计改进' },
|
||||
{ value: 2, label: '设计差错' },
|
||||
{ value: 3, label: '接口差错' },
|
||||
{ value: 4, label: '业主要求' },
|
||||
{ value: 5, label: '施工承包商要求' },
|
||||
{ value: 6, label: '外部资料与最终情况不符' },
|
||||
{ value: 7, label: '材料代用及其他' }
|
||||
]);
|
||||
const detailVisible = ref(false);
|
||||
const formatDate = (val: string | Date) => (val ? dayjs(val).format('YYYY-MM-DD') : '');
|
||||
const { des_user_major } = toRefs<any>(proxy?.useDict('des_user_major'));
|
||||
|
||||
const handleDetail = async (row) => {
|
||||
tableDetail.value = { ...row };
|
||||
|
||||
if (row.attachmentsImg) {
|
||||
const res = await listByIds(row.attachmentsImg);
|
||||
tableDetail.value.attachmentsImgList = res.data;
|
||||
}
|
||||
if (row.attachments) {
|
||||
const res = await listByIds(row.attachments);
|
||||
tableDetail.value.attachmentsList = res.data[0];
|
||||
}
|
||||
|
||||
// tableDetail.value = {
|
||||
// ...row,
|
||||
// hasAttachmentList: res.data
|
||||
// };
|
||||
detailVisible.value = true;
|
||||
};
|
||||
/** 多选框选中数据 */
|
||||
const emit = defineEmits(['selection-change', 'delete']);
|
||||
const handleSelectionChange = (selection: any) => {
|
||||
emit('selection-change', selection);
|
||||
};
|
||||
const handleDelete = (row) => {
|
||||
emit('delete', row.id);
|
||||
};
|
||||
const handleUpdate = (row) => {
|
||||
// 添加审批
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/approval/changeContact/indexEdit`,
|
||||
query: {
|
||||
thumbnailUrl: props.thumbnail,
|
||||
row: JSON.stringify(row),
|
||||
id: row.id,
|
||||
type: 'update'
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleViewInfo = (row) => {
|
||||
// 添加审批
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/approval/changeContact/indexEdit`,
|
||||
query: {
|
||||
thumbnailUrl: props.thumbnail,
|
||||
row: JSON.stringify(row),
|
||||
id: row.id,
|
||||
type: 'view'
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleDownload = async () => {
|
||||
const style = `
|
||||
<style>
|
||||
.white { background: #fff !important; }
|
||||
.none { display: none !important; }
|
||||
.zebra { background: #f5f7fa !important; }
|
||||
.el-descriptions__table { table-layout: fixed !important; }
|
||||
table { border-collapse: collapse; width: 100%; }
|
||||
th, td { border: 1px solid #333; padding: 6px; font-size: 14px; }
|
||||
</style>
|
||||
`;
|
||||
|
||||
const el = exportRef.value;
|
||||
if (!el) return;
|
||||
|
||||
// 拷贝 DOM,避免影响原内容
|
||||
const clone = el.cloneNode(true) as HTMLElement;
|
||||
|
||||
// 删除 .dialog-footer
|
||||
const footer = clone.querySelector('.dialog-footer');
|
||||
if (footer) {
|
||||
footer.remove();
|
||||
}
|
||||
|
||||
// 工具函数:图片转成指定宽度的 base64
|
||||
const resizeImageToBase64 = (img: HTMLImageElement, maxWidth = 500) => {
|
||||
return new Promise<string>((resolve) => {
|
||||
const image = new Image();
|
||||
image.crossOrigin = 'anonymous';
|
||||
image.src = img.src;
|
||||
image.onload = () => {
|
||||
const scale = Math.min(1, maxWidth / image.naturalWidth);
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = image.naturalWidth * scale;
|
||||
canvas.height = image.naturalHeight * scale;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx!.drawImage(image, 0, 0, canvas.width, canvas.height);
|
||||
resolve(canvas.toDataURL('image/png'));
|
||||
};
|
||||
image.onerror = () => {
|
||||
resolve(img.src); // 如果加载失败就用原地址
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 找到所有图片并替换成 base64(顺序执行以避免并发问题)
|
||||
const imgs = Array.from(clone.querySelectorAll('img'));
|
||||
for (let img of imgs) {
|
||||
const base64 = await resizeImageToBase64(img, 200);
|
||||
img.src = base64;
|
||||
}
|
||||
|
||||
// 应用表格的内联样式
|
||||
applyInlineTableStyles(clone);
|
||||
|
||||
// 拼接 HTML
|
||||
const html = `
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
${style}
|
||||
</head>
|
||||
<body>
|
||||
${clone.innerHTML}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
const blob = (window as any).htmlDocx.asBlob(html);
|
||||
saveAs(blob, '变更单.docx');
|
||||
};
|
||||
|
||||
const applyInlineTableStyles = (rootEl: HTMLElement) => {
|
||||
rootEl.querySelectorAll('table').forEach((table) => {
|
||||
table.setAttribute('style', 'width:100%; border-collapse:collapse; table-layout:fixed; border:1px solid #333;');
|
||||
});
|
||||
|
||||
rootEl.querySelectorAll('th, td').forEach((cell) => {
|
||||
cell.setAttribute('style', 'border:1px solid #333; padding:6px; font-size:14px; word-break:break-all;');
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.white) {
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
:deep(.none) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:deep(.zebra) {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
:deep(.el-descriptions__table) {
|
||||
table-layout: fixed !important;
|
||||
}
|
||||
.word-export-wrapper {
|
||||
table {
|
||||
width: 100% !important;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #333;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* 确保不超出 Word 页边距 */
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.el-descriptions__label {
|
||||
font-weight: bold;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.dialog-footer {
|
||||
height: 100px;
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
position: absolute;
|
||||
top: 14%;
|
||||
right: 6%;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 10px #ddd;
|
||||
text-align: center;
|
||||
padding: 20px 10px;
|
||||
|
||||
.btn-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
img {
|
||||
transform: rotateZ(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
279
src/views/design/shijibiangeng/index.vue
Normal file
279
src/views/design/shijibiangeng/index.vue
Normal file
@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAddApp" v-hasPermi="['quality:qualityInspection:add']"
|
||||
>上传设计变更单</el-button
|
||||
>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<EngineeringChangeApplicationForm
|
||||
@selection-change="handleSelectionChange"
|
||||
:data="tableData"
|
||||
:thumbnail="projectTypeOptions[1].thumbnail"
|
||||
@delete="handleDelete"
|
||||
></EngineeringChangeApplicationForm>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
<el-dialog title="新增模板" v-model="dialogVisible" width="800">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="110px">
|
||||
<div class="flex">
|
||||
<div><image-preview :src="thumbnailUrl" width="150px"></image-preview></div>
|
||||
<div>
|
||||
<el-form-item label="工程名称" prop="projectName">
|
||||
<el-input v-model="form.projectName" placeholder="请输入工程名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="编号" prop="serialNumber">
|
||||
<el-input v-model="form.serialNumber" placeholder="请输入编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="致" prop="to">
|
||||
<el-input v-model="form.to" placeholder="致:" />
|
||||
</el-form-item>
|
||||
<el-form-item label="主题" prop="subject">
|
||||
<el-input v-model="form.subject" placeholder="请输入主题" />
|
||||
</el-form-item>
|
||||
<el-form-item label="内容" prop="content">
|
||||
<el-input v-model="form.content" type="textarea" :rows="6" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="attachments">
|
||||
<file-upload v-model="form.attachments" :limit="1" :file-type="['pdf', 'png', 'jpg', 'jpeg', 'gif', 'bmp']"></file-upload>
|
||||
</el-form-item>
|
||||
<el-divider class="mb-10! mt-10!">施工项目部</el-divider>
|
||||
<el-form-item label="项目负责人" prop="contractorLeader">
|
||||
<el-input v-model="form.contractorLeader" placeholder="请输入负责人姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="日期" prop="contractorDate">
|
||||
<el-date-picker v-model="form.contractorDate" type="date" placeholder="选择日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-divider class="mb-10! mt-10!">项目监理机构</el-divider>
|
||||
|
||||
<el-form-item label="总监理工程师" prop="supervisorLeader">
|
||||
<el-input v-model="form.supervisorLeader" placeholder="请输入总监理工程师姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="日期" prop="supervisorDate">
|
||||
<el-date-picker v-model="form.supervisorDate" type="date" placeholder="选择日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-divider class="mb-10! mt-10!">建设单位</el-divider>
|
||||
<el-form-item label="业主代表" prop="ownerRep">
|
||||
<el-input v-model="form.ownerRep" placeholder="请输入业主代表" />
|
||||
</el-form-item>
|
||||
<el-form-item label="日期" prop="ownerDate">
|
||||
<el-date-picker v-model="form.ownerDate" type="date" placeholder="选择日期" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import EngineeringChangeApplicationForm from './components/engineeringChangeApplicationForm.vue';
|
||||
import { listContactTypeformtemplate } from '@/api/cory/contactformtemplate';
|
||||
import { addContactnotice, delContactnotice, listContactnotice } from '@/api/cory/contactnotice';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wf_business_status } = toRefs(proxy?.useDict('wf_business_status'));
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const thumbnailUrl = ref('');
|
||||
const tableData = ref([]);
|
||||
const total = ref(0);
|
||||
const activeName = ref('1');
|
||||
const formRef = ref<FormInstance>();
|
||||
const dialogVisible = ref<boolean>(false);
|
||||
const showSearch = ref(true);
|
||||
const multiple = ref<boolean>(true);
|
||||
const addSingle = ref<boolean>(false);
|
||||
const single = ref<boolean>(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
|
||||
const projectTypeOptions = ref<any>([
|
||||
{
|
||||
value: '0',
|
||||
label: '外部联系单'
|
||||
},
|
||||
{
|
||||
value: '1',
|
||||
label: '变更单'
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '通知单'
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: '回复单'
|
||||
},
|
||||
{
|
||||
value: '4',
|
||||
label: '签证单'
|
||||
}
|
||||
]);
|
||||
|
||||
const initFormData = {
|
||||
projectType: '',
|
||||
projectName: '',
|
||||
serialNumber: '',
|
||||
to: '',
|
||||
subject: '',
|
||||
content: '',
|
||||
attachments: '',
|
||||
contractorLeader: '',
|
||||
contractorDate: '',
|
||||
supervisorLeader: '',
|
||||
supervisorDate: '',
|
||||
ownerRep: '',
|
||||
ownerDate: '',
|
||||
unitName: '',
|
||||
profession: '',
|
||||
applyDate: '',
|
||||
bookName: '',
|
||||
bookNo: '',
|
||||
hasAttachment: '',
|
||||
changeReasons: [],
|
||||
changeContent: '',
|
||||
costEstimate: ''
|
||||
};
|
||||
const data = reactive<PageData<any, any>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
projectId: currentProject.value?.id,
|
||||
inspectionType: undefined,
|
||||
inspectionStatus: undefined,
|
||||
teamId: undefined,
|
||||
type: undefined,
|
||||
params: {},
|
||||
// ids: ['1942107830848872449', '1942107931415699457'],
|
||||
projectType: undefined
|
||||
},
|
||||
rules: {
|
||||
projectName: [{ required: true, message: '请输入工程名称', trigger: 'blur' }],
|
||||
projectType: [{ required: true, message: '请选择模板类型', trigger: 'blur' }],
|
||||
serialNumber: [{ required: true, message: '请输入编号', trigger: 'blur' }],
|
||||
to: [{ required: true, message: '请输入接收方', trigger: 'blur' }],
|
||||
subject: [{ required: true, message: '请输入主题', trigger: 'blur' }],
|
||||
content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
const submitForm = () => {
|
||||
formRef.value?.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let data = {
|
||||
type: queryParams.value.type,
|
||||
projectId: currentProject.value?.id,
|
||||
detail: JSON.stringify(form.value)
|
||||
};
|
||||
console.log('提交表单:', form);
|
||||
const res = await addContactnotice(data);
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('添加成功');
|
||||
dialogVisible.value = false;
|
||||
formRef.value.resetFields();
|
||||
getList();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const getList = async () => {
|
||||
if (!queryParams.value.projectType) {
|
||||
const res = await listContactTypeformtemplate(queryParams.value);
|
||||
projectTypeOptions.value = res.data;
|
||||
queryParams.value.projectType = res.data[1].name;
|
||||
thumbnailUrl.value = res.data[1].thumbnail;
|
||||
queryParams.value.type = res.data[1].id as string;
|
||||
}
|
||||
const res = await listContactnotice(queryParams.value);
|
||||
res.rows = res.rows.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
...JSON.parse(item.detail),
|
||||
status: item.status
|
||||
};
|
||||
});
|
||||
tableData.value = res.rows;
|
||||
console.log('🚀 ~ getList ~ tableData.value:', tableData.value);
|
||||
total.value = res.total || 0;
|
||||
};
|
||||
const handleDelete = async (id?: string) => {
|
||||
const _ids = id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除识别记录编号为"' + _ids + '"的数据项?').finally();
|
||||
const res = await delContactnotice(_ids);
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
getList();
|
||||
}
|
||||
};
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: any) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const selectType = (value: string) => {
|
||||
queryParams.value.projectType = value;
|
||||
thumbnailUrl.value = projectTypeOptions.value.filter((item) => item.name == value)[0].thumbnail;
|
||||
queryParams.value.type = projectTypeOptions.value.filter((item) => item.name == value)[0].id;
|
||||
getList();
|
||||
};
|
||||
|
||||
const handleClick = (val) => {
|
||||
console.log(val);
|
||||
queryParams.value.projectType = val.props.name;
|
||||
getList();
|
||||
};
|
||||
const handleAddApp = (row) => {
|
||||
// 添加审批
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/approval/changeContact/indexEdit`,
|
||||
query: {
|
||||
thumbnailUrl: projectTypeOptions.value[1].thumbnail,
|
||||
id: projectTypeOptions.value[1].id,
|
||||
row,
|
||||
type: 'add'
|
||||
}
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
|
||||
//监听项目id刷新数据
|
||||
const listeningProject = watch(
|
||||
() => currentProject.value?.id,
|
||||
(nid, oid) => {
|
||||
queryParams.value.projectId = nid;
|
||||
getList();
|
||||
}
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
listeningProject();
|
||||
});
|
||||
</script>
|
@ -10,6 +10,13 @@
|
||||
<el-form-item label="资料名称" prop="documentName">
|
||||
<el-input v-model="queryParams.documentName" placeholder="请输入资料名称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否文件上传" prop="isUpload" label-width="110px">
|
||||
<el-select v-model="queryParams.isUpload" placeholder="请选择" clearable @keyup.enter="handleQuery">
|
||||
<el-option value="1" label="是" />
|
||||
<el-option value="0" label="否" />
|
||||
<el-option value="2" label="全部" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery" v-hasPermi="['design:volumeCatalog:query']">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery" v-hasPermi="['design:volumeCatalog:query']">重置</el-button>
|
||||
@ -154,14 +161,14 @@
|
||||
<el-form-item v-if="uploadForm.type == '3'" label="蓝图" prop="fileIds">
|
||||
<file-upload :fileType="['pdf']" :isShowTip="false" :fileSize="100" v-model="uploadForm.fileIds"></file-upload>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="uploadForm.type == '3'" label="通知人">
|
||||
<el-form-item v-if="uploadForm.type == '1'" label="过程图纸" prop="cancellationIds">
|
||||
<file-upload :fileType="['pdf']" :isShowTip="false" :fileSize="100" v-model="uploadForm.cancellationIds"></file-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知人">
|
||||
<el-select multiple filterable clearable v-model="form.userIds" placeholder="请选择通知人">
|
||||
<el-option :value="item.userId" v-for="item in userCoryList" :key="item.userId" :label="item.nickName + '-' + item.phonenumber" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="uploadForm.type == '1'" label="过程图纸" prop="cancellationIds">
|
||||
<file-upload :fileType="['pdf']" :isShowTip="false" :fileSize="100" v-model="uploadForm.cancellationIds"></file-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="font-size: 12px; color: #999999">注意:请上传pdf格式文件</span>
|
||||
<div style="display: flex; justify-content: flex-end">
|
||||
@ -360,7 +367,8 @@ const data = reactive({
|
||||
designSubitemId: undefined,
|
||||
volumeNumber: undefined,
|
||||
documentName: undefined,
|
||||
params: {}
|
||||
params: {},
|
||||
isUpload: '2'
|
||||
},
|
||||
rules: {
|
||||
design: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
|
||||
@ -585,7 +593,6 @@ const handleUploadSuccess = async (flieList: any, res: any) => {
|
||||
};
|
||||
/** 审核蓝图按钮操作 */
|
||||
const handleAuditLantu = async (row) => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/approval/volumeCatalog/blueprintEdit`,
|
||||
query: {
|
||||
@ -596,7 +603,6 @@ const handleAuditLantu = async (row) => {
|
||||
};
|
||||
/** 查看蓝图按钮操作 */
|
||||
const handleAuditViewLantu = async (row) => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/approval/volumeCatalog/blueprintEdit`,
|
||||
query: {
|
||||
|
@ -0,0 +1,328 @@
|
||||
<template>
|
||||
<div class="centerPage">
|
||||
<div class="centerPage_map">
|
||||
<div ref="mapRef" class="map-container" style="width: 100%; height: 100%" />
|
||||
</div>
|
||||
<div class="centerPage_bottom">
|
||||
<Title title="风险预警">
|
||||
<img src="@/assets/projectLarge/robot.svg" alt="" height="20px" width="20px" />
|
||||
</Title>
|
||||
<div class="centerPage_bottom_table">
|
||||
<el-table v-loading="loading" :data="tableData" show-overflow-tooltip>
|
||||
<el-table-column label="时间" align="center" prop="date" />
|
||||
<el-table-column label="类型" align="center" prop="riskType">
|
||||
<template #default="scope">
|
||||
{{ safety_inspection_type[scope.row.riskType] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="报警内容" align="center" prop="alarmContent" />
|
||||
<el-table-column label="危险等级" align="center" prop="dangerLevel" />
|
||||
<el-table-column label="来源" align="center" prop="source" />
|
||||
<el-table-column label="警告等级" align="center" prop="alarmLevel">
|
||||
<template #default="scope">
|
||||
{{ risk_level_type[scope.row.alarmLevel] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts';
|
||||
import china from '@/assets/china.json';
|
||||
import RevenueContractCard from './RevenueContractCard.vue';
|
||||
import bottomboxconpoent from './bottomboxconpoent.vue';
|
||||
import { totalAmount, projectGis } from '@/api/largeScreen/index'; // 导入projectGis接口
|
||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import Title from './title.vue';
|
||||
import { earlyWarning } from '@/api/outputApi';
|
||||
import { useDict } from '@/utils/dict';
|
||||
import { getDicts } from '@/api/system/dict/data';
|
||||
// 地图相关变量
|
||||
const mapRef = ref<HTMLDivElement | null>(null);
|
||||
let myChart: any = null;
|
||||
const projectData = ref<any[]>([]); // 存储项目地理信息数据
|
||||
const loading = ref(false);
|
||||
const tableData = ref([]);
|
||||
const risk_level_type = ref();
|
||||
const safety_inspection_type = ref();
|
||||
// 新增:获取项目地理信息数据
|
||||
const getProjectGisData = async () => {
|
||||
try {
|
||||
const response = await projectGis();
|
||||
if (response.code === 200) {
|
||||
// 过滤掉没有经纬度的项目
|
||||
projectData.value = response.data.filter((item: any) => item.lng !== null && item.lat !== null && item.lng !== '' && item.lat !== '');
|
||||
console.log('项目地理数据:', projectData.value);
|
||||
} else {
|
||||
console.error('项目地理数据请求失败:', response.msg);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('项目地理数据调用异常:', error);
|
||||
}
|
||||
};
|
||||
//获取字典
|
||||
const getDictsType = async () => {
|
||||
const res = await getDicts('risk_level_type');
|
||||
if (res.code === 200) {
|
||||
risk_level_type.value = res.data.reduce((acc, item) => {
|
||||
acc[item.dictValue] = item.dictLabel;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
const getDictsType2 = async () => {
|
||||
const res = await getDicts('safety_inspection_type');
|
||||
if (res.code === 200) {
|
||||
safety_inspection_type.value = res.data.reduce((acc, item) => {
|
||||
acc[item.dictValue] = item.dictLabel;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
//获取表格数据
|
||||
const getTableList = async () => {
|
||||
const res = await earlyWarning();
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data;
|
||||
}
|
||||
};
|
||||
|
||||
// 地图resize处理
|
||||
const handleResize = () => {
|
||||
if (myChart) myChart.resize();
|
||||
};
|
||||
|
||||
// 初始化地图(修改为使用接口数据)
|
||||
const initEcharts = () => {
|
||||
if (!mapRef.value || projectData.value.length === 0) {
|
||||
console.error('未找到地图容器或项目数据');
|
||||
return;
|
||||
}
|
||||
|
||||
echarts.registerMap('china', china as any);
|
||||
|
||||
// 从接口数据生成散点数据
|
||||
const scatterData = projectData.value.map((item) => ({
|
||||
name: item.projectName,
|
||||
value: [parseFloat(item.lng), parseFloat(item.lat)], // 转换为数值类型
|
||||
shortName: item.shortName,
|
||||
projectSite: item.projectSite,
|
||||
symbol: 'diamond',
|
||||
itemStyle: { color: '#0166d6' },
|
||||
symbolSize: [20, 20],
|
||||
label: {
|
||||
show: true,
|
||||
formatter: '{b}', // 显示项目名称
|
||||
position: 'top',
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
backgroundColor: 'rgba(3, 26, 52, 0.7)',
|
||||
padding: [3, 6],
|
||||
borderRadius: 3
|
||||
}
|
||||
}));
|
||||
|
||||
myChart = echarts.init(mapRef.value, null, {
|
||||
renderer: 'canvas',
|
||||
useDirtyRect: false
|
||||
});
|
||||
|
||||
const option: any = {
|
||||
roam: true, // 允许缩放和平移
|
||||
geo: {
|
||||
type: 'map',
|
||||
map: 'china',
|
||||
zoom: 2, // 调整初始缩放级别
|
||||
center: [108.95, 34.27], // 中国中心位置经纬度
|
||||
label: { show: false, color: '#fff' },
|
||||
itemStyle: {
|
||||
areaColor: '#031a34',
|
||||
borderColor: '#1e3a6e',
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
backgroundColor: 'rgba(3, 26, 52, 0.8)',
|
||||
borderColor: '#1e3a6e',
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
formatter: function (params: any) {
|
||||
if (params.data) {
|
||||
// 处理散点数据
|
||||
const data = params.data;
|
||||
return `
|
||||
<div style="font-weight: bold;">${data.name}</div>
|
||||
<div>地点:${data.projectSite}</div>
|
||||
<div>经纬度:${data.value[0].toFixed(6)}, ${data.value[1].toFixed(6)}</div>
|
||||
`;
|
||||
}
|
||||
if (params.seriesType === 'map') {
|
||||
// console.log(params, 111111);
|
||||
return `
|
||||
<div style="font-weight: bold;">${params.name}</div>
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'map',
|
||||
map: 'china',
|
||||
geoIndex: 0,
|
||||
emphasis: {
|
||||
areaColor: '#fff',
|
||||
label: { show: true, color: '#fff' },
|
||||
itemStyle: { areaColor: '#02417e' }
|
||||
},
|
||||
select: { itemStyle: { areaColor: '#02417e' } },
|
||||
data: [] // 可以留空,或根据需要添加区域数据
|
||||
},
|
||||
{
|
||||
type: 'scatter',
|
||||
coordinateSystem: 'geo',
|
||||
data: scatterData,
|
||||
emphasis: {
|
||||
scale: true, // 鼠标悬停时放大
|
||||
symbolSize: [25, 25]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
};
|
||||
const risk_level_type1 = ref([]);
|
||||
const safety_inspection_type1 = ref([]);
|
||||
// 组件生命周期
|
||||
onMounted(() => {
|
||||
nextTick(async () => {
|
||||
// 先获取合同数据和项目地理数据,再初始化地图
|
||||
getDictsType();
|
||||
getDictsType2();
|
||||
await Promise.all([getProjectGisData()]);
|
||||
initEcharts();
|
||||
getTableList();
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
if (myChart) {
|
||||
myChart.dispose();
|
||||
myChart = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.centerPage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// justify-content: space-between;
|
||||
padding: 0 10px 10px 10px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.centerPage_map {
|
||||
width: 100%;
|
||||
height: 65vh;
|
||||
}
|
||||
.centerPage_bottom {
|
||||
width: 100%;
|
||||
height: 25vh;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.centerPage_bottom_table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
:deep(.el-table, .el-table__expanded-cell) {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.el-table tr) {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
// border: 1px solid rgba(0, 255, 255, 0.5) !important;
|
||||
}
|
||||
:deep(.el-table .el-table__header-wrapper th, .el-table .el-table__fixed-header-wrapper th) {
|
||||
background: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
:deep(.el-table th.el-table__cell) {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
color: #fff;
|
||||
border-bottom: 1px solid transparent !important;
|
||||
border-right: 1px solid transparent !important;
|
||||
}
|
||||
:deep(.el-table--enable-row-transition .el-table__body td.el-table__cell) {
|
||||
border-right: 1px solid transparent !important;
|
||||
border-bottom: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background-color: rgba(40, 75, 91, 0.9) !important;
|
||||
}
|
||||
/* 表格边框颜色 */
|
||||
:deep(.el-table, .el-table__header-wrapper, .el-table__body-wrapper, .el-table__footer-wrapper, .el-table th, .el-table td) {
|
||||
border: 1px solid transparent !important;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
:deep(.el-table__inner-wrapper:before) {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* 固定列的边框 */
|
||||
:deep(.el-table__fixed, .el-table__fixed-right) {
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
:deep(.el-table__body-wrapper::-webkit-scrollbar) {
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
opacity: 0.2;
|
||||
background: #00c0ff;
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper::-webkit-scrollbar-track) {
|
||||
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0;
|
||||
background: rgba(220, 228, 245, 0.8);
|
||||
}
|
||||
|
||||
:deep(.el-icon-arrow-right:before) {
|
||||
color: #0ff;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条优化
|
||||
.centerPage_bottom_table::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.centerPage_bottom_table::-webkit-scrollbar-thumb {
|
||||
background-color: #0ff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.centerPage_bottom_table::-webkit-scrollbar-track {
|
||||
background-color: rgba(0, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<div class="header_left">
|
||||
<div class="header_left_img">
|
||||
<img src="@/assets/large/secure.png" style="width: 100%; height: 100%" />
|
||||
</div>
|
||||
<div style="font-size: 12px; padding-left: 10px">安全生产天数:</div>
|
||||
<div class="header_left_text">
|
||||
{{ safetyDay }}
|
||||
<span style="font-size: 12px">天</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">
|
||||
<div>煤科建管-新能源项目数智化管理平台</div>
|
||||
<div>Coal Science Construction Management - New Energy Project Digital Intelligent Management Platform</div>
|
||||
</div>
|
||||
<div class="header_right">
|
||||
<div class="top-bar">
|
||||
<!-- 左侧:天气图标 + 日期文字 -->
|
||||
<div class="left-section">
|
||||
<div class="weather-list" @mouseenter="requestPause" @mouseleave="resumeScroll">
|
||||
<div
|
||||
v-for="(item, i) in weatherList"
|
||||
:key="i"
|
||||
class="weather-item"
|
||||
:style="{ transform: `translateY(-${offsetY}px)`, transition: transition }"
|
||||
>
|
||||
<img :src="`../../../src/assets/images/${item.icon}.png`" alt="" />
|
||||
<div>{{ item.weather }}{{ item.tempMin }}°/{{ item.tempMax }}°</div>
|
||||
<div>{{ item.week }}({{ item.date }})</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分割线 -->
|
||||
<div class="divider">
|
||||
<div class="top-block"></div>
|
||||
<div class="bottom-block"></div>
|
||||
</div>
|
||||
<!-- 右侧:管理系统图标 + 文字 -->
|
||||
<div class="right-section">
|
||||
<img src="@/assets/large/setting.png" alt="设置图标" />
|
||||
<span>管理系统</span>
|
||||
</div>
|
||||
<!-- 分割线 -->
|
||||
<div class="divider">
|
||||
<div class="top-block"></div>
|
||||
<div class="bottom-block"></div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="change" @click="emit('changePage')">
|
||||
<el-icon size="20" v-if="!isFull">
|
||||
<Expand />
|
||||
</el-icon>
|
||||
<el-icon size="20" v-else>
|
||||
<Fold />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { getScreenSafetyDay, getScreenWeather } from '@/api/projectScreen';
|
||||
|
||||
interface Weather {
|
||||
week: string;
|
||||
date: string;
|
||||
icon: string;
|
||||
weather: string;
|
||||
tempMax: string;
|
||||
tempMin: string;
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
projectId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isFull: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['changePage']);
|
||||
|
||||
const safetyDay = ref<number>(0);
|
||||
const weatherList = ref<Weather[]>([]);
|
||||
const timer = ref<number | null>(0);
|
||||
const offsetY = ref<number>(0);
|
||||
const curIndex = ref(0);
|
||||
const transition = ref('transform 0.5s ease');
|
||||
const pendingPause = ref(false);
|
||||
|
||||
/**
|
||||
* 判断当前时间是白天/夜晚
|
||||
*/
|
||||
function judgeDayOrNight(sunRise: string, sunSet: string) {
|
||||
// 将 "HH:MM" 格式转为分钟数(便于计算)
|
||||
const timeToMinutes = (timeStr: any) => {
|
||||
const [hours, minutes] = timeStr.split(':').map(Number);
|
||||
return isNaN(hours) || isNaN(minutes) ? 0 : hours * 60 + minutes;
|
||||
};
|
||||
// 转换日出、日落时间为分钟数
|
||||
const sunRiseMinutes = timeToMinutes(sunRise);
|
||||
const sunSetMinutes = timeToMinutes(sunSet);
|
||||
// 获取当前时间并转为分钟数
|
||||
const now = new Date();
|
||||
const currentMinutes = now.getHours() * 60 + now.getMinutes();
|
||||
// true 白天 false 夜晚
|
||||
return currentMinutes >= sunRiseMinutes && currentMinutes <= sunSetMinutes ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置天气周期滑动
|
||||
*/
|
||||
const setWeatherScroll = () => {
|
||||
curIndex.value += 1;
|
||||
transition.value = 'transform 0.3s ease';
|
||||
offsetY.value = curIndex.value * 60;
|
||||
|
||||
if (curIndex.value === weatherList.value.length - 1) {
|
||||
setTimeout(() => {
|
||||
transition.value = 'none';
|
||||
curIndex.value = 0;
|
||||
offsetY.value = 0;
|
||||
}, 350);
|
||||
}
|
||||
};
|
||||
|
||||
function startScroll() {
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
timer.value = window.setInterval(setWeatherScroll, 5000);
|
||||
}
|
||||
|
||||
function requestPause() {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
timer.value = null;
|
||||
}
|
||||
pendingPause.value = true;
|
||||
}
|
||||
|
||||
function resumeScroll() {
|
||||
console.log('resumeScroll');
|
||||
pendingPause.value = false;
|
||||
startScroll();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
/**
|
||||
* 获取安全生产天数
|
||||
*/
|
||||
getScreenSafetyDay(props.projectId).then((res) => {
|
||||
const { data, code } = res;
|
||||
if (code === 200) {
|
||||
safetyDay.value = data.safetyDay;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* 获取近三天天气
|
||||
*/
|
||||
getScreenWeather(props.projectId).then((res) => {
|
||||
const { data, code } = res;
|
||||
if (code === 200) {
|
||||
data.forEach((item) => {
|
||||
if (judgeDayOrNight(item.sunRise, item.sunSet)) {
|
||||
item.weather = item.dayStatus;
|
||||
item.icon = item.dayIcon;
|
||||
} else {
|
||||
item.weather = item.nightStatus;
|
||||
item.icon = item.nightIcon;
|
||||
}
|
||||
});
|
||||
weatherList.value = data;
|
||||
// 多添加第一项 实现无缝衔接
|
||||
weatherList.value = [...weatherList.value, weatherList.value[0]];
|
||||
startScroll();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.header {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2fr 1fr;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.header_left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.header_left_img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
box-sizing: border-box;
|
||||
// padding-right: 10px;
|
||||
}
|
||||
|
||||
.header_left_text {
|
||||
font-weight: 500;
|
||||
text-shadow: 0px 1.24px 6.21px rgba(25, 179, 250, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.header_right {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #fff;
|
||||
font-family: 'AlimamaShuHeiTi', sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title > div:first-child {
|
||||
/* 第一个子元素的样式 */
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.title > div:last-child {
|
||||
/* 最后一个子元素的样式 */
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 顶部栏容器:Flex 水平布局 + 垂直居中 */
|
||||
.top-bar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
color: #fff;
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 左侧区域(天气 + 日期):自身也用 Flex 水平排列,确保元素在一行 */
|
||||
.left-section {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.weather-list {
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
|
||||
.weather-item {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > div:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 分割线(视觉分隔,可根据需求调整样式) */
|
||||
.divider {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
gap: 2px;
|
||||
padding: 14px 10px;
|
||||
}
|
||||
|
||||
.divider .top-block {
|
||||
width: 2px;
|
||||
height: 7px;
|
||||
background: #19b5fb;
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.divider .bottom-block {
|
||||
width: 2px;
|
||||
height: 7px;
|
||||
background: #19b5fb;
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
/* 右侧区域(管理系统):图标 + 文字水平排列 */
|
||||
.right-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: 'AlimamaShuHeiTi', sans-serif;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.right-section img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 6px;
|
||||
/* 图标与文字间距 */
|
||||
}
|
||||
|
||||
.change {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,540 @@
|
||||
<template>
|
||||
<div class="leftPage">
|
||||
<div class="topPage">
|
||||
<Title style="font-size: 22px" title="企业关键指标" />
|
||||
<div class="indicators">
|
||||
<div class="indicator-card" v-for="indicator in indicators" :key="indicator.id">
|
||||
<div style="display: flex; align-items: baseline; gap: 4px; margin-bottom: 5px">
|
||||
<div class="indicator-value">{{ indicator.value }}</div>
|
||||
<div class="indicator-unit">{{ indicator.unit }}</div>
|
||||
</div>
|
||||
<div class="indicator-name">{{ indicator.name }}</div>
|
||||
<div class="indicator-icon">
|
||||
<img :src="indicator.iconPath" :alt="indicator.name" v-if="indicator.iconPath" style="width: 50px; height: 50px" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="endPage">
|
||||
<Title style="font-size: 22px" title="人员情况" />
|
||||
<div class="map">
|
||||
<div class="project_attendance_chart">
|
||||
<Title style="font-size: 22px" title="各项目人员出勤率" />
|
||||
<div class="chart_content" ref="attendanceChartRef"></div>
|
||||
</div>
|
||||
<div class="attendance_tag">
|
||||
<div class="tag_item">
|
||||
<img src="@/assets/projectLarge/people.svg" alt="" />
|
||||
<div class="tag_title">出勤人</div>
|
||||
<div class="tag_info">
|
||||
{{ attendanceCount }}
|
||||
<span style="font-size: 14px">人</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tag_item">
|
||||
<img src="@/assets/projectLarge/people.svg" alt="" />
|
||||
<div class="tag_title">在岗人</div>
|
||||
<div class="tag_info">
|
||||
{{ peopleCount }}
|
||||
<span style="font-size: 14px">人</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tag_item">
|
||||
<img src="@/assets/projectLarge/people.svg" alt="" />
|
||||
<div class="tag_title">出勤率</div>
|
||||
<div class="tag_info">
|
||||
{{ attendanceRate }}
|
||||
<span style="font-size: 14px">%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="attendance_tag"></div>
|
||||
</div>
|
||||
|
||||
<!-- 项目出勤率柱状图 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import Title from './title.vue';
|
||||
import { getScreenNews, getScreenPeople } from '@/api/projectScreen';
|
||||
import { keyIndex } from '@/api/enterpriseLarge/index';
|
||||
import { mapOption } from './optionList';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const props = defineProps({
|
||||
projectId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
|
||||
let mapChart = null;
|
||||
const mapChartRef = ref<HTMLDivElement | null>(null);
|
||||
const indicators = ref([
|
||||
{
|
||||
id: '1',
|
||||
name: '在建项目',
|
||||
value: '28',
|
||||
unit: '个',
|
||||
iconPath: '/src/assets/images/beUnder.png'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '合同总额',
|
||||
value: '288.88',
|
||||
unit: '亿元',
|
||||
iconPath: '/src/assets/images/contract.png'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: '总容量',
|
||||
value: '158.88',
|
||||
unit: '个',
|
||||
iconPath: '/src/assets/images/totalCapacity.png'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: '今日施工',
|
||||
value: '18',
|
||||
unit: '个',
|
||||
iconPath: '/src/assets/images/todayConstruction.png'
|
||||
}
|
||||
]);
|
||||
|
||||
const news = ref([]);
|
||||
const newDetail = ref({
|
||||
title: '',
|
||||
content: ''
|
||||
});
|
||||
const newId = ref('');
|
||||
const attendanceCount = ref(0);
|
||||
const attendanceRate = ref(0);
|
||||
const peopleCount = ref(0);
|
||||
const teamAttendanceList = ref([{ id: '', teamName: '', attendanceNumber: 0, allNumber: 0, attendanceRate: 0, attendanceTime: '' }]);
|
||||
|
||||
// 项目出勤率数据
|
||||
const projectAttendanceData = ref([
|
||||
{ name: 'A项目', value: 62 },
|
||||
{ name: 'B项目', value: 56 },
|
||||
{ name: 'C项目', value: 95 },
|
||||
{ name: 'D项目', value: 64 },
|
||||
{ name: 'E项目', value: 97.5 }
|
||||
]);
|
||||
|
||||
let attendanceChart = null;
|
||||
const attendanceChartRef = ref<HTMLDivElement | null>(null);
|
||||
|
||||
/**
|
||||
* 获取项目人员出勤数据
|
||||
*/
|
||||
const getPeopleData = async () => {
|
||||
const res = await getScreenPeople(props.projectId);
|
||||
const { data, code } = res;
|
||||
if (code === 200) {
|
||||
attendanceCount.value = data.attendanceCount;
|
||||
attendanceRate.value = data.attendanceRate;
|
||||
peopleCount.value = data.peopleCount;
|
||||
teamAttendanceList.value = data.teamAttendanceList;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取企业关键指标数据
|
||||
*/
|
||||
const getKeyIndexData = async () => {
|
||||
const res = await keyIndex();
|
||||
const { data, code } = res;
|
||||
if (code === 200) {
|
||||
// 更新指标数据,使用接口返回的指定字段
|
||||
indicators.value[0].value = data.ongoingProject || 0;
|
||||
indicators.value[1].value = data.totalContractAmount || 0;
|
||||
indicators.value[2].value = data.totalCapacity || 0;
|
||||
indicators.value[3].value = data.todayProject || 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化项目出勤率柱状图(美化版)
|
||||
*/
|
||||
const initAttendanceChart = () => {
|
||||
if (!attendanceChartRef.value) {
|
||||
return;
|
||||
}
|
||||
attendanceChart = echarts.init(attendanceChartRef.value);
|
||||
|
||||
const option = {
|
||||
backgroundColor: 'transparent',
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
shadowStyle: {
|
||||
color: 'rgba(29, 214, 255, 0.1)'
|
||||
}
|
||||
},
|
||||
backgroundColor: 'rgba(10, 24, 45, 0.8)',
|
||||
borderColor: 'rgba(29, 214, 255, 0.3)',
|
||||
borderWidth: 1,
|
||||
textStyle: {
|
||||
color: '#e6f7ff'
|
||||
},
|
||||
formatter: (params) => {
|
||||
const data = params[0];
|
||||
return `${data.name}<br/>出勤率: ${data.value}%`;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top: 40,
|
||||
right: 30,
|
||||
bottom: 40,
|
||||
left: 30,
|
||||
containLabel: true,
|
||||
backgroundColor: 'rgba(10, 24, 45, 0.1)',
|
||||
borderColor: 'rgba(29, 214, 255, 0.1)',
|
||||
borderWidth: 1
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: projectAttendanceData.value.map((item) => item.name),
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(29, 214, 255, 0.3)'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#e6f7ff',
|
||||
fontSize: 14,
|
||||
interval: 0,
|
||||
fontWeight: 'bold',
|
||||
padding: [10, 0, 0, 0]
|
||||
},
|
||||
axisTick: {
|
||||
show: true,
|
||||
length: 5,
|
||||
lineStyle: {
|
||||
color: 'rgba(29, 214, 255, 0.5)'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: 100,
|
||||
interval: 20,
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(29, 214, 255, 0.3)'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#e6f7ff',
|
||||
fontSize: 12,
|
||||
formatter: '{value}%',
|
||||
padding: [0, 10, 0, 0]
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(29, 214, 255, 0.15)',
|
||||
type: 'dashed'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: projectAttendanceData.value.map((item) => item.value),
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
color: function (params) {
|
||||
// 根据数值动态调整渐变效果
|
||||
const value = params.value;
|
||||
const baseColor = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(29, 214, 255, 1)' },
|
||||
{ offset: 1, color: 'rgba(10, 120, 200, 0.8)' }
|
||||
]);
|
||||
return baseColor;
|
||||
},
|
||||
borderRadius: [5, 5, 0, 0],
|
||||
borderColor: 'rgba(255, 255, 255, 0.3)',
|
||||
borderWidth: 1
|
||||
},
|
||||
barWidth: '45%',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
color: '#e6f7ff',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
formatter: '{c}%',
|
||||
offset: [0, -10]
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(29, 214, 255, 1)' },
|
||||
{ offset: 1, color: 'rgba(10, 120, 200, 1)' }
|
||||
]),
|
||||
shadowBlur: 10,
|
||||
shadowColor: 'rgba(29, 214, 255, 0.5)',
|
||||
borderColor: 'rgba(255, 255, 255, 0.5)'
|
||||
},
|
||||
label: {
|
||||
color: '#ffffff',
|
||||
textShadowBlur: 2,
|
||||
textShadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
},
|
||||
animationDelay: function (idx) {
|
||||
// 动画延迟,使柱子依次出现
|
||||
return idx * 100;
|
||||
}
|
||||
}
|
||||
],
|
||||
// 添加动画效果
|
||||
animationEasing: 'elasticOut',
|
||||
animationDelayUpdate: function (idx) {
|
||||
return idx * 5;
|
||||
},
|
||||
// 添加单位标签
|
||||
graphic: [
|
||||
{
|
||||
type: 'text',
|
||||
left: 10,
|
||||
top: 10,
|
||||
style: {
|
||||
text: '单位: %',
|
||||
fill: '#8ab2ff',
|
||||
fontSize: 12
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
attendanceChart.setOption(option);
|
||||
|
||||
// 添加窗口大小变化时的图表更新
|
||||
const handleResize = () => {
|
||||
if (attendanceChart) {
|
||||
attendanceChart.resize();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// 清理函数
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化地图
|
||||
*/
|
||||
const initMapChart = () => {
|
||||
if (!mapChartRef.value) {
|
||||
return;
|
||||
}
|
||||
mapChart = echarts.init(mapChartRef.value);
|
||||
mapChart.setOption(mapOption);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// nextTick(() => {
|
||||
// initMapChart();
|
||||
// });
|
||||
getPeopleData();
|
||||
getKeyIndexData();
|
||||
|
||||
// 初始化项目出勤率柱状图
|
||||
setTimeout(() => {
|
||||
initAttendanceChart();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// if (mapChart) {
|
||||
// mapChart.dispose();
|
||||
// mapChart = null;
|
||||
// }
|
||||
|
||||
if (attendanceChart) {
|
||||
attendanceChart.dispose();
|
||||
attendanceChart = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.leftPage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.topPage,
|
||||
.endPage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 15px 0;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.endPage {
|
||||
flex: 1;
|
||||
margin-top: 23px;
|
||||
}
|
||||
|
||||
.project_attendance_chart {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 15px 0;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
box-sizing: border-box;
|
||||
|
||||
.chart_title {
|
||||
font-size: 16px;
|
||||
color: #e6f7ff;
|
||||
margin-bottom: 15px;
|
||||
text-align: left;
|
||||
}
|
||||
.chart_content {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.indicators {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 15px;
|
||||
margin-top: 15px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.indicator-card {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
background: rgba(10, 24, 45, 0.7);
|
||||
border: 1px solid rgba(29, 214, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.indicator-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, rgba(29, 214, 255, 0.2) 0%, rgba(29, 214, 255, 0.6) 50%, rgba(29, 214, 255, 0.2) 100%);
|
||||
}
|
||||
|
||||
.indicator-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #e6f7ff;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.indicator-unit {
|
||||
font-size: 14px;
|
||||
color: #8ab2ff;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.indicator-name {
|
||||
font-size: 14px;
|
||||
color: #e6f7ff;
|
||||
}
|
||||
|
||||
.indicator-icon {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.indicator-icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.map {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.attendance_tag {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 30px;
|
||||
margin-top: 15px;
|
||||
|
||||
.tag_item {
|
||||
width: 28%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
border: 1px dashed rgba(29, 214, 255, 0.3);
|
||||
padding: 10px;
|
||||
|
||||
.tag_info {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: rgba(230, 247, 255, 1);
|
||||
text-shadow: 0px 1.24px 6.21px rgba(0, 190, 247, 1);
|
||||
}
|
||||
|
||||
.tag_title {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: rgba(230, 247, 255, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attendance_list {
|
||||
padding: 0px 30px;
|
||||
font-size: 14px;
|
||||
|
||||
.attendance_item {
|
||||
display: grid;
|
||||
grid-template-columns: 3fr 2fr 2fr 3fr;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.subfont {
|
||||
color: rgba(138, 149, 165, 1);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,216 @@
|
||||
export let pieOption = {
|
||||
// 定义中心文字
|
||||
graphic: [
|
||||
// {
|
||||
// type: 'text',
|
||||
// left: 'center',
|
||||
// top: '40%',
|
||||
// style: {
|
||||
// // 需要从接口替换
|
||||
// text: '70%',
|
||||
// fontSize: 24,
|
||||
// fontWeight: 'bold',
|
||||
// fill: '#fff'
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// type: 'text',
|
||||
// left: 'center',
|
||||
// top: '50%',
|
||||
// style: {
|
||||
// text: '111',
|
||||
// fontSize: 14,
|
||||
// fill: '#fff'
|
||||
// }
|
||||
// }
|
||||
],
|
||||
// legend: {
|
||||
// show: true,
|
||||
// type: 'plain',
|
||||
// bottom: 20,
|
||||
// itemWidth: 12,
|
||||
// itemHeight: 12,
|
||||
// textStyle: {
|
||||
// color: '#fff'
|
||||
// }
|
||||
// },
|
||||
series: {
|
||||
type: 'pie',
|
||||
data: [],
|
||||
radius: [50, 80],
|
||||
center: ['50%', '45%'],
|
||||
// itemStyle: {
|
||||
// borderColor: '#fff',
|
||||
// borderWidth: 1
|
||||
// },
|
||||
label: {
|
||||
alignTo: 'edge',
|
||||
formatter: function (params) {
|
||||
// 只显示前三个数据项
|
||||
return `{name|${params.data.name}}\n{percent|${params.data.completionRate}MW}`;
|
||||
},
|
||||
minMargin: 10,
|
||||
edgeDistance: 20,
|
||||
lineHeight: 15,
|
||||
rich: {
|
||||
name: {
|
||||
fontSize: 12,
|
||||
color: '#fff'
|
||||
},
|
||||
percent: {
|
||||
fontSize: 12,
|
||||
color: '#fff'
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 'bottom'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export let barOption = {
|
||||
legend: {
|
||||
icon: 'rect',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
// 调整文字与图标间距
|
||||
data: ['计划产值', '实际产值'],
|
||||
top: 0,
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
show: true,
|
||||
backgroundColor: '',
|
||||
trigger: 'axis',
|
||||
// formatter: '{b0}:{c0}万元',
|
||||
formatter: (params: any) => {
|
||||
// params 是数组,对应每条柱子
|
||||
return params
|
||||
.map((p: any) => `${p.seriesName}:${Number(p.value).toFixed(2)} 亿元`)
|
||||
|
||||
.join('<br/>');
|
||||
},
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
axisPointer: {
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow',
|
||||
}
|
||||
// borderColor: 'rgba(252, 217, 18, 1)'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
|
||||
axisLabel: {
|
||||
color: '#fff'
|
||||
},
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
name: '单位:亿元',
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}'
|
||||
},
|
||||
splitLine: {
|
||||
show: false // 不显示分割线
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '12%',
|
||||
top: '15%', // 顶部留一点空间给 legend
|
||||
bottom: '8%',
|
||||
right: '2%'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '计划产值',
|
||||
type: 'bar',
|
||||
data: [],
|
||||
barWidth: '10',
|
||||
itemStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 1, // 修改y为1表示从底部开始
|
||||
x2: 0,
|
||||
y2: 0, // 修改y2为0表示渐变到顶部
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(255, 209, 92, 0.1)' // 底部透明度0.1
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(255, 209, 92, 1)' // 顶部透明度1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '实际产值',
|
||||
type: 'bar',
|
||||
data: [],
|
||||
barWidth: '10',
|
||||
itemStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 1, // 从底部开始
|
||||
x2: 0,
|
||||
y2: 0, // 到顶部结束
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(7, 209, 250, 0.1)' // 底部透明度0.1
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(7, 209, 250, 1)' // 顶部透明度1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let mapOption = {
|
||||
geo: {
|
||||
map: 'ch',
|
||||
roam: true,
|
||||
aspectScale: Math.cos((47 * Math.PI) / 180)
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'graph',
|
||||
coordinateSystem: 'geo',
|
||||
data: [
|
||||
{ name: 'a', value: [7.667821250000001, 46.791734269956265] },
|
||||
{ name: 'b', value: [7.404848750000001, 46.516308805996054] },
|
||||
{ name: 'c', value: [7.376673125000001, 46.24728858538375] },
|
||||
{ name: 'd', value: [8.015320625000001, 46.39460918238572] },
|
||||
{ name: 'e', value: [8.616400625, 46.7020608630855] },
|
||||
{ name: 'f', value: [8.869981250000002, 46.37539345234199] },
|
||||
{ name: 'g', value: [9.546196250000001, 46.58676648282309] },
|
||||
{ name: 'h', value: [9.311399375, 47.182454114178896] },
|
||||
{ name: 'i', value: [9.085994375000002, 47.55395822835779] },
|
||||
{ name: 'j', value: [8.653968125000002, 47.47709530818285] },
|
||||
{ name: 'k', value: [8.203158125000002, 47.44506909144329] }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
@ -0,0 +1,392 @@
|
||||
<template>
|
||||
<div class="leftPage">
|
||||
<div class="topPage">
|
||||
<Title title="项目进度分析" />
|
||||
<div class="progress">
|
||||
<div class="progress_item">
|
||||
<div class="progress_imgBox">
|
||||
<div class="progress_img">
|
||||
<img src="@/assets/large/capacity.png" style="width: 100%; height: 100%" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress_text">
|
||||
<div class="progress_text_title">
|
||||
<div>{{ capacityData.gridConnectedCapacity ?? '0' }}</div>
|
||||
<div>MW</div>
|
||||
</div>
|
||||
<div class="content_text">井网总容量</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress_item">
|
||||
<div class="progress_imgBox">
|
||||
<div class="progress_img">
|
||||
<img src="@/assets/large/plan.png" style="width: 100%; height: 100%" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress_text">
|
||||
<div class="progress_text_title">
|
||||
<div>{{ capacityData.plannedCapacity ?? '0' }}</div>
|
||||
<div>MW</div>
|
||||
</div>
|
||||
<div class="content_text">计划总容量</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress_item">
|
||||
<div class="progress_imgBox">
|
||||
<div class="progress_img">
|
||||
<img src="@/assets/large/delay.png" style="width: 100%; height: 100%" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress_text">
|
||||
<div class="progress_text_title">
|
||||
<div>{{ capacityData.delayedProjectCount ?? '0' }}</div>
|
||||
<div>个</div>
|
||||
</div>
|
||||
<div class="content_text">延期项目</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="projectItem">
|
||||
<div class="chart_container">
|
||||
<div ref="pieChartRef" class="echart" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="output">
|
||||
<Title title="实际产值与预期产值对比" />
|
||||
<div class="chart_container">
|
||||
<div ref="lineChartRef" class="echart" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import Title from './title.vue';
|
||||
import * as echarts from 'echarts';
|
||||
import { pieOption, barOption } from './optionList';
|
||||
import { projectProgress, outpuProgress } from '@/api/outputApi';
|
||||
const capacityData: any = ref({});
|
||||
const props = defineProps({
|
||||
projectId: {
|
||||
type: String,
|
||||
default: 0
|
||||
}
|
||||
});
|
||||
|
||||
const generalize = ref();
|
||||
// 饼图相关
|
||||
const pieChartRef = ref<HTMLDivElement | null>(null);
|
||||
let pieChart: any = null;
|
||||
const totalPercent = ref(0);
|
||||
// 折线图相关
|
||||
const lineChartRef = ref<HTMLDivElement | null>(null);
|
||||
let lineChart: any = null;
|
||||
// 土地数据 折线图
|
||||
const designAreaData = ref([]);
|
||||
const transferAreaData = ref([]);
|
||||
const barNames = ref([]);
|
||||
// // 饼图数据
|
||||
// const pieData = [
|
||||
// { label: 'areaPercentage', name: '厂区', value: 0 },
|
||||
// { label: 'roadPercentage', name: '道路', value: 0 },
|
||||
// { label: 'collectorLinePercentage', name: '集电线路', value: 0 },
|
||||
// { label: 'exportLinePercentage', name: '送出线路', value: 0 },
|
||||
// { label: 'substationPercentage', name: '升压站', value: 0 },
|
||||
// { label: 'boxTransformerPercentage', name: '箱变', value: 0 }
|
||||
// ];
|
||||
|
||||
// 响应窗口大小变化
|
||||
const handleResize = () => {
|
||||
if (pieChart) pieChart.resize();
|
||||
if (lineChart) lineChart.resize();
|
||||
};
|
||||
|
||||
const processedDataList = ref([]);
|
||||
//获取数据
|
||||
const getData = async () => {
|
||||
const res = await projectProgress();
|
||||
if (res.code == 200) {
|
||||
capacityData.value = res.data;
|
||||
// processedDataList.value = res.data.projectProgressDetailList;
|
||||
let totalCapacity = 0;
|
||||
const processedData = res.data.projectProgressDetailList.map((item) => {
|
||||
const capacity = parseInt(item.projectCapacity) || 0;
|
||||
totalCapacity += capacity;
|
||||
return {
|
||||
name: item.projectName,
|
||||
value: capacity,
|
||||
completionRate: item.completionRate
|
||||
};
|
||||
});
|
||||
|
||||
// 计算每个项目的百分比
|
||||
processedData.forEach((item) => {
|
||||
item.percentage = totalCapacity > 0 ? ((item.value / totalCapacity) * 100).toFixed(2) : '0%';
|
||||
});
|
||||
processedDataList.value = processedData;
|
||||
initPieChart();
|
||||
}
|
||||
};
|
||||
// 初始化饼图
|
||||
const initPieChart = () => {
|
||||
if (!pieChartRef.value) {
|
||||
console.error('未找到饼图容器元素');
|
||||
return;
|
||||
}
|
||||
const data = processedDataList.value.map((item: any) => {
|
||||
return {
|
||||
name: item.name,
|
||||
value: item.percentage,
|
||||
completionRate: item.value
|
||||
};
|
||||
});
|
||||
pieOption.series.data = data;
|
||||
|
||||
// pieOption.graphic[0].style.text = totalPercent.value + '%';
|
||||
pieChart = echarts.init(pieChartRef.value, null, {
|
||||
renderer: 'canvas',
|
||||
useDirtyRect: false
|
||||
});
|
||||
pieChart.setOption(pieOption);
|
||||
};
|
||||
//获取产值数据
|
||||
const getOutputData = async () => {
|
||||
const res = await outpuProgress();
|
||||
if (res.code == 200) {
|
||||
designAreaData.value = res.data.map((item: any) => Number(item.planValue));
|
||||
transferAreaData.value = res.data.map((item: any) => Number(item.actualValue));
|
||||
barNames.value = res.data.map((item: any) => item.projectName);
|
||||
initLineChart();
|
||||
}
|
||||
};
|
||||
// 初始化柱状图图
|
||||
const initLineChart = () => {
|
||||
if (!lineChartRef.value) {
|
||||
console.error('未找到柱状图容器元素');
|
||||
return;
|
||||
}
|
||||
console.log(barOption);
|
||||
barOption.xAxis.data = barNames.value;
|
||||
barOption.series[0].data = designAreaData.value;
|
||||
barOption.series[1].data = transferAreaData.value;
|
||||
lineChart = echarts.init(lineChartRef.value, null, {
|
||||
renderer: 'canvas',
|
||||
useDirtyRect: false
|
||||
});
|
||||
lineChart.setOption(barOption);
|
||||
};
|
||||
// /**
|
||||
// * 获取项目土地统计数据
|
||||
// */
|
||||
// const getScreenLandData = async () => {
|
||||
// const res = await getScreenLand(props.projectId);
|
||||
// const { data, code } = res;
|
||||
// if (code === 200) {
|
||||
// designAreaData.value = data.map((item: any) => Number(item.designArea));
|
||||
// transferAreaData.value = data.map((item: any) => Number(item.transferArea));
|
||||
// // initLineChart();
|
||||
// }
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * 获取项目形象进度数据
|
||||
// */
|
||||
// const getScreenImgProcessData = async () => {
|
||||
// const res = await getScreenImgProcess(props.projectId);
|
||||
// const { data, code } = res;
|
||||
// if (code === 200) {
|
||||
// totalPercent.value = data.totalPercentage;
|
||||
// pieData.forEach((item: any) => {
|
||||
// item.value = data[item.label];
|
||||
// });
|
||||
// initPieChart();
|
||||
// }
|
||||
// };
|
||||
|
||||
// /**
|
||||
// * 获取项目概况数据
|
||||
// */
|
||||
// const getScreenGeneralizeData = async () => {
|
||||
// const res = await getScreenGeneralize(props.projectId);
|
||||
// const { data, code } = res;
|
||||
// if (code === 200) {
|
||||
// generalize.value = data;
|
||||
// }
|
||||
// };
|
||||
|
||||
// 组件挂载时初始化图表
|
||||
onMounted(() => {
|
||||
// getScreenLandData();
|
||||
// getScreenImgProcessData();
|
||||
// getScreenGeneralizeData();
|
||||
getData();
|
||||
getOutputData();
|
||||
nextTick(() => {
|
||||
initPieChart();
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
});
|
||||
|
||||
// 组件卸载时清理
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
if (pieChart) {
|
||||
pieChart.dispose();
|
||||
pieChart = null;
|
||||
}
|
||||
if (lineChart) {
|
||||
lineChart.dispose();
|
||||
lineChart = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.leftPage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.topPage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 15px 0 0 0;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
box-sizing: border-box;
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
// .content {
|
||||
// height: 100px;
|
||||
// margin: 0 15px;
|
||||
// padding: 0 10px;
|
||||
// margin-top: 15px;
|
||||
// box-sizing: border-box;
|
||||
// overflow-y: auto;
|
||||
|
||||
// &::-webkit-scrollbar-track {
|
||||
// background: rgba(204, 204, 204, 0.1);
|
||||
// border-radius: 10px;
|
||||
// }
|
||||
|
||||
// &::-webkit-scrollbar-thumb {
|
||||
// background: rgba(29, 214, 255, 0.78);
|
||||
// border-radius: 10px;
|
||||
// }
|
||||
|
||||
// .content_item {
|
||||
// font-size: 14px;
|
||||
// font-weight: 400;
|
||||
// color: rgba(230, 247, 255, 1);
|
||||
// margin-bottom: 10px;
|
||||
|
||||
// &:last-child {
|
||||
// margin-bottom: 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
.progress {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-gap: 10px;
|
||||
.progress_item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// background: rgba(29, 214, 255, 1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
.progress_imgBox {
|
||||
width: 100%;
|
||||
height: 35%;
|
||||
position: relative;
|
||||
.progress_img {
|
||||
width: 84px;
|
||||
height: 48px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 80%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.progress_text {
|
||||
width: 100%;
|
||||
height: 65%;
|
||||
background: rgba(29, 214, 255, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
padding: 15px 5px 5px 5px;
|
||||
.progress_text_title {
|
||||
width: 100%;
|
||||
// height: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
& > div:first-child {
|
||||
// 第一个子元素的样式
|
||||
width: 50%;
|
||||
font-size: 24px;
|
||||
// font-weight: bold;
|
||||
font-family: 'AlimamaShuHeiTi', sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
& > div:last-child {
|
||||
// 最后一个子元素的样式
|
||||
width: 50%;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.content_text {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: #c6d1db;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.projectItem {
|
||||
width: 100%;
|
||||
height: 40%;
|
||||
// background: rgba(29, 214, 255, 1);
|
||||
padding: 10px 10px 10px 0;
|
||||
// border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
.chart_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.echart {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.output {
|
||||
width: 100%;
|
||||
height: 40%;
|
||||
// background: rgba(29, 214, 255, 0.5);
|
||||
padding: 10px 10px 10px 0;
|
||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||
|
||||
.chart_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.echart {
|
||||
height: 90%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="title">
|
||||
<div class="title_icon">
|
||||
<img src="@/assets/projectLarge/section.svg" alt="" />
|
||||
<img src="@/assets/projectLarge/border.svg" alt="" />
|
||||
</div>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div>{{ title }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '标题'
|
||||
|
||||
},
|
||||
prefix: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
font-family: 'AlimamaShuHeiTi', sans-serif;
|
||||
|
||||
.title_icon {
|
||||
position: relative;
|
||||
|
||||
& > img:last-child {
|
||||
position: absolute;
|
||||
bottom: 4px;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -22,11 +22,10 @@ import leftPage from './components/leftPage.vue';
|
||||
import centerPage from './components/centerPage.vue';
|
||||
import rightPage from './components/rightPage.vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
|
||||
const userStore = useUserStoreHook();
|
||||
const projectId = computed(() => userStore.selectedProject.id);
|
||||
const isFull = ref(false)
|
||||
const isHideOther = ref(false)
|
||||
const isFull = ref(false);
|
||||
const isHideOther = ref(false);
|
||||
|
||||
/**
|
||||
* 切换中心页面全屏
|
||||
@ -41,7 +40,7 @@ const handleChangePage = () => {
|
||||
isFull.value = true;
|
||||
isHideOther.value = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
@ -140,9 +140,9 @@ const createEarth = () => {
|
||||
// 加载底图
|
||||
loadBaseMap(earthInstance.viewer);
|
||||
|
||||
// 可以取消注释以下代码来设置初始视角
|
||||
// // 可以取消注释以下代码来设置初始视角
|
||||
// YJ.Global.flyTo(earthInstance, view);
|
||||
// YJ.Global.setDefaultView(earthInstance.viewer, view)
|
||||
// YJ.Global.setDefaultView(earthInstance.viewer, view);
|
||||
|
||||
// 地球创建完成后获取并渲染轨迹数据
|
||||
getTrajectoryData();
|
||||
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
|
||||
:leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
|
||||
@ -12,15 +11,25 @@
|
||||
<el-input v-model="queryParams.formalitiesId" placeholder="请输入手续办理清单模板id" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="计划开始时间" prop="planTheStartTime">
|
||||
<el-date-picker clearable v-model="queryParams.planTheStartTime" type="date" value-format="YYYY-MM-DD"
|
||||
placeholder="请选择计划开始时间" />
|
||||
<el-date-picker
|
||||
clearable
|
||||
v-model="queryParams.planTheStartTime"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择计划开始时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="head">
|
||||
<el-input v-model="queryParams.head" placeholder="请输入负责人" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="实际完成时间" prop="actualCompletionTime">
|
||||
<el-date-picker clearable v-model="queryParams.actualCompletionTime" type="date" value-format="YYYY-MM-DD"
|
||||
placeholder="请选择实际完成时间" />
|
||||
<el-date-picker
|
||||
clearable
|
||||
v-model="queryParams.actualCompletionTime"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择实际完成时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="手续材料" prop="formalitiesUrl">
|
||||
<el-input v-model="queryParams.formalitiesUrl" placeholder="请输入手续材料" clearable @keyup.enter="handleQuery" />
|
||||
@ -38,13 +47,15 @@
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd()"
|
||||
v-hasPermi="['formalities:formalitiesAreConsolidated:getTree']">新增</el-button>
|
||||
<span style="margin-left: 10px"><el-tooltip class="box-item" effect="dark" content="从原有模板列表选择新增"
|
||||
placement="top">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['formalities:formalitiesAreConsolidated:getTree']"
|
||||
>新增</el-button
|
||||
>
|
||||
<span style="margin-left: 10px"
|
||||
><el-tooltip class="box-item" effect="dark" content="从原有模板列表选择新增" placement="top">
|
||||
<el-icon color="#409efc">
|
||||
<WarningFilled />
|
||||
</el-icon> </el-tooltip></span>
|
||||
</el-icon> </el-tooltip
|
||||
></span>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-hasPermi="['formalities:listOfFormalities:list']">
|
||||
<el-button type="primary" plain icon="Plus" @click="addTemplate()">新增数据</el-button>
|
||||
@ -71,11 +82,20 @@
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="formalitiesAreConsolidatedList" @selection-change="handleSelectionChange"
|
||||
row-key="id" default-expand-all>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:table-layout="'auto'"
|
||||
:data="formalitiesAreConsolidatedList"
|
||||
@selection-change="handleSelectionChange"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="手续办理清单模板父级" align="center" prop="formalitiesPname" /> -->
|
||||
<el-table-column label="手续办理清单" align="left" prop="formalitiesName" />
|
||||
<el-table-column label="手续办理清单" align="left" prop="formalitiesName">
|
||||
<template #default="scope">
|
||||
{{ scope.row.formalitiesName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划开始时间" align="center" prop="planTheStartTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.planTheStartTime, '{y}-{m}-{d}') }}</span>
|
||||
@ -95,52 +115,58 @@
|
||||
<el-table-column label="办理状态" align="center" prop="processingStatus" />
|
||||
<el-table-column label="手续材料" align="center" prop="formalitiesUrl" width="180">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; justify-content: center; align-items: center;">
|
||||
|
||||
|
||||
<div>
|
||||
<el-link type="primary" :underline="false" @click="handlePreview(scope.row)" target="_blank"
|
||||
v-if="scope.row.formalitiesPid">查看</el-link>
|
||||
<div style="display: flex; justify-content: center; align-items: center">
|
||||
<div style="width: 30px">
|
||||
<el-link type="primary" :underline="false" @click="handlePreview(scope.row)" target="_blank" v-if="scope.row.formalitiesPid"
|
||||
>查看</el-link
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<el-badge v-if="scope.row.fileCount" :value="scope.row.fileCount" class="item" type="danger">
|
||||
</el-badge>
|
||||
<div style="width: 5px">
|
||||
<el-badge v-if="scope.row.fileCount" :value="scope.row.fileCount" class="item" type="danger"> </el-badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<el-table-column label="操作" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.formalitiesPid">
|
||||
<el-button link type="primary" icon="Edit" v-if="scope.row.processingStatus != '已完成'"
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
v-if="scope.row.processingStatus != '已完成'"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['formalities:formalitiesAreConsolidated:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Upload" v-if="scope.row.processingStatus != '已完成'"
|
||||
@click="handleUpload(scope.row)">上传</el-button>
|
||||
<el-button link type="primary" icon="EditPen" @click="handleUpdateStatus(scope.row)"
|
||||
v-hasPermi="['formalities:formalitiesAreConsolidated:edit']">修改状态</el-button>
|
||||
v-hasPermi="['formalities:formalitiesAreConsolidated:edit']"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button link type="primary" icon="Upload" v-if="scope.row.processingStatus != '已完成'" @click="handleUpload(scope.row)"
|
||||
>上传</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="EditPen"
|
||||
@click="handleUpdateStatus(scope.row)"
|
||||
v-hasPermi="['formalities:formalitiesAreConsolidated:edit']"
|
||||
>修改状态</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
<!-- 添加或修改合规性手续合账对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="formalitiesAreConsolidatedFormRef" :model="form" :rules="rules" label-width="160px">
|
||||
<el-form-item label="计划开始时间" prop="planTheStartTime">
|
||||
<el-date-picker clearable v-model="form.planTheStartTime" type="date" value-format="YYYY-MM-DD"
|
||||
placeholder="请选择计划开始时间">
|
||||
<el-date-picker clearable v-model="form.planTheStartTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择计划开始时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="计划完成时间" prop="planTheStartTime">
|
||||
<el-date-picker clearable v-model="form.planTheEndTime" type="date" value-format="YYYY-MM-DD"
|
||||
placeholder="请选择计划完成时间">
|
||||
<el-date-picker clearable v-model="form.planTheEndTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择计划完成时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="head">
|
||||
@ -162,8 +188,7 @@
|
||||
<el-table :data="fileList" style="width: 100%" border v-loading="fileLoading">
|
||||
<el-table-column prop="fileName" label="文件" align="center">
|
||||
<template #default="scope">
|
||||
<el-link :key="scope.row.annexUrl" :href="scope.row.annexUrl" target="_blank" type="primary"
|
||||
:underline="false">
|
||||
<el-link :key="scope.row.annexUrl" :href="scope.row.annexUrl" target="_blank" type="primary" :underline="false">
|
||||
{{ scope.row.fileName || '查看文件' }}
|
||||
</el-link>
|
||||
</template>
|
||||
@ -174,8 +199,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="fileTotal > 0" :total="fileTotal" v-model:page="fileParams.pageNum"
|
||||
v-model:limit="fileParams.pageSize" @pagination="getFileList" />
|
||||
<pagination
|
||||
v-show="fileTotal > 0"
|
||||
:total="fileTotal"
|
||||
v-model:page="fileParams.pageNum"
|
||||
v-model:limit="fileParams.pageSize"
|
||||
@pagination="getFileList"
|
||||
/>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button type="primary" @click="viewVisible = false">关闭</el-button>
|
||||
@ -185,9 +215,18 @@
|
||||
<!-- 上传文件对话框 -->
|
||||
<el-dialog draggable title="上传文件" v-model="fileVisible" width="450">
|
||||
<el-form-item label="上传文件" prop="processingStatus">
|
||||
<file-upload v-model="file" ref="uploadRef" uploadUrl="/formalities/formalitiesAnnex"
|
||||
v-hasPermi="['formalities:formalitiesAnnex:add']" :data="{ formalitiesId: form.id }" :fileType="['pdf']"
|
||||
:auto-upload="false" showFileList method="put" :onUploadSuccess="handleUploadSuccess" />
|
||||
<file-upload
|
||||
v-model="file"
|
||||
ref="uploadRef"
|
||||
uploadUrl="/formalities/formalitiesAnnex"
|
||||
v-hasPermi="['formalities:formalitiesAnnex:add']"
|
||||
:data="{ formalitiesId: form.id }"
|
||||
:fileType="['pdf']"
|
||||
:auto-upload="false"
|
||||
showFileList
|
||||
method="put"
|
||||
:onUploadSuccess="handleUploadSuccess"
|
||||
/>
|
||||
</el-form-item>
|
||||
<template #footer>
|
||||
<span>
|
||||
@ -215,14 +254,18 @@
|
||||
</el-dialog>
|
||||
<el-dialog title="新增合规性手续合账" v-model="templateVisbile" width="450">
|
||||
<el-form-item label="合规性手续模板">
|
||||
<el-cascader v-model="tempValue" :options="tempTreeList" :props="{
|
||||
multiple: true,
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
disabled: (node: any) => {
|
||||
return (node.pid == 0 && !node.children.length) || node.status == 1; // 有 parent 的是二级,没有 parent 的是一级,禁用一级
|
||||
}
|
||||
}" />
|
||||
<el-cascader
|
||||
v-model="tempValue"
|
||||
:options="tempTreeList"
|
||||
:props="{
|
||||
multiple: true,
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
disabled: (node: any) => {
|
||||
return (node.pid == 0 && !node.children.length) || node.status == 1; // 有 parent 的是二级,没有 parent 的是一级,禁用一级
|
||||
}
|
||||
}"
|
||||
/>
|
||||
<div style="margin-left: 10px; display: flex; justify-content: center; align-items: center">
|
||||
<el-tooltip class="box-item" effect="dark" content="列表上已选择得模版不可再选" placement="top">
|
||||
<el-icon>
|
||||
@ -248,8 +291,7 @@
|
||||
<el-option v-for="item in listOfFormalitiesList" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" prop="formalitiesName"
|
||||
:rules="[{ required: true, message: '请输入名称', trigger: 'blur' }]">
|
||||
<el-form-item label="名称" prop="formalitiesName" :rules="[{ required: true, message: '请输入名称', trigger: 'blur' }]">
|
||||
<el-input v-model="formTemplate.formalitiesName" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div style="font-size: 12px; padding-left: 10px">安全生产天数:</div>
|
||||
<div class="header_left_text">
|
||||
1,235
|
||||
{{ safetyDay }}
|
||||
<span style="font-size: 12px">天</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -16,14 +16,20 @@
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="top-bar">
|
||||
<!-- 左侧:天气图标 + 日期文字 -->
|
||||
<!-- 左侧:天气轮播区域 -->
|
||||
<div class="left-section">
|
||||
<img src="@/assets/large/weather.png" alt="天气图标" />
|
||||
|
||||
<span>
|
||||
<span>多云 9°/18°</span>
|
||||
<span style="padding-left: 20px"> {{ week[date.week] }} ({{ date.ymd }})</span>
|
||||
</span>
|
||||
<div class="weather-list" @mouseenter="requestPause" @mouseleave="resumeScroll">
|
||||
<div
|
||||
v-for="(item, i) in weatherList"
|
||||
:key="i"
|
||||
class="weather-item"
|
||||
:style="{ transform: `translateY(-${offsetY}px)`, transition: transition }"
|
||||
>
|
||||
<img :src="`../../../src/assets/images/${item.icon}.png`" alt="" />
|
||||
<div>{{ item.weather }}{{ item.tempMin }}°/{{ item.tempMax }}°</div>
|
||||
<div>{{ item.week }}({{ item.date }})</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分割线 -->
|
||||
<div class="divider">
|
||||
@ -41,38 +47,164 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { getSafetyDay, getWeather } from '@/api/largeScreen/index';
|
||||
|
||||
interface WeatherData {
|
||||
date: string;
|
||||
week: string;
|
||||
tempMax: string;
|
||||
tempMin: string;
|
||||
sunRise: string;
|
||||
sunSet: string;
|
||||
dayStatus: string;
|
||||
dayIcon: string;
|
||||
nightStatus: string;
|
||||
nightIcon: string;
|
||||
}
|
||||
|
||||
// 星期映射
|
||||
const week = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
|
||||
// 日期数据
|
||||
const date = ref({
|
||||
ymd: '',
|
||||
hms: '',
|
||||
week: 0
|
||||
});
|
||||
// 安全生产天数
|
||||
const safetyDay = ref('');
|
||||
// 用户存储
|
||||
const userStore = useUserStoreHook();
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
|
||||
// 天气轮播相关变量
|
||||
const weatherList = ref<WeatherData[]>([]);
|
||||
const offsetY = ref<number>(0);
|
||||
const curIndex = ref(0);
|
||||
const transition = ref('transform 0.5s ease');
|
||||
const timer = ref<number | null>(0);
|
||||
const pendingPause = ref(false);
|
||||
|
||||
// 判断当前时间是白天/夜晚
|
||||
function judgeDayOrNight(sunRise: string, sunSet: string) {
|
||||
const timeToMinutes = (timeStr: string) => {
|
||||
const [hours, minutes] = timeStr.split(':').map(Number);
|
||||
return isNaN(hours) || isNaN(minutes) ? 0 : hours * 60 + minutes;
|
||||
};
|
||||
const sunRiseMinutes = timeToMinutes(sunRise);
|
||||
const sunSetMinutes = timeToMinutes(sunSet);
|
||||
const now = new Date();
|
||||
const currentMinutes = now.getHours() * 60 + now.getMinutes();
|
||||
return currentMinutes >= sunRiseMinutes && currentMinutes <= sunSetMinutes;
|
||||
}
|
||||
|
||||
// 天气轮播逻辑:每5秒切换一次
|
||||
const setWeatherScroll = () => {
|
||||
curIndex.value += 1;
|
||||
transition.value = 'transform 0.3s ease';
|
||||
offsetY.value = curIndex.value * 60; // 每个天气项高度60px,需和样式一致
|
||||
|
||||
// 轮播到最后一项时,无缝衔接回第一项
|
||||
if (curIndex.value === weatherList.value.length - 1) {
|
||||
setTimeout(() => {
|
||||
transition.value = 'none';
|
||||
curIndex.value = 0;
|
||||
offsetY.value = 0;
|
||||
}, 350);
|
||||
}
|
||||
};
|
||||
|
||||
// 启动轮播定时器
|
||||
function startScroll() {
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
timer.value = window.setInterval(setWeatherScroll, 5000) as unknown as number;
|
||||
}
|
||||
|
||||
// 鼠标悬浮暂停轮播
|
||||
function requestPause() {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
timer.value = null;
|
||||
}
|
||||
pendingPause.value = true;
|
||||
}
|
||||
|
||||
// 鼠标离开恢复轮播
|
||||
function resumeScroll() {
|
||||
pendingPause.value = false;
|
||||
startScroll();
|
||||
}
|
||||
|
||||
// 设置实时时间
|
||||
const setTime = () => {
|
||||
let date1 = new Date();
|
||||
let year: any = date1.getFullYear();
|
||||
let month: any = date1.getMonth() + 1;
|
||||
let day: any = date1.getDate();
|
||||
let hours: any = date1.getHours();
|
||||
if (hours < 10) {
|
||||
hours = '0' + hours;
|
||||
}
|
||||
let minutes: any = date1.getMinutes();
|
||||
if (minutes < 10) {
|
||||
minutes = '0' + minutes;
|
||||
}
|
||||
let seconds: any = date1.getSeconds();
|
||||
if (seconds < 10) {
|
||||
seconds = '0' + seconds;
|
||||
}
|
||||
date.value.ymd = year + '-' + month + '-' + day;
|
||||
date.value.hms = hours + ':' + minutes + ':' + seconds;
|
||||
const date1 = new Date();
|
||||
const year = date1.getFullYear();
|
||||
const month = date1.getMonth() + 1;
|
||||
const day = date1.getDate();
|
||||
const hours = date1.getHours().toString().padStart(2, '0');
|
||||
const minutes = date1.getMinutes().toString().padStart(2, '0');
|
||||
const seconds = date1.getSeconds().toString().padStart(2, '0');
|
||||
|
||||
date.value.ymd = `${year}-${month}-${day}`;
|
||||
date.value.hms = `${hours}:${minutes}:${seconds}`;
|
||||
date.value.week = date1.getDay();
|
||||
};
|
||||
// 添加定时器,每秒更新一次时间
|
||||
const timer = setInterval(setTime, 1000);
|
||||
|
||||
// 获取天气数据
|
||||
const getWeatherData = async () => {
|
||||
try {
|
||||
if (currentProject.value?.id) {
|
||||
const res = await getWeather(currentProject.value.id);
|
||||
if (res.code === 200 && res.data && res.data.length > 0) {
|
||||
weatherList.value = res.data;
|
||||
|
||||
// 处理每一天的天气(白天/夜晚切换图标和状态)
|
||||
weatherList.value.forEach((item) => {
|
||||
const isDay = judgeDayOrNight(item.sunRise, item.sunSet);
|
||||
item.status = isDay ? item.dayStatus : item.nightStatus;
|
||||
item.icon = isDay ? item.dayIcon : item.nightIcon;
|
||||
item.tempRange = `${item.tempMin}°/${item.tempMax}°`;
|
||||
});
|
||||
|
||||
// 复制第一项实现无缝轮播
|
||||
weatherList.value = [...weatherList.value, weatherList.value[0]];
|
||||
startScroll(); // 数据加载后启动轮播
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取天气数据失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取安全生产天数
|
||||
const getSafetyDays = async () => {
|
||||
try {
|
||||
if (currentProject.value?.id) {
|
||||
const res = await getSafetyDay(currentProject.value.id);
|
||||
if (res.code === 200 && res.data) {
|
||||
safetyDay.value = res.data.safetyDay.toString();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取安全生产天数失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 组件挂载时初始化
|
||||
onMounted(() => {
|
||||
setTime(); // 初始化时间
|
||||
getSafetyDays();
|
||||
getWeatherData();
|
||||
// 时间定时器(每秒更新)
|
||||
window.setInterval(setTime, 1000);
|
||||
});
|
||||
|
||||
// 组件卸载时清除定时器
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer);
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -86,41 +218,47 @@ onUnmounted(() => {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.header_left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.header_left_img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
box-sizing: border-box;
|
||||
// padding-right: 10px;
|
||||
}
|
||||
|
||||
.header_left_text {
|
||||
font-weight: 500;
|
||||
text-shadow: 0px 1.24px 6.21px rgba(25, 179, 250, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.header_right {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #fff;
|
||||
font-family: 'AlimamaShuHeiTi', sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title > div:first-child {
|
||||
/* 第一个子元素的样式 */
|
||||
font-size: 38px;
|
||||
// font-weight: 300;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.title > div:last-child {
|
||||
/* 最后一个子元素的样式 */
|
||||
font-size: 14px;
|
||||
letter-spacing: 0.3em; /* 调整这个值来控制间距大小 */
|
||||
}
|
||||
.right {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* 顶部栏容器:Flex 水平布局 + 垂直居中 */
|
||||
.top-bar {
|
||||
width: 100%;
|
||||
@ -128,27 +266,44 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
// background-color: #1e2128;
|
||||
color: #fff;
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 左侧区域(天气 + 日期):自身也用 Flex 水平排列,确保元素在一行 */
|
||||
.left-section {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// margin-right: auto; /* 让右侧元素(管理系统)居右 */
|
||||
}
|
||||
.left-section img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 8px; /* 图标与文字间距 */
|
||||
|
||||
.weather-list {
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
|
||||
.weather-item {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > div:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 分割线(视觉分隔,可根据需求调整样式) */
|
||||
.divider {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
height: 100%; /* 根据需要调整高度 */
|
||||
gap: 2px;
|
||||
padding: 14px 10px;
|
||||
}
|
||||
|
||||
@ -165,16 +320,27 @@ onUnmounted(() => {
|
||||
background: #19b5fb;
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
/* 右侧区域(管理系统):图标 + 文字水平排列 */
|
||||
.right-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: 'AlimamaShuHeiTi', sans-serif;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.right-section img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 6px; /* 图标与文字间距 */
|
||||
margin-right: 6px;
|
||||
/* 图标与文字间距 */
|
||||
}
|
||||
|
||||
.change {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
@ -228,8 +228,13 @@ const getMaterialsListData = async () => {
|
||||
label: item.materialsName + '_' + item.createTime,
|
||||
children: []
|
||||
}));
|
||||
queryParams.value.materialsId = TreeData.value[0].id;
|
||||
getList();
|
||||
if (TreeData.value.length > 0) {
|
||||
queryParams.value.materialsId = TreeData.value[0].id;
|
||||
getList();
|
||||
} else {
|
||||
queryParams.value.materialsId = '';
|
||||
getList();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -453,7 +458,7 @@ const listeningProject: WatchStopHandle = watch(
|
||||
Object.values(childRowStates.value).forEach((state) => {
|
||||
state.queryParams.projectId = newId;
|
||||
});
|
||||
getList();
|
||||
getMaterialsListData();
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -73,12 +73,12 @@
|
||||
</el-row>
|
||||
</el-form> -->
|
||||
<el-table :data="tableData" v-loading="loading" row-key="id" border>
|
||||
<el-table-column prop="num" label="编号" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
<el-table-column align="center" prop="num" label="编号" />
|
||||
<el-table-column align="center" prop="name" label="名称" />
|
||||
<el-table-column align="center" prop="specification" label="规格" />
|
||||
<el-table-column align="center" prop="unit" label="单位" />
|
||||
<el-table-column align="center" prop="quantity" label="数量" />
|
||||
<el-table-column align="center" prop="remark" label="备注" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -214,7 +214,7 @@ const getInfo = () => {
|
||||
console.log('res.data', masterDataRes);
|
||||
Object.assign(form.value, masterDataRes?.data[0]);
|
||||
// console.log('form', form.value);
|
||||
tableData.value = res.rows.reverse();//翻转
|
||||
tableData.value = res.rows; //正序显示
|
||||
loading.value = false;
|
||||
buttonLoading.value = false;
|
||||
});
|
||||
@ -319,9 +319,7 @@ onMounted(() => {
|
||||
.el-input__inner,
|
||||
.el-select .el-input__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
@ -331,9 +329,7 @@ onMounted(() => {
|
||||
|
||||
.el-textarea__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
|
@ -123,6 +123,8 @@ function addPre() {
|
||||
|
||||
// 视频播放
|
||||
function videoPlay(obj: any) {
|
||||
console.log('objobjobj',obj);
|
||||
|
||||
getAccessToken().then((res: any) => {
|
||||
if (res.code == 200 && obj.deviceSerial) {
|
||||
flvPlayer.value = new EZUIKit.EZUIKitPlayer({
|
||||
|
@ -19,9 +19,9 @@
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['out:constructionValue:add']">新增</el-button>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
@ -39,8 +39,16 @@
|
||||
<el-table-column label="人工填报数量" align="center" prop="artificialNum" />
|
||||
<el-table-column label="无人机识别数量" align="center" prop="uavNum" />
|
||||
<el-table-column label="确认数量" align="center" prop="confirmNum" />
|
||||
<el-table-column label="对乙产值" align="center" prop="outValue" />
|
||||
<el-table-column label="对甲产值" align="center" prop="ownerValue" />
|
||||
<el-table-column label="对乙产值" align="center" prop="outValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.outValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="对甲产值" align="center" prop="ownerValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="流程状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="wf_business_status" :value="scope.row.auditStatus" />
|
||||
|
@ -24,9 +24,21 @@
|
||||
<el-table v-loading="loading" :data="monthPlanList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="计划月份" align="center" prop="planMonth" />
|
||||
<el-table-column label="计划产值" align="center" prop="planValue" />
|
||||
<el-table-column label="完成产值" align="center" prop="completeValue" />
|
||||
<el-table-column label="差额" align="center" prop="differenceValue" />
|
||||
<el-table-column label="计划产值" align="center" prop="planValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.planValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成产值" align="center" prop="completeValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.completeValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="差额" align="center" prop="differenceValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.differenceValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.type == '1'">对甲</span>
|
||||
|
@ -40,9 +40,21 @@
|
||||
<el-table v-loading="loading" :data="monthPlanList">
|
||||
<el-table-column type="index" label="序号" width="55" align="center" />
|
||||
<el-table-column label="计划月份" align="center" prop="planMonth" />
|
||||
<el-table-column label="计划产值(元)" align="center" prop="planValue" />
|
||||
<el-table-column label="完成产值(元)" align="center" prop="completeValue" />
|
||||
<el-table-column label="差额(元)" align="center" prop="differenceValue" />
|
||||
<el-table-column label="计划产值(元)" align="center" prop="planValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.planValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成产值(元)" align="center" prop="completeValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.completeValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="差额(元)" align="center" prop="differenceValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.differenceValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产值类型" align="center" prop="valueType">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="out_value_type" :value="scope.row.valueType" />
|
||||
@ -104,7 +116,7 @@
|
||||
<script setup name="MonthPlan" lang="ts">
|
||||
import { listMonthPlan, getMonthPlan, delMonthPlan, addMonthPlan, updateMonthPlan } from '@/api/out/monthPlan';
|
||||
import { MonthPlanVO } from '@/api/out/monthPlan/types';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { out_value_type } = toRefs<any>(proxy?.useDict('out_value_type'));
|
||||
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||
|
||||
|
@ -31,11 +31,27 @@
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="monthPlanAuditList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="设计产值(元)" align="center" prop="designValue" />
|
||||
<el-table-column label="采购产值(元)" align="center" prop="purchaseValue" />
|
||||
<el-table-column label="施工产值(元)" align="center" prop="constructionValue" />
|
||||
<el-table-column label="总产值(元)" align="center" prop="totalValue" />
|
||||
<el-table-column type="index" width="55" label="序号" align="center" />
|
||||
<el-table-column label="设计产值(元)" align="center" prop="designValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.designValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="采购产值(元)" align="center" prop="purchaseValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.purchaseValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="施工产值(元)" align="center" prop="constructionValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.constructionValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总产值(元)" align="center" prop="totalValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划月份" align="center" prop="planMonth" />
|
||||
</el-table>
|
||||
|
||||
|
@ -26,12 +26,32 @@
|
||||
|
||||
<el-table v-loading="loading" :data="valueAllocationList">
|
||||
<el-table-column label="项目" align="center" prop="projectName" />
|
||||
<el-table-column label="月预计产值" align="center" prop="monthEstimatedValue" />
|
||||
<el-table-column label="完成产值月合计" align="center" prop="monthCompletionValue" />
|
||||
<el-table-column label="产值差额" align="center" prop="valueDifference" />
|
||||
<el-table-column label="项目总产值" align="center" prop="totalValue" />
|
||||
<el-table-column label="累计完成产值" align="center" prop="accumulatedCompletionValue" />
|
||||
<el-table-column label="项目完成率" align="center" prop="projectCompletionRate" />
|
||||
<el-table-column label="月预计产值" align="center" prop="monthEstimatedValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.monthEstimatedValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="完成产值月合计" align="center" prop="monthCompletionValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.monthCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="产值差额" align="center" prop="valueDifference">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.valueDifference) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="项目总产值" align="center" prop="totalValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="累计完成产值" align="center" prop="accumulatedCompletionValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.accumulatedCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="项目完成率" align="center" prop="projectCompletionRate"></el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
@ -48,7 +68,7 @@
|
||||
|
||||
<script setup name="ValueAllocation" lang="ts">
|
||||
import { listOutTable } from '@/api/out/outDesignTable';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { dayjs } from 'element-plus';
|
||||
// 获取用户 store
|
||||
|
@ -23,9 +23,21 @@
|
||||
<el-card shadow="never">
|
||||
<el-table v-loading="loading" :data="tableData" v-if="activeTab == '1' || activeTab == '2'">
|
||||
<el-table-column label="项目" align="center" prop="projectName" />
|
||||
<el-table-column label="累计完工产值" align="center" prop="totalCompletionOutputValue" />
|
||||
<el-table-column label="累计结算产值" align="center" prop="totalSettlementOutputValue" />
|
||||
<el-table-column label="完工未结算额" align="center" prop="completionUnsettledAmount" />
|
||||
<el-table-column label="累计完工产值" align="center" prop="totalCompletionOutputValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalCompletionOutputValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="累计结算产值" align="center" prop="totalSettlementOutputValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalSettlementOutputValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完工未结算额" align="center" prop="completionUnsettledAmount">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.completionUnsettledAmount) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完工未结算比例" align="center" prop="completionUnsettledRatio" />
|
||||
<!-- <el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
@ -36,9 +48,21 @@
|
||||
<el-table v-loading="loading" :data="tableData" v-if="activeTab == '3'">
|
||||
<el-table-column label="项目" align="center" prop="projectName" />
|
||||
<!-- <el-table-column label="累计完工产值" align="center" prop="totalCompletionOutputValue" /> -->
|
||||
<el-table-column label="分包累计结算产值" align="center" prop="subTotalSettlementOutputValue" />
|
||||
<el-table-column label="业主累计结算产值" align="center" prop="ownerTotalSettlementOutputValue" />
|
||||
<el-table-column label="差额" align="center" prop="differenceValue" />
|
||||
<el-table-column label="分包累计结算产值" align="center" prop="subTotalSettlementOutputValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subTotalSettlementOutputValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="业主累计结算产值" align="center" prop="ownerTotalSettlementOutputValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerTotalSettlementOutputValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="差额" align="center" prop="differenceValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.differenceValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<!-- <el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="handleEdit(scope.row)" link icon="Position">联查分包结算</el-button>
|
||||
@ -47,12 +71,36 @@
|
||||
</el-table>
|
||||
<el-table v-loading="loading" :data="tableData" v-if="activeTab == '4'">
|
||||
<el-table-column label="项目" align="center" prop="projectName" />
|
||||
<el-table-column label="对甲计划总产值" align="center" prop="ownerTotal" />
|
||||
<el-table-column label="对乙计划总产值" align="center" prop="subTotal" />
|
||||
<el-table-column label="对甲月计划产值" align="center" prop="ownerPlanTotal" />
|
||||
<el-table-column label="对乙月计划产值" align="center" prop="subPlanTotal" />
|
||||
<el-table-column label="对甲月实际产值" align="center" prop="ownerActualTotal" />
|
||||
<el-table-column label="对乙月实际产值" align="center" prop="subActualTotal" />
|
||||
<el-table-column label="对甲计划总产值" align="center" prop="ownerTotal">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerTotal) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙计划总产值" align="center" prop="subTotal">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subTotal) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对甲月计划产值" align="center" prop="ownerPlanTotal">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerPlanTotal) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙月计划产值" align="center" prop="subPlanTotal">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subPlanTotal) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对甲月实际产值" align="center" prop="ownerActualTotal">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerActualTotal) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙月实际产值" align="center" prop="subActualTotal">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subActualTotal) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<!-- <el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="handleEdit(scope.row)" link icon="Position">联查分包结算</el-button>
|
||||
@ -75,7 +123,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { listOutTable, comparisonOfOutputValue, comparisonOfSettlementValue } from '@/api/out/outDesignTableVS/index';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
import { dayjs } from 'element-plus';
|
||||
const userStore = useUserStoreHook();
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
|
@ -16,18 +16,66 @@
|
||||
<el-card shadow="never">
|
||||
<el-table v-loading="loading" :data="tableData">
|
||||
<el-table-column label="项目" align="center" prop="projectName" />
|
||||
<el-table-column label="项目总产值" align="center" prop="totalValue" />
|
||||
<el-table-column label="月预计产值" align="center" prop="monthlyEstimatedValue" />
|
||||
<el-table-column label="完成产值(第一周)" align="center" prop="firstWeekCompletionValue" />
|
||||
<el-table-column label="完成产值(第二周)" align="center" prop="secondWeekCompletionValue" />
|
||||
<el-table-column label="完成产值(第三周)" align="center" prop="thirdWeekCompletionValue" />
|
||||
<el-table-column label="完成产值(第四周)" align="center" prop="fourthWeekCompletionValue" />
|
||||
<el-table-column label="完成产值(第五周)" align="center" prop="fifthWeekCompletionValue" />
|
||||
<el-table-column label="完成产值月合计" align="center" prop="totalCompletionValue" />
|
||||
<el-table-column label="产值差额" align="center" prop="valueDifference" />
|
||||
<el-table-column label="预计累计产值" align="center" prop="estimatedAccumulatedValue" />
|
||||
<el-table-column label="累计完成产值" align="center" prop="accumulatedCompletionValue" />
|
||||
<el-table-column label="产值差额" align="center" prop="valueDifferenceAccumulation" />
|
||||
<el-table-column label="项目总产值" align="center" prop="totalValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="月预计产值" align="center" prop="monthlyEstimatedValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.monthlyEstimatedValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完成产值(第一周)" align="center" prop="firstWeekCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.firstWeekCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完成产值(第二周)" align="center" prop="secondWeekCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.secondWeekCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完成产值(第三周)" align="center" prop="thirdWeekCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.thirdWeekCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完成产值(第四周)" align="center" prop="fourthWeekCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.fourthWeekCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完成产值(第五周)" align="center" prop="fifthWeekCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.fifthWeekCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="完成产值月合计" align="center" prop="totalCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="产值差额" align="center" prop="valueDifference"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.valueDifference) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="预计累计产值" align="center" prop="estimatedAccumulatedValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.estimatedAccumulatedValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="累计完成产值" align="center" prop="accumulatedCompletionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.accumulatedCompletionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="产值差额" align="center" prop="valueDifferenceAccumulation"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.valueDifferenceAccumulation) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="项目完成总进度" align="center" prop="totalCompletionProgress" />
|
||||
</el-table>
|
||||
<pagination
|
||||
@ -50,6 +98,7 @@ import { listOutTable } from '@/api/out/outTable';
|
||||
const userStore = useUserStoreHook();
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const activeTab = ref('1');
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const queryParams = ref({
|
||||
month: '',
|
||||
pageNum: 1,
|
||||
@ -102,15 +151,15 @@ const getList = async () => {
|
||||
total.value = res.total;
|
||||
}
|
||||
};
|
||||
const resetMonth=()=>{
|
||||
const currentDate = new Date();
|
||||
const resetMonth = () => {
|
||||
const currentDate = new Date();
|
||||
const year = currentDate.getFullYear();
|
||||
const month = currentDate.getMonth() + 1; // 月份从0开始,所以需要加1
|
||||
|
||||
// 形成"YYYY-M"格式
|
||||
const formattedDate = `${year}-${String(month).padStart(2, '0')}`;
|
||||
queryParams.value.month = formattedDate;
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
resetMonth();
|
||||
|
||||
|
@ -12,7 +12,11 @@
|
||||
<el-table-column label="规格" align="center" prop="specification" />
|
||||
<el-table-column label="单位" align="center" prop="unit" />
|
||||
<el-table-column label="接收数量" align="center" prop="acceptedQuantity" />
|
||||
<el-table-column label="价格" align="center" prop="unitPrice"> </el-table-column>
|
||||
<el-table-column label="价格" align="center" prop="unitPrice">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.unitPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark"> </el-table-column>
|
||||
<el-table-column label="操作" align="center" prop="remark" v-if="queryParams.type == '1'">
|
||||
<template #default="scope">
|
||||
|
@ -48,7 +48,11 @@
|
||||
<span>{{ parseTime(scope.row.settlementDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算产值" align="center" prop="settlementValue" />
|
||||
<el-table-column label="结算产值" align="center" prop="settlementValue" >
|
||||
<template #default="scope">
|
||||
<span>{{ proxy.formatPrice(scope.row.settlementValue) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="说明" align="center" prop="remark" />
|
||||
<el-table-column label="合同编码" align="center" prop="contractCode" />
|
||||
<el-table-column label="合同名称" align="center" prop="contractName" />
|
||||
|
@ -17,14 +17,46 @@
|
||||
|
||||
<el-table v-loading="loading" :data="valueAllocationList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="对甲总产值" align="center" prop="ownerTotalValue" />
|
||||
<el-table-column label="对甲设计产值" align="center" prop="ownerDesignValue" />
|
||||
<el-table-column label="对甲采购产值" align="center" prop="ownerPurchaseValue" />
|
||||
<el-table-column label="对甲施工产值" align="center" prop="ownerConstructionValue" />
|
||||
<el-table-column label="对乙总产值" align="center" prop="subTotalValue" />
|
||||
<el-table-column label="对乙设计产值" align="center" prop="subDesignValue" />
|
||||
<el-table-column label="对乙采购产值" align="center" prop="subPurchaseValue" />
|
||||
<el-table-column label="对乙施工产值" align="center" prop="subConstructionValue" />
|
||||
<el-table-column label="对甲总产值" align="center" prop="ownerTotalValue">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerTotalValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="对甲设计产值" align="center" prop="ownerDesignValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerDesignValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对甲采购产值" align="center" prop="ownerPurchaseValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerPurchaseValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对甲施工产值" align="center" prop="ownerConstructionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.ownerConstructionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙总产值" align="center" prop="subTotalValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subTotalValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙设计产值" align="center" prop="subDesignValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subDesignValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙采购产值" align="center" prop="subPurchaseValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subPurchaseValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="对乙施工产值" align="center" prop="subConstructionValue"
|
||||
><template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.subConstructionValue) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
|
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
|
||||
:leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="请选择项目:" prop="pid" label-width="100">
|
||||
<el-select v-model="queryParams.projectId" placeholder="请选择" @change="handleChange" clearable>
|
||||
<el-option v-for="item in matrixOptions" :key="item.projectId" :label="item.name" :value="item.projectId" />
|
||||
<el-option v-for="item in matrixOptions" :key="item.projectId" :label="item.name"
|
||||
:value="item.projectId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请选择方阵:" prop="pid" label-width="100" v-if="relevancyStructure == '2'">
|
||||
@ -21,24 +23,16 @@
|
||||
<el-tabs type="border-card" v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane :label="item.name" v-for="item in tabList" :key="item.id" :name="item.id"></el-tab-pane>
|
||||
<el-card shadow="never">
|
||||
<el-table
|
||||
ref="progressCategoryTableRef"
|
||||
v-loading="loading"
|
||||
:data="progressCategoryList"
|
||||
row-key="id"
|
||||
:default-expand-all="isExpandAll"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
v-if="isExpand"
|
||||
border
|
||||
>
|
||||
<el-table ref="progressCategoryTableRef" v-loading="loading" :data="progressCategoryList" row-key="id"
|
||||
:default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
v-if="isExpand" border>
|
||||
<el-table-column label="" width="50" type="expand">
|
||||
<template #header>
|
||||
<el-icon
|
||||
class="cursor-pointer text-4! transform-rotate-z--90 transition-all-300"
|
||||
<el-icon class="cursor-pointer text-4! transform-rotate-z--90 transition-all-300"
|
||||
:class="!isExpandAll ? 'transform-rotate-z--90' : 'transform-rotate-z-90'"
|
||||
@click="handleToggleExpandAll"
|
||||
><Expand
|
||||
/></el-icon>
|
||||
@click="handleToggleExpandAll">
|
||||
<Expand />
|
||||
</el-icon>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-card class="pl-25" shadow="hover">
|
||||
@ -46,9 +40,8 @@
|
||||
<el-table-column label="名称" align="center" prop="name" width="170">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip :content="row.remark" placement="top" effect="dark" v-if="row.remark">
|
||||
<span class="flex items-center justify-center"
|
||||
><i class="iconfont icon-wenhao mr-0.5 text-3.5! text-#999"></i>{{ row.name }}</span
|
||||
>
|
||||
<span class="flex items-center justify-center"><i
|
||||
class="iconfont icon-wenhao mr-0.5 text-3.5! text-#999"></i>{{ row.name }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ row.name }}</span>
|
||||
</template>
|
||||
@ -60,7 +53,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="是否延期" align="center" prop="isDelay" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.isDelay == '1' ? 'danger' : 'primary'">{{ row.isDelay == '1' ? '是' : '否' }}</el-tag>
|
||||
<el-tag :type="row.isDelay == '1' ? 'danger' : 'primary'">{{ row.isDelay == '1' ? '是' : '否'
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计量方式" align="center" prop="unitType" width="100">
|
||||
@ -71,7 +65,8 @@
|
||||
<el-table-column label="总量" align="center" prop="total" width="100" />
|
||||
<el-table-column label="总进度" align="center" prop="projectId">
|
||||
<template #default="{ row }">
|
||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.completedPercentage" status="success" />
|
||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.completedPercentage"
|
||||
status="success" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划总量" align="center" prop="planTotal" width="100" />
|
||||
@ -87,35 +82,17 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="Download"
|
||||
link
|
||||
size="small"
|
||||
v-if="scope.row.name === '光伏板'"
|
||||
<el-button type="warning" icon="Download" link size="small" v-if="scope.row.name === '光伏板'"
|
||||
@click="openDialog(scope.row, 'importTableStatus', '上传表格')"
|
||||
v-hasPermi="['progress:progressCategory:add']"
|
||||
>
|
||||
v-hasPermi="['progress:progressCategory:add']">
|
||||
导入表格
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="Plus"
|
||||
link
|
||||
size="small"
|
||||
@click="planRef.openDialog(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']"
|
||||
>
|
||||
<el-button type="success" icon="Plus" link size="small" @click="planRef.openDialog(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']">
|
||||
计划
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="Plus"
|
||||
link
|
||||
size="small"
|
||||
@click="handleDayAdd(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']"
|
||||
>
|
||||
<el-button type="primary" icon="Plus" link size="small" @click="handleDayAdd(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']">
|
||||
日报
|
||||
</el-button>
|
||||
</template>
|
||||
@ -132,7 +109,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="总进度" align="center" prop="projectId">
|
||||
<template #default="{ row }">
|
||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.completedPercentage" status="success" />
|
||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.completedPercentage"
|
||||
status="success" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -140,7 +118,8 @@
|
||||
<el-table-column label="名称" align="center" prop="name" width="170">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip :content="row.remark" placement="top" effect="dark" v-if="row.remark">
|
||||
<span class="flex items-center justify-center"><i class="iconfont icon-wenhao mr-0.5 text-3.5! text-#999"></i>{{ row.name }}</span>
|
||||
<span class="flex items-center justify-center"><i
|
||||
class="iconfont icon-wenhao mr-0.5 text-3.5! text-#999"></i>{{ row.name }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ row.name }}</span>
|
||||
</template>
|
||||
@ -163,7 +142,8 @@
|
||||
<el-table-column label="总量" align="center" prop="total" width="100" />
|
||||
<el-table-column label="总进度" align="center" prop="projectId">
|
||||
<template #default="{ row }">
|
||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.completedPercentage" status="success" />
|
||||
<el-progress :text-inside="true" :stroke-width="20" :percentage="row.completedPercentage"
|
||||
status="success" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划总量" align="center" prop="planTotal" width="100" />
|
||||
@ -179,28 +159,17 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="Download"
|
||||
link
|
||||
size="small"
|
||||
v-if="scope.row.name === '光伏板'"
|
||||
<el-button type="warning" icon="Download" link size="small" v-if="scope.row.name === '光伏板'"
|
||||
@click="openDialog(scope.row, 'importTableStatus', '上传表格')"
|
||||
v-hasPermi="['progress:progressCategory:add']"
|
||||
>
|
||||
v-hasPermi="['progress:progressCategory:add']">
|
||||
导入表格
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="Plus"
|
||||
link
|
||||
size="small"
|
||||
@click="planRef.openDialog(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']"
|
||||
>
|
||||
<el-button type="success" icon="Plus" link size="small" @click="planRef.openDialog(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']">
|
||||
计划
|
||||
</el-button>
|
||||
<el-button type="primary" icon="Plus" link size="small" @click="handleDayAdd(scope.row)" v-hasPermi="['progress:progressCategory:add']">
|
||||
<el-button type="primary" icon="Plus" link size="small" @click="handleDayAdd(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:add']">
|
||||
日报
|
||||
</el-button>
|
||||
</template>
|
||||
@ -211,7 +180,8 @@
|
||||
|
||||
<!-- 导入数据对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.importDataStatus" width="500px" append-to-body>
|
||||
<file-upload class="pl-20 pt" v-model="dialog.file" :limit="20" :file-size="50" :file-type="['shp', 'shx', 'dbf']" />
|
||||
<file-upload class="pl-20 pt" v-model="dialog.file" :limit="20" :file-size="50"
|
||||
:file-type="['shp', 'shx', 'dbf']" />
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
|
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
|
||||
:leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="请选择项目:" prop="pid" label-width="100">
|
||||
<el-select v-model="queryParams.projectId" placeholder="请选择" @change="handleChange" clearable>
|
||||
<el-option v-for="item in matrixOptions" :key="item.projectId" :label="item.name" :value="item.projectId" />
|
||||
<el-option v-for="item in matrixOptions" :key="item.projectId" :label="item.name"
|
||||
:value="item.projectId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="请选择方阵:" prop="pid" label-width="100" v-if="relevancyStructure == '2'">
|
||||
@ -27,13 +29,8 @@
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<file-upload
|
||||
upload-url="/progress/progressCategory/import"
|
||||
v-model="file"
|
||||
:limit="1"
|
||||
:file-type="['xls', 'xlsx']"
|
||||
:on-upload-success="handleSuccess"
|
||||
>
|
||||
<file-upload upload-url="/progress/progressCategory/import" v-model="file" :limit="1"
|
||||
:file-type="['xls', 'xlsx']" :on-upload-success="handleSuccess">
|
||||
<el-button type="primary" plain icon="upload">导入</el-button>
|
||||
</file-upload>
|
||||
</el-col>
|
||||
@ -43,17 +40,39 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
|
||||
</el-col>
|
||||
<el-col :span="6" :push="6">
|
||||
<div class="summary-container">
|
||||
<div class="summary-card owner-summary">
|
||||
<div class="summary-icon">
|
||||
<el-icon size="24">
|
||||
<Money />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="summary-content">
|
||||
<div class="summary-label">产值金额(业主)</div>
|
||||
<div class="summary-value">{{ ownerOutputSum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-card construction-summary">
|
||||
<div class="summary-icon">
|
||||
<el-icon size="24">
|
||||
<Wallet />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="summary-content">
|
||||
<div class="summary-label">产值金额(分包)</div>
|
||||
<div class="summary-value">{{ constructionOutputSum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
|
||||
</el-row>
|
||||
</template>
|
||||
<el-table
|
||||
ref="progressCategoryTableRef"
|
||||
v-loading="loading"
|
||||
:data="progressCategoryList"
|
||||
row-key="id"
|
||||
:default-expand-all="isExpandAll"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table ref="progressCategoryTableRef" v-loading="loading" :data="progressCategoryList" row-key="id"
|
||||
:default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
max-height="550">
|
||||
<!-- <el-table-column label="父类别id" prop="parentId" /> -->
|
||||
<el-table-column label="类别名称" prop="name" width="230" />
|
||||
<el-table-column label="计量方式" align="center" prop="unitType">
|
||||
@ -69,22 +88,22 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="综合单价(业主)" align="center" prop="ownerPrice">
|
||||
<template #default="{ row }">
|
||||
{{ row.unitType == 0 ? '' : row.ownerPrice }}
|
||||
{{ row.unitType == 0 ? '' : proxy.formatPrice(row.ownerPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="综合单价(分包)" align="center" prop="constructionPrice">
|
||||
<template #default="{ row }">
|
||||
{{ row.unitType == 0 ? '' : row.constructionPrice }}
|
||||
{{ row.unitType == 0 ? '' : proxy.formatPrice(row.constructionPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产值金额(业主)" align="center" prop="ownerOutputValue">
|
||||
<template #default="{ row }">
|
||||
{{ row.unitType == 0 ? '' : row.ownerOutputValue }}
|
||||
{{ row.unitType == 0 ? '' : proxy.formatPrice(row.ownerOutputValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产值金额(分包)" align="center" prop="constructionOutputValue">
|
||||
<template #default="{ row }">
|
||||
{{ row.unitType == 0 ? '' : row.constructionOutputValue }}
|
||||
{{ row.unitType == 0 ? '' : proxy.formatPrice(row.constructionOutputValue) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总数量" align="center" prop="total">
|
||||
@ -102,10 +121,12 @@
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['progress:progressCategory:edit']">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:edit']">
|
||||
修改
|
||||
</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['progress:progressCategory:remove']">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['progress:progressCategory:remove']">
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
@ -119,14 +140,9 @@
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="progressCategoryFormRef" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="父类别" prop="parentId" v-if="!form.id">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="progressCategoryOptions"
|
||||
:props="{ value: 'id', label: 'name', children: 'children' }"
|
||||
value-key="id"
|
||||
placeholder="请选择父类别"
|
||||
check-strictly
|
||||
/>
|
||||
<el-tree-select v-model="form.parentId" :data="progressCategoryOptions"
|
||||
:props="{ value: 'id', label: 'name', children: 'children' }" value-key="id" placeholder="请选择父类别"
|
||||
check-strictly />
|
||||
</el-form-item>
|
||||
<el-form-item label="计量方式" prop="unitType" v-if="!form.workType && form.unitType != '0'">
|
||||
<el-select v-model="form.unitType" placeholder="请选择关联数据">
|
||||
@ -191,8 +207,9 @@ import {
|
||||
import { ProgressCategoryVO, ProgressCategoryQuery, ProgressCategoryForm } from '@/api/progress/progressCategory/types';
|
||||
import { getTabList } from '@/api/progress/progressCategoryTemplate';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { Money, Wallet } from '@element-plus/icons-vue';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { progress_unit_type, progress_work_type } = toRefs<any>(proxy?.useDict('progress_unit_type', 'progress_work_type'));
|
||||
const activeTab = ref('0');
|
||||
const relevancyStructure = ref('1');
|
||||
@ -225,7 +242,7 @@ const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const tempData = ref([])
|
||||
const initFormData: ProgressCategoryForm = {
|
||||
id: undefined,
|
||||
parentId: undefined,
|
||||
@ -291,7 +308,20 @@ const data = reactive<PageData<ProgressCategoryForm, ProgressCategoryQuery>>({
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
const matrixIdList = ref([]);
|
||||
|
||||
const ownerOutputSum = computed(() => {
|
||||
let sum = 0;
|
||||
tempData.value.forEach(item => {
|
||||
sum += Number(item.ownerOutputValue);
|
||||
})
|
||||
return proxy.formatPrice(sum);
|
||||
});
|
||||
const constructionOutputSum = computed(() => {
|
||||
let sum = 0;
|
||||
tempData.value.forEach(item => {
|
||||
sum += Number(item.constructionOutputValue);
|
||||
})
|
||||
return proxy.formatPrice(sum);
|
||||
});
|
||||
/** 查询分项工程单价列表 */
|
||||
const getList = async () => {
|
||||
if (!queryParams.value.projectId) {
|
||||
@ -310,6 +340,7 @@ const getList = async () => {
|
||||
matrixId: item.projectId
|
||||
};
|
||||
});
|
||||
|
||||
if (!matrixValue.value) matrixValue.value = matrixList[0].id;
|
||||
matrixOptions.value = matrixList;
|
||||
queryParams.value.projectId = matrixList[0].projectId;
|
||||
@ -325,6 +356,7 @@ const getList = async () => {
|
||||
try {
|
||||
const id = relevancyStructure.value == '2' ? matrixValue.value : activeTab.value;
|
||||
const res = await listProgressCategory(id);
|
||||
tempData.value = res.data;
|
||||
const data = proxy?.handleTree<ProgressCategoryVO>(res.data, 'id', 'parentId');
|
||||
if (data) {
|
||||
progressCategoryList.value = data;
|
||||
@ -506,3 +538,89 @@ onUnmounted(() => {
|
||||
listeningProject();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.summary-container {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px 20px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e4e7ed;
|
||||
background: #ffffff;
|
||||
min-width: 200px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.summary-card:hover {
|
||||
border-color: #c0c4cc;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.owner-summary {
|
||||
background: #f8f9fa;
|
||||
border-color: #409eff;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.construction-summary {
|
||||
background: #f8f9fa;
|
||||
border-color: #67c23a;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.summary-icon {
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 4px;
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
.owner-summary .summary-icon {
|
||||
background: #e6f7ff;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.construction-summary .summary-icon {
|
||||
background: #f0f9ff;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.summary-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
margin-bottom: 6px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.summary-value {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.summary-container {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
min-width: 180px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -148,7 +148,7 @@
|
||||
<el-table-column label="薪水" align="center" min-width="180">
|
||||
<template #default="scope">
|
||||
<span class="flex justify-center">
|
||||
{{ scope.row.salary ? scope.row.salary : scope.row.standardSalary }}
|
||||
{{ proxy.formatPrice(scope.row.salary ? scope.row.salary : scope.row.standardSalary) }}
|
||||
(<dict-tag :options="wage_measure_unit_type" :value="scope.row.wageMeasureUnit"></dict-tag>)
|
||||
</span>
|
||||
<div class="text-blue text-sm cursor-pointer" @click="openSalaryDialog(scope.row)">{{ scope.row.salary ? '取消变更' : '变更' }}</div>
|
||||
@ -516,7 +516,7 @@ import { AttendanceMonthVO } from '@/api/project/attendance/types';
|
||||
import { parseTime } from '@/utils/ruoyi';
|
||||
|
||||
const calendar = ref<CalendarInstance>();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { type_of_work, user_sex_type, user_clock_type, user_file_type, user_status_type, wage_measure_unit_type } = toRefs<any>(
|
||||
proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type', 'user_file_type', 'user_status_type', 'wage_measure_unit_type')
|
||||
);
|
||||
|
@ -22,7 +22,7 @@
|
||||
<div>
|
||||
<div>
|
||||
<span>租金</span>
|
||||
<span>{{ detailInfo.rentSum / 1000 }} 万元</span>
|
||||
<span>{{ proxy.formatPrice(detailInfo.rentSum) / 1000 }} 万元</span>
|
||||
</div>
|
||||
<el-icon :size="50" color="#3176ff">
|
||||
<Postcard />
|
||||
@ -83,9 +83,21 @@
|
||||
{{ scope.row.transferArea && scope.row.designArea ? ((scope.row.transferArea / scope.row.designArea) * 100).toFixed(2) : '0.00' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="土地租金(元)" align="center" prop="landRentAll" width="180" />
|
||||
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensationAll" width="180" />
|
||||
<el-table-column label="总金额(元)" align="center" prop="totalAmountAll" width="150" />
|
||||
<el-table-column label="土地租金(元)" align="center" prop="landRentAll" width="180">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.landRentAll) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensationAll" width="180">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.seedlingCompensationAll) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="总金额(元)" align="center" prop="totalAmountAll" width="150">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalAmountAll) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
|
||||
<el-table-column label="操作" align="center" fixed="right" width="200">
|
||||
<template #default="scope">
|
||||
@ -168,9 +180,21 @@
|
||||
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
|
||||
<el-table-column label="已流转面积(亩)" align="center" prop="areaValue" width="180" />
|
||||
<el-table-column label="流转比例(%)" align="center" prop="transferRatio" width="180" />
|
||||
<el-table-column label="土地租金(元)" align="center" prop="landRent" width="180" />
|
||||
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensation" width="180" />
|
||||
<el-table-column label="总金额(元)" align="center" prop="totalAmount" width="150" />
|
||||
<el-table-column label="土地租金(元)" align="center" prop="landRent" width="180">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.landRent) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensation" width="180">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.seedlingCompensation) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="总金额(元)" align="center" prop="totalAmount" width="150">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalAmount) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="状态说明" align="center" prop="statusDescription" />
|
||||
<el-table-column label="问题总结" align="center" prop="issueSummary" />
|
||||
<el-table-column label="下一步策略" align="center" prop="nextStrategy" width="180" />
|
||||
@ -180,7 +204,7 @@
|
||||
<!-- 不流转子项 -->
|
||||
<div v-if="sonTransferLedgerList2.length > 0">
|
||||
<h4 style="margin-top: 20px; margin-bottom: 10px; color: #ff6b6b">不流转</h4>
|
||||
<el-table v-loading="sonLoading" :data="sonTransferLedgerList2" @selection-change="handleSonSelectionChange">
|
||||
<el-table v-loading="sonLoading" :data="sonTransferLedgerList2" @selection-change="handleSonSelectionChange" width="100%">
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="土地类型" align="center" prop="landTypeName" />
|
||||
<el-table-column label="地块" align="center" prop="landName" />
|
||||
@ -221,8 +245,8 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增子项对话框 -->
|
||||
<el-dialog draggable :title="sonFormDialog.title" v-model="sonFormDialog.visible" width="600px" append-to-body>
|
||||
<el-form ref="sonLandTransferLedgerFormRef" :model="sonForm" :rules="sonRules" label-width="120px">
|
||||
<el-dialog draggable :title="sonFormDialog.title" v-model="sonFormDialog.visible" width="650px" append-to-body>
|
||||
<el-form ref="sonLandTransferLedgerFormRef" :model="sonForm" :rules="sonRules" label-width="150px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="对应地块" prop="landBlockId">
|
||||
@ -329,7 +353,7 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" v-if="sonForm.transferStatus == '2'">
|
||||
<el-col :span="24" v-if="sonForm.transferStatus == '2'" style="">
|
||||
<el-form-item label="不签合同面积(亩)" prop="noContractArea">
|
||||
<el-input v-model="sonForm.noContractArea" type="number" placeholder="请输入不签合同面积" />
|
||||
</el-form-item>
|
||||
@ -557,7 +581,7 @@ interface PageData<T, Q> {
|
||||
rules: Record<string, any[]>;
|
||||
}
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="110px">
|
||||
<el-form-item label="对应地块" prop="landBlockId">
|
||||
<el-select v-model="queryParams.landBlockId" clearable placeholder="请选择对应地块">
|
||||
@ -15,31 +15,16 @@
|
||||
<el-form-item label="责任人" prop="responsiblePerson">
|
||||
<el-input v-model="queryParams.responsiblePerson" placeholder="请输入责任人" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="预计完成时间" prop="expectedFinishDate">
|
||||
<el-date-picker
|
||||
clearable
|
||||
v-model="queryParams.expectedFinishDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择预计完成时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="landTransferLedgerList" @selection-change="handleSelectionChange">
|
||||
<el-table v-loading="loading" :data="landTransferLedgerList">
|
||||
<!-- 二级表格 -->
|
||||
<el-table-column type="expand">
|
||||
<template #default="scope">
|
||||
@ -51,27 +36,39 @@
|
||||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="土地类型" align="center" prop="landType" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="土地类型" align="center" prop="landTypeName" />
|
||||
<el-table-column label="地块" align="center" prop="landName" />
|
||||
<el-table-column label="进场道路" align="center" prop="roadName" />
|
||||
<el-table-column label="设计面积" align="center" prop="designArea" />
|
||||
<el-table-column label="设计面积(亩)" align="center" prop="designArea" width="180" />
|
||||
<el-table-column label="责任人" align="center" prop="responsiblePerson" />
|
||||
<el-table-column label="预计完成时间" align="center" prop="expectedFinishDate" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.expectedFinishDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已流转面积" align="center" prop="transferAea" />
|
||||
<el-table-column label="流转比例" align="center" prop="transferRatio" />
|
||||
<el-table-column label="土地租金" align="center" prop="landRent" />
|
||||
<el-table-column label="青苗赔偿" align="center" prop="seedlingCompensation" />
|
||||
<el-table-column label="总金额" align="center" prop="totalAmount" />
|
||||
<el-table-column label="流转状态" align="center" prop="transferStatus" />
|
||||
<el-table-column label="流转状态" align="center" prop="transferStatusName" />
|
||||
<el-table-column label="已流转面积(亩)" align="center" prop="transferAea" width="180" />
|
||||
<el-table-column label="流转比例(%)" align="center" prop="transferRatio" width="180" />
|
||||
<el-table-column label="土地租金(元)" align="center" prop="landRent" width="180">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.landRent) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="青苗赔偿(元)" align="center" prop="seedlingCompensation" width="180">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.seedlingCompensation) }}
|
||||
</template></el-table-column
|
||||
>
|
||||
<el-table-column label="总金额(元)" align="center" prop="totalAmount" width="150">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.totalAmount) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态说明" align="center" prop="statusDescription" />
|
||||
<el-table-column label="问题总结" align="center" prop="issueSummary" />
|
||||
<el-table-column label="下一步策略" align="center" prop="nextStrategy" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
|
||||
<el-table-column label="下一步策略" align="center" prop="nextStrategy" width="180" />
|
||||
<!-- <el-table-column label="操作" fixed="right" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['land:landTransferLedger:edit']">编辑</el-button>
|
||||
@ -80,7 +77,7 @@
|
||||
<el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['land:landTransferLedger:remove']">删除</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
@ -157,7 +154,7 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button v-hasPermi="['land:landTransferLedger:add']" :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
@ -177,7 +174,7 @@ import { listEnterRoad } from '@/api/system/landTransfer/enterRoad';
|
||||
import { LandTransferLedgerVO, LandTransferLedgerQuery, LandTransferLedgerForm } from '@/api/system/landTransfer/landTransferLedger/types';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { listLandBlock } from '@/api/system/landTransfer/landBlock';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
@ -203,7 +200,7 @@ const dialog = reactive<DialogOption>({
|
||||
|
||||
const initFormData: LandTransferLedgerForm = {
|
||||
id: undefined,
|
||||
projectId: currentProject.value.id,
|
||||
projectId: currentProject.value?.id,
|
||||
landType: undefined,
|
||||
landBlockId: undefined,
|
||||
enterRoadId: undefined,
|
||||
@ -225,7 +222,7 @@ const data = reactive<PageData<LandTransferLedgerForm, LandTransferLedgerQuery>>
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
projectId: currentProject.value.id,
|
||||
projectId: currentProject.value?.id,
|
||||
landType: undefined,
|
||||
landBlockId: undefined,
|
||||
enterRoadId: undefined,
|
||||
@ -344,18 +341,18 @@ const getListLand = async () => {
|
||||
const res = await listLandBlock({
|
||||
pageNum: 1,
|
||||
pageSize: 10000,
|
||||
projectId: currentProject.value.id
|
||||
projectId: currentProject.value?.id
|
||||
});
|
||||
landBlockList.value = res.rows;
|
||||
};
|
||||
/** 查询进场道路信息列表 */
|
||||
const getListRoad = async () => {
|
||||
const res = await listEnterRoad({ pageNum: 1, pageSize: 10000, projectId: currentProject.value.id, landBlockId: form.value.landBlockId });
|
||||
const res = await listEnterRoad({ pageNum: 1, pageSize: 10000, projectId: currentProject.value?.id, landBlockId: form.value.landBlockId });
|
||||
enterRoadList.value = res.rows;
|
||||
};
|
||||
//监听项目id刷新数据
|
||||
const listeningProject = watch(
|
||||
() => currentProject.value.id,
|
||||
() => currentProject.value?.id,
|
||||
(nid, oid) => {
|
||||
queryParams.value.projectId = nid;
|
||||
getListLand();
|
||||
|
@ -148,8 +148,8 @@
|
||||
<el-table-column label="薪水" align="center" min-width="180">
|
||||
<template #default="scope">
|
||||
<span class="flex justify-center">
|
||||
{{ scope.row.salary == '0' ? scope.row.original : scope.row.salary }}
|
||||
<!-- (<dict-tag :options="wage_measure_unit_type" :value="scope.row.wageMeasureUnit"></dict-tag>) -->
|
||||
{{ proxy.formatPrice(scope.row.salary ? scope.row.salary : scope.row.standardSalary) }}
|
||||
(<dict-tag :options="wage_measure_unit_type" :value="scope.row.wageMeasureUnit"></dict-tag>)
|
||||
</span>
|
||||
<div class="text-blue text-sm cursor-pointer" @click="openSalaryDialog(scope.row)">
|
||||
{{ scope.row.salary != '0' ? '取消变更' : '变更' }}
|
||||
@ -217,12 +217,12 @@
|
||||
</div>
|
||||
<div class="el-col el-col-12" v-if="!form.id">
|
||||
<el-form-item label="身份证正面图片" prop="sfzFrontPic">
|
||||
<image-upload v-model="form.sfzFrontPic" :limit="1" :is-show-tip="false" />
|
||||
<image-upload v-model="form.sfzFrontPic" :limit="1" :is-show-tip="false" :idCardType="'front'" @success="handleUploadSuccess" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="el-col el-col-12" v-if="!form.id">
|
||||
<el-form-item label="身份证背面图片" prop="sfzBackPic">
|
||||
<image-upload v-model="form.sfzBackPic" :limit="1" :is-show-tip="false" />
|
||||
<image-upload v-model="form.sfzBackPic" :limit="1" :is-show-tip="false" :idCardType="'back'" @success="handleUploadSuccessBack" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="el-col el-col-12">
|
||||
@ -291,7 +291,7 @@
|
||||
<div class="el-row">
|
||||
<div class="el-col el-col-24" v-if="!form.id">
|
||||
<el-form-item label="银行图片" prop="yhkPic">
|
||||
<image-upload v-model="form.yhkPic" :limit="1" :is-show-tip="false" />
|
||||
<image-upload v-model="form.yhkPic" :limit="1" :is-show-tip="false" :idCardType="'bank'" @success="handleUploadSuccessBank" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="el-col el-col-12">
|
||||
@ -558,9 +558,9 @@ import { AttendanceMonthVO } from '@/api/project/attendance/types';
|
||||
import { parseTime } from '@/utils/ruoyi';
|
||||
|
||||
const calendar = ref<CalendarInstance>();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { type_of_work, user_sex_type, user_clock_type, user_file_type, user_status_type, wage_measure_unit_type } = toRefs<any>(
|
||||
proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type', 'user_file_type', 'user_status_type', 'wage_measure_unit_type')
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { type_of_work, user_sex_type, user_clock_type, user_file_type, user_status_type, wage_measure_unit_type, user_post_type } = toRefs<any>(
|
||||
proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type', 'user_file_type', 'user_status_type', 'wage_measure_unit_type', 'user_post_type')
|
||||
);
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
@ -738,6 +738,41 @@ const uploadPath = computed(() => {
|
||||
console.log('🚀 ~ list:', list, fileList.value);
|
||||
return list;
|
||||
});
|
||||
//身份证正面上传成功
|
||||
const handleUploadSuccess = (data: any) => {
|
||||
console.log('上传成功返回的数据:', data);
|
||||
// 这里可以处理返回的数据
|
||||
form.value.userName = data.name;
|
||||
form.value.sex = data.gender == '男' ? 2 : 3;
|
||||
form.value.nation = data.nation;
|
||||
form.value.sfzNumber = data.citizenIdentification;
|
||||
form.value.sfzSite = data.address;
|
||||
form.value.sfzBirth = formatDate(data.birth);
|
||||
};
|
||||
//身份证反面面上传成功
|
||||
const handleUploadSuccessBack = (data: any) => {
|
||||
console.log('上传成功返回的数据:', data);
|
||||
form.value.sfzStart = formatDate(data.issuingDate);
|
||||
form.value.sfzEnd = formatDate(data.expiryDate);
|
||||
};
|
||||
//银行卡上传成功
|
||||
const handleUploadSuccessBank = (data: any) => {
|
||||
console.log('上传成功返回的数据:', data);
|
||||
form.value.yhkNumber = data.bankCardNumber;
|
||||
};
|
||||
//格式化时间
|
||||
const formatDate = (date: any) => {
|
||||
const year = date.substring(0, 4);
|
||||
const month = date.substring(4, 6);
|
||||
const day = date.substring(6, 8);
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
// 获取项目列表
|
||||
const getProjectList = async () => {
|
||||
const res = await ProjectList({});
|
||||
projectList.value = res.rows;
|
||||
projectList.value.unshift({ id: '', projectName: '全部' });
|
||||
};
|
||||
|
||||
/** 返回文件上传状态 */
|
||||
const uploadStatusColor = computed(() => (str: string) => {
|
||||
|
@ -16,7 +16,7 @@
|
||||
<el-popover placement="top-start" title="" :width="200" trigger="hover" :content="DetailMoney + '元'">
|
||||
<template #reference>
|
||||
<el-tag class="m-2" size="large"
|
||||
><span style="font-size: 20px; cursor: pointer">金额:{{ totalMoney }}元</span></el-tag
|
||||
><span style="font-size: 20px; cursor: pointer">金额:{{ totalMoney ? proxy.formatPrice(totalMoney) : 0 }}元</span></el-tag
|
||||
>
|
||||
</template>
|
||||
</el-popover>
|
||||
@ -25,7 +25,9 @@
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" min-width="50px" />
|
||||
<el-table-column label="标题" align="center" prop="title" min-width="120px" />
|
||||
<el-table-column label="金额" align="center" prop="money" min-width="100px" />
|
||||
<el-table-column label="金额" align="center" prop="money" min-width="100px">
|
||||
<template #default="scope"> {{ proxy.formatPrice(scope.row.money) }} </template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding" min-width="200px" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="handleView(scope.row)"
|
||||
|
@ -147,7 +147,7 @@
|
||||
<el-table-column label="薪水" align="center" min-width="180">
|
||||
<template #default="scope">
|
||||
<span class="flex justify-center">
|
||||
{{ scope.row.salary ? scope.row.salary : scope.row.standardSalary }}
|
||||
{{ proxy.formatPrice(scope.row.salary ? scope.row.salary : scope.row.standardSalary) }}
|
||||
(<dict-tag :options="wage_measure_unit_type" :value="scope.row.wageMeasureUnit"></dict-tag>)
|
||||
</span>
|
||||
<div class="text-blue text-sm cursor-pointer" @click="openSalaryDialog(scope.row)">{{ scope.row.salary ? '取消变更' : '变更' }}</div>
|
||||
@ -513,7 +513,7 @@ import { AttendanceMonthVO } from '@/api/project/attendance/types';
|
||||
import { parseTime } from '@/utils/ruoyi';
|
||||
|
||||
const calendar = ref<CalendarInstance>();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { type_of_work, user_sex_type, user_clock_type, user_file_type, user_status_type, wage_measure_unit_type } = toRefs<any>(
|
||||
proxy?.useDict('type_of_work', 'user_sex_type', 'user_clock_type', 'user_file_type', 'user_status_type', 'wage_measure_unit_type')
|
||||
);
|
||||
|
@ -59,7 +59,11 @@
|
||||
<dict-tag :options="subcontract_type" :value="scope.row.contractType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同金额" align="center" prop="contractAmount" />
|
||||
<el-table-column label="合同金额" align="center" prop="contractAmount">
|
||||
<template #default="scope">
|
||||
<span>{{ proxy.formatPrice(scope.row.contractAmount) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合同时间" align="center" prop="contractTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.contractTime, '{y}-{m}-{d}') }}</span>
|
||||
@ -133,7 +137,7 @@ import { SubcontractVO, SubcontractQuery, SubcontractForm } from '@/api/project/
|
||||
import { listContractor } from '@/api/project/contractor';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="centerPage">
|
||||
<div class="topPage">
|
||||
<div id="earth" style="width: 100%;height: 100%;"></div>
|
||||
<newMap :isHide="isHide"></newMap>
|
||||
</div>
|
||||
<div class="endPage" :class="{ 'slide-out-down': isHide }">
|
||||
<Title title="AI安全巡检">
|
||||
@ -16,7 +16,7 @@
|
||||
<div class="swiper_content" ref="swiperContent">
|
||||
<div class="swiper_item" v-for="(item, i) in inspectionList" :key="i">
|
||||
<img :src="item.picture" alt="安全巡检" class="swiper_img">
|
||||
<div class="swiper_date">{{ item.createTime.slice(5) }}</div>
|
||||
<!-- <div class="swiper_date">{{ item.createTime.slice(5) }}</div> -->
|
||||
<div class="swiper_tip">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -35,7 +35,7 @@ import { ref, onMounted, toRefs, getCurrentInstance } from "vue"
|
||||
import Title from './title.vue'
|
||||
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
|
||||
import { getScreenSafetyInspection } from '@/api/projectScreen'
|
||||
|
||||
import newMap from "./newmap.vue"
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { violation_level_type } = toRefs(proxy?.useDict('violation_level_type'));
|
||||
|
||||
@ -95,60 +95,8 @@ const getInspectionList = async () => {
|
||||
inspectionList.value = data
|
||||
}
|
||||
}
|
||||
// 创建地球
|
||||
const createEarth = () => {
|
||||
window.YJ.on({
|
||||
ws: true,
|
||||
// host: getIP(), //资源所在服务器地址
|
||||
// username: this.loginForm.username, //用户名 可以不登录(不填写用户名),不登录时无法加载服务端的数据
|
||||
// password: md5pass, //密码 生成方式:md5(用户名_密码)
|
||||
}).then((res) => {
|
||||
let earth = new YJ.YJEarth("earth");
|
||||
window.Earth1 = earth;
|
||||
YJ.Global.openRightClick(window.Earth1);
|
||||
YJ.Global.openLeftClick(window.Earth1);
|
||||
let view = {
|
||||
"position": {
|
||||
"lng": 102.03643298211526,
|
||||
"lat": 34.393586474501,
|
||||
"alt": 11298179.51993155
|
||||
},
|
||||
"orientation": {
|
||||
"heading": 360,
|
||||
"pitch": -89.94481747201486,
|
||||
"roll": 0
|
||||
}
|
||||
}
|
||||
loadBaseMap(earth.viewer)
|
||||
YJ.Global.CesiumContainer(window.Earth1, {
|
||||
compass: false, //罗盘
|
||||
});
|
||||
// YJ.Global.flyTo(earth, view);
|
||||
// YJ.Global.setDefaultView(earth.viewer, view)
|
||||
})
|
||||
}
|
||||
// 加载底图
|
||||
const loadBaseMap = (viewer) => {
|
||||
// 创建瓦片提供器
|
||||
const imageryProvider = new Cesium.UrlTemplateImageryProvider({
|
||||
url: 'https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
// 可选:设置瓦片的格式
|
||||
fileExtension: 'png',
|
||||
// 可选:设置瓦片的范围和级别
|
||||
minimumLevel: 0,
|
||||
maximumLevel: 18,
|
||||
// 可选:设置瓦片的投影(默认为Web Mercator)
|
||||
projection: Cesium.WebMercatorProjection,
|
||||
// 可选:如果瓦片服务需要跨域请求,设置请求头部
|
||||
credit: new Cesium.Credit('卫星图数据来源')
|
||||
});
|
||||
|
||||
// 添加图层到视图
|
||||
const layer = viewer.imageryLayers.addImageryProvider(imageryProvider);
|
||||
}
|
||||
onMounted(() => {
|
||||
getInspectionList()
|
||||
createEarth()
|
||||
if (swiperContent.value && swiperContent.value.children.length > 0) {
|
||||
swiperItemWidth.value = swiperContent.value.children[0].clientWidth + 20
|
||||
}
|
@ -19,8 +19,12 @@
|
||||
<!-- 左侧:天气图标 + 日期文字 -->
|
||||
<div class="left-section">
|
||||
<div class="weather-list" @mouseenter="requestPause" @mouseleave="resumeScroll">
|
||||
<div v-for="(item, i) in weatherList" :key="i" class="weather-item"
|
||||
:style="{ transform: `translateY(-${offsetY}px)`, transition: transition }">
|
||||
<div
|
||||
v-for="(item, i) in weatherList"
|
||||
:key="i"
|
||||
class="weather-item"
|
||||
:style="{ transform: `translateY(-${offsetY}px)`, transition: transition }"
|
||||
>
|
||||
<img :src="`../../../src/assets/images/${item.icon}.png`" alt="" />
|
||||
<div>{{ item.weather }}{{ item.tempMin }}°/{{ item.tempMax }}°</div>
|
||||
<div>{{ item.week }}({{ item.date }})</div>
|
||||
@ -78,15 +82,15 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const emit = defineEmits(['changePage'])
|
||||
const emit = defineEmits(['changePage']);
|
||||
|
||||
const safetyDay = ref<number>(0);
|
||||
const weatherList = ref<Weather[]>([])
|
||||
const timer = ref<number | null>(0)
|
||||
const offsetY = ref<number>(0)
|
||||
const curIndex = ref(0)
|
||||
const weatherList = ref<Weather[]>([]);
|
||||
const timer = ref<number | null>(0);
|
||||
const offsetY = ref<number>(0);
|
||||
const curIndex = ref(0);
|
||||
const transition = ref('transform 0.5s ease');
|
||||
const pendingPause = ref(false);
|
||||
|
||||
@ -106,18 +110,16 @@ function judgeDayOrNight(sunRise: string, sunSet: string) {
|
||||
const now = new Date();
|
||||
const currentMinutes = now.getHours() * 60 + now.getMinutes();
|
||||
// true 白天 false 夜晚
|
||||
return currentMinutes >= sunRiseMinutes && currentMinutes <= sunSetMinutes
|
||||
? true
|
||||
: false;
|
||||
return currentMinutes >= sunRiseMinutes && currentMinutes <= sunSetMinutes ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置天气周期滑动
|
||||
*/
|
||||
const setWeatherScroll = () => {
|
||||
curIndex.value += 1
|
||||
curIndex.value += 1;
|
||||
transition.value = 'transform 0.3s ease';
|
||||
offsetY.value = curIndex.value * 60
|
||||
offsetY.value = curIndex.value * 60;
|
||||
|
||||
if (curIndex.value === weatherList.value.length - 1) {
|
||||
setTimeout(() => {
|
||||
@ -126,7 +128,7 @@ const setWeatherScroll = () => {
|
||||
offsetY.value = 0;
|
||||
}, 350);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function startScroll() {
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
@ -135,57 +137,56 @@ function startScroll() {
|
||||
|
||||
function requestPause() {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
timer.value = null
|
||||
clearInterval(timer.value);
|
||||
timer.value = null;
|
||||
}
|
||||
pendingPause.value = true;
|
||||
}
|
||||
|
||||
function resumeScroll() {
|
||||
console.log('resumeScroll')
|
||||
console.log('resumeScroll');
|
||||
pendingPause.value = false;
|
||||
startScroll();
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
/**
|
||||
* 获取安全生产天数
|
||||
*/
|
||||
getScreenSafetyDay(props.projectId).then(res => {
|
||||
const { data, code } = res
|
||||
getScreenSafetyDay(props.projectId).then((res) => {
|
||||
const { data, code } = res;
|
||||
if (code === 200) {
|
||||
safetyDay.value = data.safetyDay;
|
||||
}
|
||||
})
|
||||
});
|
||||
/**
|
||||
* 获取近三天天气
|
||||
*/
|
||||
getScreenWeather(props.projectId).then(res => {
|
||||
const { data, code } = res
|
||||
getScreenWeather(props.projectId).then((res) => {
|
||||
const { data, code } = res;
|
||||
if (code === 200) {
|
||||
data.forEach(item => {
|
||||
data.forEach((item) => {
|
||||
if (judgeDayOrNight(item.sunRise, item.sunSet)) {
|
||||
item.weather = item.dayStatus
|
||||
item.icon = item.dayIcon
|
||||
item.weather = item.dayStatus;
|
||||
item.icon = item.dayIcon;
|
||||
} else {
|
||||
item.weather = item.nightStatus
|
||||
item.icon = item.nightIcon
|
||||
item.weather = item.nightStatus;
|
||||
item.icon = item.nightIcon;
|
||||
}
|
||||
})
|
||||
weatherList.value = data
|
||||
});
|
||||
weatherList.value = data;
|
||||
// 多添加第一项 实现无缝衔接
|
||||
weatherList.value = [...weatherList.value, weatherList.value[0]]
|
||||
startScroll()
|
||||
weatherList.value = [...weatherList.value, weatherList.value[0]];
|
||||
startScroll();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
clearInterval(timer.value);
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -228,13 +229,13 @@ onUnmounted(() => {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title>div:first-child {
|
||||
.title > div:first-child {
|
||||
/* 第一个子元素的样式 */
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.title>div:last-child {
|
||||
.title > div:last-child {
|
||||
/* 最后一个子元素的样式 */
|
||||
font-size: 14px;
|
||||
}
|
||||
@ -267,7 +268,7 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&>div:last-child {
|
||||
& > div:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
296
src/views/projectLarge/ProjectScreen/components/newmap.vue
Normal file
296
src/views/projectLarge/ProjectScreen/components/newmap.vue
Normal file
@ -0,0 +1,296 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, onUnmounted,defineProps} from 'vue';
|
||||
import CesiumImageLabelEntity from '../js/CesiumImageLabelEntity.js';
|
||||
import CesiumFlyToRoamingController from '../js/CesiumFlyToRoamingController.js';
|
||||
import { setSelect, getSelectList, getGps } from '@/api/projectScreen/index.ts'
|
||||
import videoDialog from "./video.vue"
|
||||
const defaultExpandedKeys = [1, 2, 3] //默认展开第一级节点
|
||||
const defaultCheckedKeys = ref([]) //默认选中节点
|
||||
const data = ref([]);
|
||||
const deviceId = ref('');
|
||||
const videoDialogRef = ref(null);
|
||||
const props = defineProps({
|
||||
isHide:{
|
||||
type:Boolean,
|
||||
default:true,
|
||||
}
|
||||
})
|
||||
console.log('props', props);
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
}
|
||||
let entityManager = null;
|
||||
window.deviceMap = new Map();
|
||||
let list = ref([]);
|
||||
// 漫游实例
|
||||
let roamingController = null;
|
||||
// 获取GPS数据
|
||||
function getGpsData() {
|
||||
getGps('1897160897167638529').then(res => {
|
||||
console.log('res', res);
|
||||
if (res.code === 200) {
|
||||
data.value = res.data;
|
||||
if (res.data.length > 0) {
|
||||
res.data.forEach(element => {
|
||||
list.value = [...list.value, ...element.children]
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 设置选中节点
|
||||
function setCheckedNode(idList) {
|
||||
let obj = {
|
||||
projectId: '1897160897167638529',
|
||||
idList
|
||||
}
|
||||
setSelect(obj).then(res => {
|
||||
console.log('res', res);
|
||||
})
|
||||
}
|
||||
// 获取选中节点
|
||||
function getCheckedNode() {
|
||||
getSelectList({
|
||||
projectId: '1897160897167638529'
|
||||
}).then(res => {
|
||||
if (res.code == 200) {
|
||||
defaultCheckedKeys.value = res.data || []
|
||||
}
|
||||
})
|
||||
}
|
||||
// 渲染无人机、摄像头、定位设备
|
||||
function renderDevice(item) {
|
||||
const imageEntity = new CesiumImageLabelEntity(Earth1.viewer, {
|
||||
id: item.id,
|
||||
position: {
|
||||
lng: Number(item.lng),
|
||||
lat: Number(item.lat),
|
||||
height: 0
|
||||
},
|
||||
imageWidth: 64,
|
||||
imageHeight: 64,
|
||||
name: item.label || item.id,
|
||||
imageUrl: `/image/${item.type}.png`,
|
||||
onClick: (entity)=>{
|
||||
entityClickHandler(entity,item);
|
||||
}
|
||||
});
|
||||
window.deviceMap.set(item.id, imageEntity);
|
||||
}
|
||||
// 实体的点击事件
|
||||
function entityClickHandler(entity,item) {
|
||||
console.log('entity', entity,item);
|
||||
if (item.type == 'camera') {
|
||||
deviceId.value = 'AE9470016';
|
||||
videoDialogRef.value.show();
|
||||
videoDialogRef.value.videoPlay(deviceId.value);
|
||||
}
|
||||
}
|
||||
// 初始化地球
|
||||
function initEarth() {
|
||||
YJ.on({
|
||||
ws: true,
|
||||
host: '', //资源所在服务器地址
|
||||
username: '', //用户名 可以不登录(不填写用户名),不登录时无法加载服务端的数据
|
||||
password: '', //密码 生成方式:md5(用户名_密码)
|
||||
}).then((res) => {
|
||||
let earth = new YJ.YJEarth("earth");
|
||||
|
||||
window.Earth1 = earth;
|
||||
// 加载底图
|
||||
// earth.viewer.terrainProvider = Cesium.createWorldTerrain();
|
||||
// Earth1.viewer
|
||||
addArcgisLayer(Earth1.viewer, 'img_w')
|
||||
// 添加倾斜数据
|
||||
// loadTiltData(Earth1.viewer)
|
||||
// 获取中心点
|
||||
YJ.Global.CesiumContainer(window.Earth1, {
|
||||
compass: false,//罗盘
|
||||
legend: false, //图例
|
||||
});
|
||||
// 创建实体管理器实例
|
||||
list.value.forEach(item => {
|
||||
if (defaultCheckedKeys.value.includes(item.id)) {
|
||||
console.log("defaultCheckedKeys", item.id);
|
||||
renderDevice(item)
|
||||
}
|
||||
});
|
||||
roamingController = new CesiumFlyToRoamingController(window.Earth1.viewer, {
|
||||
duration: 5, // 每个点之间飞行5秒
|
||||
pitch: -89 // 20度俯角
|
||||
});
|
||||
window.roamingController = roamingController;
|
||||
})
|
||||
}
|
||||
// 加载倾斜数据
|
||||
function loadTiltData(viewer) {
|
||||
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
|
||||
// url: 'http://192.168.110.2:8895/yjearth4.0/data/pak/e904acb32aaa8b872c64866ebaaaf5e2',
|
||||
// url:"http://58.17.134.85:7363/yjearth4.0/data/pak/e904acb32aaa8b872c64866ebaaaf5e2"
|
||||
url: import.meta.env.VITE_EARTH_URL + "/yjearth4.0/data/pak/4eb21d3fc02873092e75640e261544b3"
|
||||
});
|
||||
}
|
||||
// 获取ArcGIS服务的URL
|
||||
function getArcGisUrlByType(type) {
|
||||
switch (type) {
|
||||
//影像
|
||||
case "img_w":
|
||||
return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer";
|
||||
//电子
|
||||
case "vec_w":
|
||||
return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer";
|
||||
//蓝色底图
|
||||
case "vec_blue":
|
||||
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer";
|
||||
//灰色底图
|
||||
case "vec_gray":
|
||||
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetGray/MapServer";
|
||||
//暖色底图
|
||||
case "vec_warm":
|
||||
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer";
|
||||
}
|
||||
}
|
||||
// 添加ArcGIS图层
|
||||
function addArcgisLayer(viewer, type) {
|
||||
let url = getArcGisUrlByType(type)
|
||||
const layerProvider = new Cesium.ArcGisMapServerImageryProvider({
|
||||
url: url
|
||||
});
|
||||
viewer.imageryLayers.addImageryProvider(layerProvider);
|
||||
}
|
||||
// 节点单击事件
|
||||
function handleNodeClick(data) {
|
||||
console.log('data', data);
|
||||
let entity = window.deviceMap.get(data.id);
|
||||
if (entity) {
|
||||
entity.flyTo();
|
||||
}
|
||||
}
|
||||
// 复选框选中事件
|
||||
function handleCheck(checkedNodes, nodes) {
|
||||
console.log('check', checkedNodes, nodes);
|
||||
// 处理单个节点的通用函数
|
||||
const handleNode = (node) => {
|
||||
if (!window.deviceMap.has(node.id)) {
|
||||
console.log("defaultCheckedKeys", node.id);
|
||||
renderDevice(node);
|
||||
} else {
|
||||
const device = window.deviceMap.get(node.id);
|
||||
// 根据当前显示状态切换显示/隐藏
|
||||
device[device.entity.show ? 'hide' : 'show']();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理选中的节点(可能是单个节点或包含子节点的集合)
|
||||
if (checkedNodes?.children?.length) {
|
||||
console.log('children', checkedNodes.children);
|
||||
checkedNodes.children.forEach(handleNode);
|
||||
} else {
|
||||
handleNode(checkedNodes);
|
||||
}
|
||||
|
||||
setCheckedNode(nodes.checkedKeys);
|
||||
}
|
||||
// 开始漫游
|
||||
function startRoaming() {
|
||||
if (roamingController) {
|
||||
roamingController.startPathRoaming([
|
||||
Cesium.Cartesian3.fromDegrees(106.49556855602525, 29.534393226355515, 200),
|
||||
Cesium.Cartesian3.fromDegrees(106.49142431645038, 29.534472802500083, 200),
|
||||
Cesium.Cartesian3.fromDegrees(106.49142125177437, 29.541881138875755, 200)
|
||||
], 3, false);
|
||||
} else {
|
||||
console.log('请先初始化地球');
|
||||
}
|
||||
}
|
||||
// 停止漫游
|
||||
function stopRoaming() {
|
||||
if (roamingController) {
|
||||
roamingController.stopRoaming();
|
||||
} else {
|
||||
console.log('请先初始化地球');
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
// 获取选中节点
|
||||
getCheckedNode();
|
||||
// 获取GPS数据
|
||||
getGpsData();
|
||||
// 初始化地球
|
||||
initEarth();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
window.deviceMap.forEach((item) => {
|
||||
item.destroy();
|
||||
})
|
||||
window.deviceMap.clear();
|
||||
window.roamingController.destroy();
|
||||
window.Earth1.destroy();
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="earth-container-big">
|
||||
<div class="earth" id="earth"></div>
|
||||
<div v-show="isHide" class="left">
|
||||
<div style="width: 100%;height: 100%;">
|
||||
<el-button type="primary" @click="startRoaming">开始漫游</el-button>
|
||||
<el-button type="primary" @click="stopRoaming">停止漫游</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="isHide" class="right">
|
||||
<el-tree show-checkbox :data="data" :props="defaultProps" node-key="id" :expand-on-click-node="false"
|
||||
:check-on-click-node="false" :check-on-click-leaf="false" :default-expanded-keys="defaultExpandedKeys"
|
||||
:default-checked-keys="defaultCheckedKeys" @check="handleCheck" @node-click="handleNodeClick" />
|
||||
</div>
|
||||
<videoDialog :data="deviceId" ref="videoDialogRef"></videoDialog>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.earth-container-big {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.earth {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.right {
|
||||
top: 50%;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.left {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.right,
|
||||
.left {
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
height: 100%;
|
||||
transform: translateY(-50%);
|
||||
background-color: #00000052;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
z-index: 10;
|
||||
|
||||
.el-tree {
|
||||
background-color: transparent;
|
||||
--el-tree-node-hover-bg-color: transparent;
|
||||
--el-tree-text-color: #fff;
|
||||
.el-text {
|
||||
color: azure;
|
||||
}
|
||||
|
||||
.el-tree-node__content:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
109
src/views/projectLarge/ProjectScreen/components/video.vue
Normal file
109
src/views/projectLarge/ProjectScreen/components/video.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="摄像头直播" :width="dialogWidth" :height="dialogHeight" :before-close="handleClose"
|
||||
destroy-on-close>
|
||||
<div class="video-container-entity" id="video-container-entity" style="width: 100%; height: 600px"></div>
|
||||
<!-- <template #footer>
|
||||
<el-button type="primary" @click="handlesubmit">确定</el-button>
|
||||
<el-button type="danger" @click="handleClose">关闭</el-button>
|
||||
</template> -->
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, defineEmits, defineProps,onUnmounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { getAccessToken } from '@/api/other/ys7Device';
|
||||
import EZUIKit from 'ezuikit-js';
|
||||
const emit = defineEmits(['send-data', 'close']);
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
}
|
||||
});
|
||||
// 弹窗控制变量
|
||||
const visible = ref(false);
|
||||
const dialogWidth = ref('950px');
|
||||
const dialogHeight = ref('90%');
|
||||
let loading = ref(true);
|
||||
const flvPlayer = ref(null);
|
||||
const show = () => {
|
||||
visible.value = true;
|
||||
}
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
// 处理数据传递
|
||||
const handlesubmit = () => {
|
||||
handleClose();
|
||||
};
|
||||
// 视频播放
|
||||
function videoPlay(deviceSerial) {
|
||||
getAccessToken().then((res) => {
|
||||
if (res.code == 200 && deviceSerial) {
|
||||
flvPlayer.value = new EZUIKit.EZUIKitPlayer({
|
||||
audio: '0',
|
||||
id: 'video-container-entity',
|
||||
accessToken: res.data,
|
||||
url: `ezopen://open.ys7.com/${deviceSerial}/1.hd.live`,
|
||||
template: 'pcLive',
|
||||
width: 870,
|
||||
height: 600,
|
||||
plugin: ['talk'],
|
||||
handleError: function (err) {
|
||||
console.log(err);
|
||||
if (err?.data?.ret === 20020) {
|
||||
// 20020 是并发连接限制的错误码
|
||||
ElMessage.error('当前观看人数已达上限,请稍后再试');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 组件挂载时设置容器ID
|
||||
onMounted(() => {
|
||||
|
||||
});
|
||||
|
||||
// 暴露显示方法给父组件
|
||||
defineExpose({
|
||||
show,
|
||||
videoPlay
|
||||
});
|
||||
|
||||
//
|
||||
onUnmounted(() => {
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.earth-container {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 10px;
|
||||
height: calc(100% - 100px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-dialog) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__content) {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
107
src/views/projectLarge/ProjectScreen/index.vue
Normal file
107
src/views/projectLarge/ProjectScreen/index.vue
Normal file
@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<div class="large_screen">
|
||||
<Header :projectId="projectId" :isFull="isFull" @changePage="handleChangePage" />
|
||||
<div class="nav">
|
||||
<div class="nav_left" :style="{ left: isHideOther ? '-25vw' : '0' }">
|
||||
<leftPage :projectId="projectId" />
|
||||
</div>
|
||||
<div class="nav_center" :style="{ width: isFull ? '100%' : 'calc(50vw - 30px)' }">
|
||||
<centerPage :projectId="projectId" :isHide="isFull" />
|
||||
</div>
|
||||
<div class="nav_right" :style="{ right: isHideOther ? '-25vw' : '0' }">
|
||||
<rightPage :projectId="projectId" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import Header from './components/header.vue';
|
||||
import leftPage from './components/leftPage.vue';
|
||||
import centerPage from './components/centerPage.vue';
|
||||
import rightPage from './components/rightPage.vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
const userStore = useUserStoreHook();
|
||||
const projectId = computed(() => userStore.selectedProject.id);
|
||||
const isFull = ref(false);
|
||||
const isHideOther = ref(false);
|
||||
|
||||
/**
|
||||
* 切换中心页面全屏
|
||||
*/
|
||||
const handleChangePage = () => {
|
||||
if (isFull.value) {
|
||||
isFull.value = false;
|
||||
setTimeout(() => {
|
||||
isHideOther.value = false;
|
||||
}, 500);
|
||||
} else {
|
||||
isFull.value = true;
|
||||
isHideOther.value = true;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.large_screen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: url('@/assets/large/bg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-attachment: fixed;
|
||||
background-color: rgba(4, 7, 17, 1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav {
|
||||
position: relative;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: calc(100vw - 30px);
|
||||
height: calc(100vh - 90px);
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav_left,
|
||||
.nav_right {
|
||||
position: absolute;
|
||||
width: calc(25vw - 15px);
|
||||
height: 100%;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.nav_left {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.nav_right {
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.nav_center {
|
||||
height: 100%;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
/* 中间面板全屏动画 */
|
||||
.full-width {
|
||||
/* 取消flex增长,使用固定宽度 */
|
||||
width: calc(100vw - 30px);
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.slide_left {
|
||||
left: -25vw;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.slide_right {
|
||||
right: -25vw;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,293 @@
|
||||
export default class CesiumFlyToRoamingController {
|
||||
/**
|
||||
* 构造函数 - 创建基于flyTo的漫游控制器
|
||||
* @param {Cesium.Viewer} viewer - Cesium Viewer实例
|
||||
* @param {Object} [options] - 漫游配置选项
|
||||
* @param {number} [options.duration=3] - 飞行持续时间(秒)
|
||||
* @param {number} [options.pitch=-30] - 俯仰角(度)
|
||||
* @param {number} [options.headingOffset=0] - 航向偏移(度)
|
||||
*/
|
||||
constructor(viewer, options = {}) {
|
||||
if (!viewer || !(viewer instanceof Cesium.Viewer)) {
|
||||
throw new Error('必须提供有效的Cesium Viewer实例');
|
||||
}
|
||||
|
||||
this.viewer = viewer;
|
||||
this.isRoaming = false;
|
||||
this.path = [];
|
||||
this.currentIndex = -1; // 初始为-1,表示尚未开始
|
||||
this.loop = false;
|
||||
this.duration = options.duration || 3;
|
||||
this.pitch = Cesium.Math.toRadians(options.pitch || -30);
|
||||
this.headingOffset = Cesium.Math.toRadians(options.headingOffset || 0);
|
||||
this.flyToOptions = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始路径漫游 - 严格按照路径点顺序,首先飞入第一个点位
|
||||
* @param {Array} path - 路径点数组(按顺序排列)
|
||||
* @param {number} [duration] - 飞行持续时间(秒)
|
||||
* @param {boolean} [loop=false] - 是否循环漫游
|
||||
*/
|
||||
startPathRoaming(path, duration, loop = false) {
|
||||
if (!path || path.length < 1) {
|
||||
throw new Error('路径漫游需要至少1个路径点');
|
||||
}
|
||||
|
||||
// 停止当前可能的漫游
|
||||
this.stopRoaming();
|
||||
|
||||
// 初始化参数
|
||||
this.path = [...path];
|
||||
this.loop = loop;
|
||||
this.currentIndex = -1; // 重置为初始状态
|
||||
|
||||
if (duration !== undefined) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
this.isRoaming = true;
|
||||
|
||||
// 第一步:飞到第一个点位
|
||||
this.flyToFirstPoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* 专门用于飞到第一个点位的方法
|
||||
*/
|
||||
flyToFirstPoint() {
|
||||
if (!this.isRoaming || this.path.length === 0) return;
|
||||
|
||||
const firstPointIndex = 0;
|
||||
const firstPoint = this.path[firstPointIndex];
|
||||
|
||||
// 计算朝向:如果有第二个点,则面向第二个点,否则保持当前朝向
|
||||
let orientation;
|
||||
if (this.path.length > 1) {
|
||||
orientation = this.calculateOrientation(firstPoint, this.path[1]);
|
||||
} else {
|
||||
orientation = {
|
||||
heading: this.viewer.camera.heading,
|
||||
pitch: this.pitch,
|
||||
roll: 0
|
||||
};
|
||||
}
|
||||
|
||||
// 飞行到第一个点
|
||||
this.flyToOptions = {
|
||||
destination: firstPoint,
|
||||
orientation: orientation,
|
||||
duration: this.duration,
|
||||
complete: () => {
|
||||
// 第一个点到达后更新索引
|
||||
this.currentIndex = firstPointIndex;
|
||||
|
||||
// 如果有更多点,继续飞行到下一个点
|
||||
if (this.path.length > 1) {
|
||||
this.flyToNextPoint();
|
||||
} else {
|
||||
// 只有一个点时,完成后停止漫游
|
||||
this.isRoaming = false;
|
||||
}
|
||||
},
|
||||
cancel: () => {
|
||||
this.isRoaming = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.viewer.camera.flyTo(this.flyToOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 飞行到下一个路径点
|
||||
*/
|
||||
flyToNextPoint() {
|
||||
if (!this.isRoaming || this.currentIndex === -1) return;
|
||||
|
||||
// 计算下一个点的索引
|
||||
const nextIndex = this.currentIndex + 1;
|
||||
|
||||
// 检查是否超出路径范围
|
||||
if (nextIndex >= this.path.length) {
|
||||
if (this.loop) {
|
||||
// 循环模式:回到第一个点
|
||||
this.currentIndex = -1;
|
||||
this.flyToFirstPoint();
|
||||
} else {
|
||||
// 非循环模式:到达终点,停止漫游
|
||||
this.isRoaming = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新当前索引并获取目标点
|
||||
this.currentIndex = nextIndex;
|
||||
const targetPoint = this.path[this.currentIndex];
|
||||
|
||||
// 计算朝向
|
||||
let orientation;
|
||||
if (this.currentIndex < this.path.length - 1) {
|
||||
// 面向下一个点
|
||||
orientation = this.calculateOrientation(targetPoint, this.path[this.currentIndex + 1]);
|
||||
} else if (this.loop) {
|
||||
// 最后一个点且循环模式,面向第一个点
|
||||
orientation = this.calculateOrientation(targetPoint, this.path[0]);
|
||||
} else {
|
||||
// 最后一个点且不循环,保持当前朝向
|
||||
orientation = {
|
||||
heading: this.viewer.camera.heading,
|
||||
pitch: this.pitch,
|
||||
roll: 0
|
||||
};
|
||||
}
|
||||
|
||||
// 执行飞行
|
||||
this.flyToOptions = {
|
||||
destination: targetPoint,
|
||||
orientation: orientation,
|
||||
duration: this.duration,
|
||||
complete: () => this.flyToNextPoint(),
|
||||
cancel: () => { this.isRoaming = false; }
|
||||
};
|
||||
|
||||
this.viewer.camera.flyTo(this.flyToOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算相机朝向
|
||||
* @param {Cesium.Cartesian3} position - 相机位置
|
||||
* @param {Cesium.Cartesian3} lookAtPoint - 看向的点
|
||||
* @returns {Object} 朝向配置
|
||||
*/
|
||||
calculateOrientation(position, lookAtPoint) {
|
||||
const direction = Cesium.Cartesian3.subtract(lookAtPoint, position, new Cesium.Cartesian3());
|
||||
const heading = Math.atan2(direction.x, direction.y) + this.headingOffset;
|
||||
|
||||
return {
|
||||
heading: heading,
|
||||
pitch: this.pitch,
|
||||
roll: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止漫游
|
||||
*/
|
||||
stopRoaming() {
|
||||
if (this.isRoaming) {
|
||||
this.isRoaming = false;
|
||||
if (this.flyToOptions) {
|
||||
this.viewer.camera.cancelFlight();
|
||||
this.flyToOptions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停漫游
|
||||
*/
|
||||
pauseRoaming() {
|
||||
if (this.isRoaming) {
|
||||
this.isRoaming = false;
|
||||
if (this.flyToOptions) {
|
||||
this.viewer.camera.cancelFlight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复漫游
|
||||
*/
|
||||
resumeRoaming() {
|
||||
if (!this.isRoaming && this.path.length > 0) {
|
||||
this.isRoaming = true;
|
||||
if (this.currentIndex === -1) {
|
||||
this.flyToFirstPoint();
|
||||
} else {
|
||||
this.flyToNextPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加路径点
|
||||
* @param {Cesium.Cartesian3} point - 路径点
|
||||
*/
|
||||
addPathPoint(point) {
|
||||
if (point instanceof Cesium.Cartesian3) {
|
||||
this.path.push(point);
|
||||
} else {
|
||||
console.warn('路径点必须是Cesium.Cartesian3类型');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除路径
|
||||
*/
|
||||
clearPath() {
|
||||
this.stopRoaming();
|
||||
this.path = [];
|
||||
this.currentIndex = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置飞行持续时间
|
||||
* @param {number} duration - 持续时间(秒)
|
||||
*/
|
||||
setDuration(duration) {
|
||||
if (typeof duration === 'number' && duration > 0) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁控制器
|
||||
*/
|
||||
destroy() {
|
||||
this.stopRoaming();
|
||||
this.viewer = null;
|
||||
this.path = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用示例:
|
||||
// 假设已经有一个Cesium Viewer实例叫做viewer
|
||||
//
|
||||
// // 创建漫游控制器
|
||||
// const roamingController = new CesiumRoamingController(viewer, {
|
||||
// speed: 20,
|
||||
// pitch: -20, // 20度俯角
|
||||
// headingOffset: 0
|
||||
// });
|
||||
//
|
||||
// // 示例1: 自由漫游
|
||||
// // 开始自由漫游
|
||||
// document.getElementById('startFreeRoam').addEventListener('click', () => {
|
||||
// roamingController.startFreeRoaming(15); // 速度15米/秒
|
||||
// });
|
||||
//
|
||||
// // 示例2: 路径漫游
|
||||
// // 创建路径点
|
||||
// const pathPoints = [
|
||||
// Cesium.Cartesian3.fromDegrees(116.3, 39.9, 200),
|
||||
// Cesium.Cartesian3.fromDegrees(116.4, 39.9, 200),
|
||||
// Cesium.Cartesian3.fromDegrees(116.4, 40.0, 200),
|
||||
// Cesium.Cartesian3.fromDegrees(116.3, 40.0, 200)
|
||||
// ];
|
||||
//
|
||||
// // 开始路径漫游
|
||||
// document.getElementById('startPathRoam').addEventListener('click', () => {
|
||||
// roamingController.startPathRoaming(pathPoints, 30, true); // 速度30米/秒,循环漫游
|
||||
// });
|
||||
//
|
||||
// // 停止漫游
|
||||
// document.getElementById('stopRoam').addEventListener('click', () => {
|
||||
// roamingController.stopRoaming();
|
||||
// });
|
||||
//
|
||||
// // 调整速度
|
||||
// document.getElementById('speedUp').addEventListener('click', () => {
|
||||
// const currentSpeed = roamingController.speed;
|
||||
// roamingController.setSpeed(currentSpeed + 5);
|
||||
// });
|
||||
|
@ -0,0 +1,298 @@
|
||||
export default class CesiumImageLabelEntity {
|
||||
/**
|
||||
* 构造函数 - 创建带有图片和名称的Cesium Entity
|
||||
* @param {Cesium.Viewer} viewer - Cesium Viewer实例
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {Cesium.Cartesian3} options.position - 实体位置坐标
|
||||
* @param {string} options.name - 实体名称(标签文本)
|
||||
* @param {string} options.imageUrl - 图片URL
|
||||
* @param {Function} [options.onClick] - 左击事件回调函数
|
||||
* @param {string} [options.id] - 实体ID,可选
|
||||
* @param {number} [options.imageWidth=64] - 图片宽度
|
||||
* @param {number} [options.imageHeight=64] - 图片高度
|
||||
* @param {Cesium.Color} [options.imageColor=Cesium.Color.WHITE] - 图片颜色(用于色调调整)
|
||||
* @param {Cesium.Color} [options.labelColor=Cesium.Color.WHITE] - 标签颜色
|
||||
* @param {string} [options.labelFont='16px sans-serif'] - 标签字体
|
||||
* @param {number} [options.labelOffsetY=-70] - 标签Y轴偏移量(相对于图片)
|
||||
* @param {boolean} [options.show=true] - 是否显示实体
|
||||
* @param {Cesium.HorizontalOrigin} [options.horizontalOrigin=Cesium.HorizontalOrigin.CENTER] - 水平对齐方式
|
||||
* @param {Cesium.VerticalOrigin} [options.verticalOrigin=Cesium.VerticalOrigin.BOTTOM] - 垂直对齐方式
|
||||
*/
|
||||
constructor(viewer, options) {
|
||||
// 验证必要参数
|
||||
if (!viewer || !(viewer instanceof Cesium.Viewer)) {
|
||||
throw new Error('必须提供有效的Cesium Viewer实例');
|
||||
}
|
||||
if (!options || !options.position) {
|
||||
throw new Error('必须提供实体位置信息');
|
||||
}
|
||||
if (!options.name) {
|
||||
throw new Error('必须提供实体名称');
|
||||
}
|
||||
if (!options.imageUrl) {
|
||||
throw new Error('必须提供图片URL');
|
||||
}
|
||||
|
||||
this.viewer = viewer;
|
||||
this.onClickCallback = options.onClick || null;
|
||||
this.options = {
|
||||
// 默认配置
|
||||
id: options.id || `image-label-entity-${Date.now()}`,
|
||||
imageWidth: options.imageWidth || 64,
|
||||
imageHeight: options.imageHeight || 64,
|
||||
imageColor: options.imageColor || Cesium.Color.WHITE,
|
||||
labelColor: options.labelColor || Cesium.Color.WHITE,
|
||||
labelFont: options.labelFont || '16px sans-serif',
|
||||
labelOffsetY: options.labelOffsetY || -80,
|
||||
show: options.show !== undefined ? options.show : true,
|
||||
horizontalOrigin: options.horizontalOrigin || Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: options.verticalOrigin || Cesium.VerticalOrigin.BOTTOM,
|
||||
...options
|
||||
};
|
||||
|
||||
// 创建实体
|
||||
this.entity = this.createEntity();
|
||||
|
||||
// 为实体添加标识,方便后续判断
|
||||
this.entity._isImageLabelEntity = true;
|
||||
this.entity._imageLabelInstance = this;
|
||||
|
||||
// 初始化全局点击事件(确保只注册一次)
|
||||
this.initGlobalClickHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建实体
|
||||
* @returns {Cesium.Entity} 创建的实体对象
|
||||
*/
|
||||
createEntity() {
|
||||
const entity = new Cesium.Entity({
|
||||
id: this.options.id,
|
||||
position: Cesium.Cartesian3.fromDegrees(
|
||||
this.options.position.lng,
|
||||
this.options.position.lat,
|
||||
this.options.position.height || 0 // 修复:使用height而非alt
|
||||
),
|
||||
show: this.options.show,
|
||||
|
||||
// 图片属性
|
||||
billboard: {
|
||||
image: this.options.imageUrl,
|
||||
width: this.options.imageWidth,
|
||||
height: this.options.imageHeight,
|
||||
color: this.options.imageColor,
|
||||
horizontalOrigin: this.options.horizontalOrigin,
|
||||
verticalOrigin: this.options.verticalOrigin,
|
||||
pickable: true // 确保可拾取
|
||||
},
|
||||
|
||||
// 名称标签属性
|
||||
label: {
|
||||
text: this.options.name,
|
||||
font: this.options.labelFont,
|
||||
fillColor: this.options.labelColor,
|
||||
horizontalOrigin: this.options.horizontalOrigin,
|
||||
verticalOrigin: Cesium.VerticalOrigin.TOP,
|
||||
pixelOffset: new Cesium.Cartesian2(0, this.options.labelOffsetY),
|
||||
backgroundColor: new Cesium.Color(0, 0, 0, 0.5), // 修复:半透明背景更易点击
|
||||
backgroundPadding: new Cesium.Cartesian2(5, 5),
|
||||
showBackground: true,
|
||||
pickable: true // 确保可拾取
|
||||
}
|
||||
});
|
||||
|
||||
// 将实体添加到viewer
|
||||
this.viewer.entities.add(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化全局点击事件处理器(只注册一次)
|
||||
*/
|
||||
initGlobalClickHandler() {
|
||||
// 检查是否已注册全局事件,避免重复注册
|
||||
if (!this.viewer._imageLabelGlobalClickHandler) {
|
||||
const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
|
||||
|
||||
handler.setInputAction((movement) => {
|
||||
const pickedObject = this.viewer.scene.pick(movement.position);
|
||||
|
||||
// 判断是否点击了我们创建的图片标签实体
|
||||
if (Cesium.defined(pickedObject) &&
|
||||
Cesium.defined(pickedObject.id) &&
|
||||
pickedObject.id._isImageLabelEntity) {
|
||||
// 调用对应实例的回调函数
|
||||
if (pickedObject.id._imageLabelInstance.onClickCallback) {
|
||||
pickedObject.id._imageLabelInstance.onClickCallback(
|
||||
pickedObject.id,
|
||||
movement.position
|
||||
);
|
||||
}
|
||||
}
|
||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
||||
|
||||
// 存储全局事件处理器引用,避免重复创建
|
||||
this.viewer._imageLabelGlobalClickHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置点击事件回调函数
|
||||
* @param {Function} callback - 回调函数,接收(entity, position)参数
|
||||
*/
|
||||
setOnClick(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.onClickCallback = callback;
|
||||
} else {
|
||||
console.warn('回调函数必须是一个函数');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 平滑飞行到实体当前位置
|
||||
* @param {Object} [options] - 飞行参数配置
|
||||
* @param {number} [options.duration=3] - 飞行持续时间(秒)
|
||||
* @param {number} [options.offsetDistance=1000] - 距离目标点的距离(米)
|
||||
* @param {Cesium.HeadingPitchRange} [options.headingPitchRange] - 方向、俯仰和范围,优先级高于offsetDistance
|
||||
* @param {Function} [options.complete] - 飞行完成后的回调函数
|
||||
* @param {Function} [options.cancel] - 飞行被取消后的回调函数
|
||||
*/
|
||||
flyTo(options = {}) {
|
||||
// 获取实体当前位置(考虑可能已更新的情况)
|
||||
const currentPosition = this.entity?.position?.getValue(Cesium.JulianDate.now());
|
||||
|
||||
if (!currentPosition) {
|
||||
console.warn('无法飞行到实体,实体或实体位置不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
// 默认飞行参数
|
||||
const defaultOptions = {
|
||||
duration: 3,
|
||||
offsetDistance: 1000,
|
||||
complete: () => {},
|
||||
cancel: () => {}
|
||||
};
|
||||
|
||||
// 合并用户配置和默认配置
|
||||
const flyOptions = { ...defaultOptions, ...options };
|
||||
|
||||
// 计算飞行视角
|
||||
let headingPitchRange;
|
||||
if (flyOptions.headingPitchRange) {
|
||||
headingPitchRange = flyOptions.headingPitchRange;
|
||||
} else {
|
||||
// 默认视角:从上方稍远处看向实体
|
||||
headingPitchRange = new Cesium.HeadingPitchRange(
|
||||
0, // 方向角(弧度)
|
||||
Cesium.Math.toRadians(-30), // 俯仰角(弧度),负值表示向下看
|
||||
flyOptions.offsetDistance // 距离目标点的距离
|
||||
);
|
||||
}
|
||||
|
||||
// 执行飞行到当前位置
|
||||
this.viewer.flyTo(this.entity, {
|
||||
destination: currentPosition, // 明确指定当前位置作为目标
|
||||
duration: flyOptions.duration,
|
||||
offset: headingPitchRange,
|
||||
complete: flyOptions.complete,
|
||||
cancel: flyOptions.cancel
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新实体位置
|
||||
* @param {Cesium.Cartesian3} position - 新的位置坐标
|
||||
*/
|
||||
updatePosition(position) {
|
||||
if (position && this.entity) {
|
||||
this.entity.position = position;
|
||||
// 更新options中的位置,保持同步
|
||||
this.options.position = position;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新实体名称
|
||||
* @param {string} name - 新的名称
|
||||
*/
|
||||
updateName(name) {
|
||||
if (name && this.entity && this.entity.label) {
|
||||
this.entity.label.text = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新实体图片
|
||||
* @param {string} imageUrl - 新的图片URL
|
||||
*/
|
||||
updateImage(imageUrl) {
|
||||
if (imageUrl && this.entity && this.entity.billboard) {
|
||||
this.entity.billboard.image = imageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示实体
|
||||
*/
|
||||
show() {
|
||||
if (this.entity) {
|
||||
this.entity.show = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏实体
|
||||
*/
|
||||
hide() {
|
||||
if (this.entity) {
|
||||
this.entity.show = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除实体
|
||||
*/
|
||||
remove() {
|
||||
if (this.entity) {
|
||||
this.viewer.entities.remove(this.entity);
|
||||
this.entity = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实体
|
||||
* @returns {Cesium.Entity} 当前实体对象
|
||||
*/
|
||||
getEntity() {
|
||||
return this.entity;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用示例:
|
||||
// 假设已经有一个Cesium Viewer实例叫做viewer
|
||||
// // 创建实体
|
||||
// const initialPosition = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 100);
|
||||
// const imageEntity = new CesiumImageLabelEntity(viewer, {
|
||||
// position: initialPosition,
|
||||
// name: "可移动点",
|
||||
// imageUrl: "path/to/your/image.png",
|
||||
// onClick: function(entity) {
|
||||
// console.log("点击了实体,飞向当前位置");
|
||||
// entity.flyTo(); // 飞向当前位置
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // 一段时间后更新位置
|
||||
// setTimeout(() => {
|
||||
// const newPosition = Cesium.Cartesian3.fromDegrees(116.45, 39.92, 100);
|
||||
// imageEntity.updatePosition(newPosition);
|
||||
// console.log("实体位置已更新");
|
||||
// }, 2000);
|
||||
//
|
||||
// // 调用flyTo将飞向最新的位置
|
||||
// setTimeout(() => {
|
||||
// imageEntity.flyTo({duration: 2});
|
||||
// }, 4000);
|
||||
|
@ -46,16 +46,16 @@
|
||||
:load="loadChildren"
|
||||
:has-children="hasChildren"
|
||||
>
|
||||
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
|
||||
<el-table-column prop="icon" label="图标" align="center" width="100">
|
||||
<el-table-column align="center" prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
|
||||
<el-table-column align="center" prop="icon" label="图标" width="100">
|
||||
<template #default="scope">
|
||||
<svg-icon :icon-class="scope.row.icon" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
|
||||
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="80">
|
||||
<el-table-column align="center" prop="orderNum" label="排序" width="60"></el-table-column>
|
||||
<el-table-column align="center" prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column align="center" prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column align="center" prop="status" label="状态" width="80">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
|
||||
</template>
|
||||
@ -65,7 +65,7 @@
|
||||
<span>{{ scope.row.createTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="180">
|
||||
<el-table-column align="center" fixed="right" label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button v-hasPermi="['system:menu:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
|
||||
|
@ -27,6 +27,9 @@
|
||||
<el-form-item label="用户名称" prop="userName">
|
||||
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户昵称" prop="nickName">
|
||||
<el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phonenumber">
|
||||
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
|
@ -81,8 +81,8 @@
|
||||
changePrice(scope.row);
|
||||
}
|
||||
"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
:precision="4"
|
||||
:min="0"
|
||||
:controls="false"
|
||||
v-if="scope.row.quantity && scope.row.quantity != 0"
|
||||
:disabled="versionsData.status != 'draft'"
|
||||
@ -91,7 +91,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="taxRate" label="税率" width="100" align="center">
|
||||
@ -154,7 +154,7 @@ interface VersionItem {
|
||||
}
|
||||
|
||||
// 实例与状态初始化
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const userStore = useUserStoreHook();
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
|
||||
|
@ -41,10 +41,14 @@
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.unitPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -41,10 +41,14 @@
|
||||
<el-table-column prop="specification" label="规格" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.unitPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -2,22 +2,14 @@
|
||||
<el-dialog v-model="dialogVisible" title="招标文件" width="500" draggable>
|
||||
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
|
||||
<el-form-item label="招标文件" prop="name">
|
||||
<file-upload
|
||||
v-model="form.costEstimationFile"
|
||||
:fileSize="100"
|
||||
:auto-upload="false"
|
||||
uploadUrl="/tender/biddingPlan/uploadBiddingDocuments"
|
||||
method="put"
|
||||
ref="fileUploadRef"
|
||||
:data="{
|
||||
<file-upload v-model="form.costEstimationFile" :fileSize="100" :auto-upload="false" @handleRemove="handleRemove"
|
||||
uploadUrl="/tender/biddingPlan/uploadBiddingDocuments" method="put" ref="fileUploadRef" :data="{
|
||||
projectId: currentProject?.id,
|
||||
type: planType,
|
||||
fileType: '1',
|
||||
bidStatus: '0',
|
||||
id: row.id
|
||||
}"
|
||||
showFileList
|
||||
/>
|
||||
}" showFileList />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@ -45,7 +37,11 @@ const emit = defineEmits(['success']);
|
||||
const form = ref({
|
||||
costEstimationFile: ''
|
||||
});
|
||||
const handleRemove = (file: any, fileList: any) => {
|
||||
console.log(file, fileList);
|
||||
console.log('handleRemove', form.value);
|
||||
|
||||
};
|
||||
const open = (rows: any, type: string) => {
|
||||
dialogVisible.value = true;
|
||||
console.log(rows, type);
|
||||
|
@ -7,23 +7,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="中标文件" prop="name">
|
||||
<file-upload
|
||||
v-model="form.costEstimationFile"
|
||||
:fileSize="100"
|
||||
:auto-upload="false"
|
||||
uploadUrl="/tender/biddingPlan/uploadBiddingDocuments"
|
||||
method="put"
|
||||
ref="fileUploadRef"
|
||||
:data="{
|
||||
<file-upload v-model="form.costEstimationFile" :fileSize="100" :auto-upload="false"
|
||||
uploadUrl="/tender/biddingPlan/uploadBiddingDocuments" method="put" ref="fileUploadRef" :data="{
|
||||
projectId: currentProject?.id,
|
||||
type: planType,
|
||||
fileType: '0',
|
||||
bidStatus: '0',
|
||||
id: row.id,
|
||||
winningBidderId: form.winningBidder
|
||||
}"
|
||||
showFileList
|
||||
/>
|
||||
}" showFileList />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
@ -13,7 +13,8 @@
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
<el-button type="primary" plain :icon="Plus" @click="openDialog" v-hasPermi="['tender:biddingPlan:add']">新增</el-button>
|
||||
<el-button type="primary" plain :icon="Plus" @click="openDialog"
|
||||
v-hasPermi="['tender:biddingPlan:add']">新增</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@ -25,13 +26,16 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="名称" align="center" />
|
||||
<el-table-column prop="content" label="内容" align="center" />
|
||||
<el-table-column prop="price" label="限价" align="center" />
|
||||
<el-table-column prop="price" label="限价" align="center">
|
||||
<template #default="scope">
|
||||
{{ proxy.formatPrice(scope.row.price) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bidd" align="center">
|
||||
<template #header> <span style="color: red">*</span>招标文件 </template>
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link v-hasPermi="['tender:biddingPlan:getAnnex']" @click="biddView(scope.row)" v-if="scope.row.annexCount > 0"
|
||||
>查看文件({{ scope.row.annexCount }})</el-button
|
||||
>
|
||||
<el-button type="primary" link v-hasPermi="['tender:biddingPlan:getAnnex']" @click="biddView(scope.row)"
|
||||
v-if="scope.row.annexCount > 0">查看文件({{ scope.row.annexCount }})</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="winningBidder" align="center">
|
||||
@ -43,102 +47,57 @@
|
||||
<el-table-column prop="bidFileName" align="center">
|
||||
<template #header> <span style="color: red">*</span>中标文件 </template>
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="openPdf(scope.row.bidFile)">{{ scope.row.bidFileName }} </el-button>
|
||||
<el-button type="primary" link @click="openPdf(scope.row.bidFile)">{{ scope.row.bidFileName }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="plannedBiddingTime" align="center" width="250">
|
||||
<template #header> <span style="color: red">*</span>计划招标时间 </template>
|
||||
<template #default="scope">
|
||||
<el-date-picker
|
||||
v-model="scope.row.plannedBiddingTime"
|
||||
@change="
|
||||
(val: any) => {
|
||||
changeBiddingTime(val, scope.row);
|
||||
}
|
||||
"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="选择时间"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:edit']"
|
||||
/>
|
||||
<el-date-picker v-model="scope.row.plannedBiddingTime" @change="
|
||||
(val: any) => {
|
||||
changeBiddingTime(val, scope.row);
|
||||
}
|
||||
" type="date" value-format="YYYY-MM-DD" placeholder="选择时间" :disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:edit']" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="contractPrice" align="center" width="200">
|
||||
<template #header> <span style="color: red">*</span>合同金额 </template>
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
:model-value="scope.row.contractPrice"
|
||||
@change="
|
||||
(val) => {
|
||||
scope.row.contractPrice = val;
|
||||
changeContractPrice(val, scope.row);
|
||||
}
|
||||
"
|
||||
:precision="2"
|
||||
:step="1"
|
||||
:controls="false"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:edit']"
|
||||
/>
|
||||
<el-input-number :model-value="scope.row.contractPrice" @change="
|
||||
(val) => {
|
||||
scope.row.contractPrice = val;
|
||||
changeContractPrice(val, scope.row);
|
||||
}
|
||||
" :precision="4" :min="0" :controls="false" :disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:edit']" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="price" label="操作" align="center" width="400">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="FolderOpened"
|
||||
@click="handleSave(scope.row)"
|
||||
v-hasPermi="['tender:biddingPlan:uploadBiddingDocuments']"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
>招标上传
|
||||
<el-button type="primary" link icon="FolderOpened" @click="handleSave(scope.row)"
|
||||
v-hasPermi="['tender:biddingPlan:uploadBiddingDocuments']" :disabled="scope.row.bidStatus == 1">招标上传
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="FolderOpened"
|
||||
@click="handleWinTheBid(scope.row)"
|
||||
v-hasPermi="['tender:biddingPlan:uploadBiddingDocuments']"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
>中标上传
|
||||
<el-button type="primary" link icon="FolderOpened" @click="handleWinTheBid(scope.row)"
|
||||
v-hasPermi="['tender:biddingPlan:uploadBiddingDocuments']" :disabled="scope.row.bidStatus == 1">中标上传
|
||||
</el-button>
|
||||
<!-- <el-button type="primary" link icon="Edit" @click="handleSave(scope.row)" v-hasPermi="['tender:segmentedIndicatorPlanning:edit']"
|
||||
>信息
|
||||
</el-button> -->
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="View"
|
||||
@click="handleDetail(scope.row)"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:getMore']"
|
||||
>详情</el-button
|
||||
>
|
||||
<el-button type="primary" link icon="View" @click="handleDetail(scope.row)"
|
||||
:disabled="scope.row.bidStatus == 1" v-hasPermi="['tender:biddingPlan:getMore']">详情</el-button>
|
||||
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Delete"
|
||||
@click="delHandle(scope.row)"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Lock"
|
||||
@click="editStatusBtn(scope.row)"
|
||||
:disabled="scope.row.bidStatus == 1"
|
||||
v-hasPermi="['tender:biddingPlan:editStatus']"
|
||||
>确定</el-button
|
||||
>
|
||||
<el-button type="primary" link icon="Delete" @click="delHandle(scope.row)"
|
||||
:disabled="scope.row.bidStatus == 1" v-hasPermi="['tender:biddingPlan:remove']">删除</el-button>
|
||||
<el-button type="primary" link icon="Lock" @click="editStatusBtn(scope.row)"
|
||||
:disabled="scope.row.bidStatus == 1" v-hasPermi="['tender:biddingPlan:editStatus']">确定</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-dialog title="新增" v-model="dialogVisible" width="75%" draggable>
|
||||
@ -160,7 +119,8 @@
|
||||
<el-form :model="treeForm" :inline="true">
|
||||
<el-form-item label="版本号" prop="versions">
|
||||
<el-select v-model="treeForm.versions" placeholder="选择版本号" @change="changeVersions">
|
||||
<el-option v-for="item in options" :key="item.versions" :label="item.versions" :value="item.versions" />
|
||||
<el-option v-for="item in options" :key="item.versions" :label="item.versions"
|
||||
:value="item.versions" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表名" prop="sheet" v-if="planType == '2'">
|
||||
@ -173,16 +133,8 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-table
|
||||
:data="treeData"
|
||||
ref="treeTableRef"
|
||||
v-loading="treeLoading"
|
||||
row-key="id"
|
||||
border
|
||||
lazy
|
||||
default-expand-all
|
||||
@selection-change="handleSelection"
|
||||
>
|
||||
<el-table :data="treeData" ref="treeTableRef" v-loading="treeLoading" row-key="id" border lazy
|
||||
default-expand-all @selection-change="handleSelection">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="num" label="编号" />
|
||||
<el-table-column prop="name" label="工程或费用名称" />
|
||||
@ -196,52 +148,50 @@
|
||||
(scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0) ==
|
||||
0
|
||||
0
|
||||
? activeTab == 2
|
||||
? 0
|
||||
: ''
|
||||
: (
|
||||
(scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0)
|
||||
).toFixed(2)
|
||||
(scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0)
|
||||
).toFixed(2)
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="selectNum" label="设计量" align="center">
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
:model-value="scope.row.selectNum"
|
||||
@change="
|
||||
(val) => {
|
||||
scope.row.selectNum = val;
|
||||
handleNumberChange(scope.row);
|
||||
}
|
||||
"
|
||||
:precision="2"
|
||||
:step="1"
|
||||
:controls="false"
|
||||
:max="Math.floor(scope.row.quantity)"
|
||||
v-if="scope.row.quantity && scope.row.quantity != 0 && scope.row.unitPrice"
|
||||
/>
|
||||
<el-input-number :model-value="scope.row.selectNum" @change="
|
||||
(val) => {
|
||||
scope.row.selectNum = val;
|
||||
handleNumberChange(scope.row);
|
||||
}
|
||||
" :precision="2" :step="1" :controls="false" :max="Math.floor(scope.row.quantity)"
|
||||
v-if="scope.row.quantity && scope.row.quantity != 0 && scope.row.unitPrice" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unitPrice" label="单价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.unitPrice ? proxy.formatPrice(scope.row.unitPrice) : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unitPrice" label="单价" align="center" />
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{
|
||||
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice) ==
|
||||
0
|
||||
? ''
|
||||
: (
|
||||
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice)
|
||||
).toFixed(2)
|
||||
proxy.formatPrice(
|
||||
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice) ==
|
||||
0
|
||||
? ''
|
||||
: ((scope.row.quantity ? Number(scope.row.quantity) : 0) -
|
||||
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
|
||||
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
|
||||
Number(scope.row.unitPrice),
|
||||
false
|
||||
)
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -259,10 +209,14 @@
|
||||
<el-table-column prop="name" label="工程或费用名称" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center" />
|
||||
<el-table-column prop="unitPrice" label="单价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.unitPrice ? proxy.formatPrice(scope.row.unitPrice) : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总价" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.price }}
|
||||
{{ scope.row.price ? proxy.formatPrice(scope.row.price) : '' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -274,15 +228,8 @@
|
||||
<el-table-column prop="price" label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="View" @click="openPdf(scope.row.url)">查看</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Delete"
|
||||
@click="delHandlebidd(scope.row)"
|
||||
v-if="scope.row.bidStatus != 1"
|
||||
v-hasPermi="['tender:biddingPlanAnnex:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="primary" link icon="Delete" @click="delHandlebidd(scope.row)"
|
||||
v-if="scope.row.bidStatus != 1" v-hasPermi="['tender:biddingPlanAnnex:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -294,12 +241,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getCurrentInstance, ComponentInternalInstance } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { getDicts } from '@/api/system/dict/data';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import winTheBid from './comm/winTheBid.vue';
|
||||
import information from './comm/planPage.vue';
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
import {
|
||||
sheetList,
|
||||
@ -713,6 +662,7 @@ const delHandlebidd = (row: any) => {
|
||||
});
|
||||
biddView(biddViewRow.value);
|
||||
}
|
||||
getList()
|
||||
});
|
||||
};
|
||||
//修改状态
|
||||
|
@ -31,9 +31,12 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['supplierInput:supplierInput:add']">新增</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplierInput:supplierInput:export']">导出</el-button>
|
||||
</el-col> -->
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Upload" @click="handleImport" v-hasPermi="['supplierInput:supplierInput:import']">导入</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplierInput:supplierInput:export']">导出模板</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
@ -223,8 +226,8 @@
|
||||
<!-- 第十行:安全生产许可证有效期(仅劳务类型显示) -->
|
||||
<el-row :gutter="20" class="mb-4" v-if="form.supplierType === '劳务'">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="安全生产许可证发证日期" prop="safeCertificateValidity">
|
||||
<el-date-picker v-model="form.safeCertificateValidity" type="date" placeholder="请选择发证日期" />
|
||||
<el-form-item label="安全生产许可证有效期" prop="safeCertificateValidity">
|
||||
<el-date-picker v-model="form.safeCertificateValidity" type="date" placeholder="请选择有效期" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@ -243,7 +246,7 @@
|
||||
<el-form-item label="注册造价工程师" prop="registeredEngineerNumber">
|
||||
<el-input v-model="form.registeredEngineerNumber" placeholder="请输入注册造价工程师数量" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="其他(分别写)" prop="otherBuildingNumber">
|
||||
<el-form-item label="其他人员数量" prop="otherBuildingNumber">
|
||||
<el-input v-model="form.otherBuildingNumber" placeholder="请输入其他人员数量" clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -309,7 +312,14 @@
|
||||
<script setup name="SupplierInput" lang="ts">
|
||||
import { ComponentInternalInstance, getCurrentInstance, onMounted, ref, reactive, toRefs, computed } from 'vue';
|
||||
import { ElFormInstance } from 'element-plus';
|
||||
import { listSupplierInput, getSupplierInput, delSupplierInput, updateSupplierInput } from '@/api/supplierInput/supplierInput/index';
|
||||
import {
|
||||
listSupplierInput,
|
||||
getSupplierInput,
|
||||
delSupplierInput,
|
||||
updateSupplierInput,
|
||||
leadingIn,
|
||||
leadingOut
|
||||
} from '@/api/supplierInput/supplierInput/index';
|
||||
import { SupplierInputVO, SupplierInputQuery, SupplierInputForm, PageData, DialogOption } from '@/api/supplierInput/supplierInput/types';
|
||||
import Pagination from '@/components/Pagination/index.vue';
|
||||
import RightToolbar from '@/components/RightToolbar/index.vue';
|
||||
@ -690,7 +700,75 @@ const handleDelete = async (row?: SupplierInputVO) => {
|
||||
|
||||
/** 导出操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download('supplierInput/supplierInput/export', { ...queryParams.value }, `supplierInput_${new Date().getTime()}.xlsx`);
|
||||
try {
|
||||
// 创建a标签并直接下载public目录下的静态文件
|
||||
const link = document.createElement('a');
|
||||
link.href = '/assets/files/供应商导入模板.xlsx'; // 使用public目录下现有的Excel文件作为模板
|
||||
link.download = '供应商导入模板.xlsx';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
// 清理DOM元素
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(link);
|
||||
}, 100);
|
||||
} catch (error) {
|
||||
proxy?.$modal.msgError('模板下载失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
/** 导入操作 */
|
||||
const handleImport = () => {
|
||||
// 创建一个隐藏的input[type=file]元素
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = '.xlsx,.xls'; // 限定只能导入excel文件
|
||||
input.style.display = 'none';
|
||||
|
||||
// 监听文件选择事件
|
||||
input.onchange = async (e: Event) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
const file = target.files?.[0];
|
||||
|
||||
if (file) {
|
||||
// 检查文件类型是否为Excel
|
||||
const isValidType = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
|
||||
if (!isValidType) {
|
||||
proxy?.$modal.msgError('请选择Excel文件(.xlsx或.xls)');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建FormData并添加文件
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
try {
|
||||
// 显示加载状态
|
||||
loading.value = true;
|
||||
// 调用导入接口
|
||||
const res = await leadingIn(formData, queryParams.value.projectId);
|
||||
console.log("111111111111",queryParams.value.projectId);
|
||||
|
||||
if (res.code === 200) {
|
||||
proxy?.$modal.msgSuccess('导入成功');
|
||||
// 刷新列表
|
||||
getList();
|
||||
} else {
|
||||
proxy?.$modal.msgError(res.msg || '导入失败');
|
||||
}
|
||||
} catch (error) {
|
||||
proxy?.$modal.msgError('导入失败,请重试');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 清除input元素
|
||||
input.remove();
|
||||
};
|
||||
|
||||
// 触发文件选择对话框
|
||||
document.body.appendChild(input);
|
||||
input.click();
|
||||
};
|
||||
//调用projectId并获取列表
|
||||
onMounted(() => {
|
||||
|
@ -13,7 +13,7 @@
|
||||
<el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
@ -38,8 +38,7 @@
|
||||
<el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
|
||||
<el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程名称"></el-table-column>
|
||||
<el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
|
||||
<el-table-column align="center" prop="version" label="版本号" width="90">
|
||||
<template #default="scope"> v{{ scope.row.version }}.0</template>
|
||||
|
@ -24,8 +24,13 @@
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px">
|
||||
<el-form-item label="流程定义编码" prop="flowCode">
|
||||
<el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="流程名称" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目" prop="projectId">
|
||||
<el-select v-model="queryParams.projectId" placeholder="全部" clearable filterable style="width: 150px; margin-right: 20px">
|
||||
<el-option v-for="project in projects" :key="project.id" :label="project.name" :value="project.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
@ -43,11 +48,10 @@
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
|
||||
<el-table-column v-if="false" align="center" prop="id" label="id"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"> </el-table-column>
|
||||
<el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程名称"> </el-table-column>
|
||||
<!-- <el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column> -->
|
||||
<el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
|
||||
<el-table-column align="center" prop="version" label="版本号" width="90">
|
||||
<template #default="scope"> v{{ scope.row.version }}.0</template>
|
||||
@ -68,20 +72,18 @@
|
||||
<template #default="scope">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="handleOpen(scope.row, 'update')">编辑</el-button>
|
||||
<el-button type="primary" link icon="Edit" @click="handleOpen(scope.row, 'update')">编辑</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'">
|
||||
<el-button type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
<el-button type="primary" link icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" size="small" icon="View" @click="handleOpen(scope.row, 'view')">查看</el-button>
|
||||
<el-button type="primary" link icon="View" @click="handleOpen(scope.row, 'view')">查看</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="scope.row.flowStatus === 'waiting'">
|
||||
<el-button type="primary" size="small" icon="Notification" @click="handleCancelProcessApply(scope.row.businessId)"
|
||||
>撤销</el-button
|
||||
>
|
||||
<el-button type="primary" link icon="Notification" @click="handleCancelProcessApply(scope.row.businessId)">撤销</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
@ -113,7 +115,12 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const categoryTreeRef = ref<ElTreeInstance>();
|
||||
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
const userStore = useUserStore();
|
||||
const projects = computed(() => [
|
||||
{ id: '0', name: '全部项目' }, // 添加空选项
|
||||
...userStore.projects
|
||||
]);
|
||||
// 遮罩层
|
||||
const loading = ref(true);
|
||||
// 选中数组
|
||||
@ -135,11 +142,13 @@ const categoryName = ref('');
|
||||
|
||||
const tab = ref('running');
|
||||
// 查询参数
|
||||
const queryParams = ref<FlowInstanceQuery>({
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
flowCode: undefined,
|
||||
category: undefined
|
||||
category: undefined,
|
||||
projectId: '0',
|
||||
flowName: undefined
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -7,11 +7,13 @@
|
||||
<el-form-item label="任务名称" prop="nodeName">
|
||||
<el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="流程名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义编码" label-width="100" prop="flowCode">
|
||||
<el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="项目" prop="projectId">
|
||||
<el-select v-model="queryParams.projectId" placeholder="全部" clearable filterable style="width: 150px; margin-right: 20px">
|
||||
<el-option v-for="project in projects" :key="project.id" :label="project.name" :value="project.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
@ -31,8 +33,7 @@
|
||||
<el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
|
||||
<el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程名称"></el-table-column>
|
||||
<el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
|
||||
<el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
|
||||
<el-table-column align="center" label="流程状态" min-width="70">
|
||||
@ -43,7 +44,7 @@
|
||||
<el-table-column align="center" prop="updateTime" label="更新时间" width="150"></el-table-column>
|
||||
<el-table-column label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
|
||||
<el-button type="primary" icon="View" @click="handleView(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -64,6 +65,12 @@ import { TaskQuery } from '@/api/workflow/task/types';
|
||||
import workflowCommon from '@/api/workflow/workflowCommon';
|
||||
import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
|
||||
//审批记录组件
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
const userStore = useUserStore();
|
||||
const projects = computed(() => [
|
||||
{ id: '0', name: '全部项目' }, // 添加空选项
|
||||
...userStore.projects
|
||||
]);
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||
@ -82,8 +89,9 @@ const total = ref(0);
|
||||
// 模型定义表格数据
|
||||
const taskList = ref([]);
|
||||
// 查询参数
|
||||
const queryParams = ref<TaskQuery>({
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
projectId: '0',
|
||||
pageSize: 10,
|
||||
nodeName: undefined,
|
||||
flowName: undefined,
|
||||
|
@ -4,19 +4,21 @@
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item>
|
||||
<!-- <el-form-item>
|
||||
<el-badge :value="userSelectCount" :max="10" class="item">
|
||||
<el-button type="primary" @click="openUserSelect">选择申请人</el-button>
|
||||
</el-badge>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="任务名称" prop="nodeName">
|
||||
<el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="流程名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义编码" label-width="100" prop="flowCode">
|
||||
<el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="项目" prop="projectId">
|
||||
<el-select v-model="queryParams.projectId" placeholder="全部" clearable filterable style="width: 150px; margin-right: 20px">
|
||||
<el-option v-for="project in projects" :key="project.id" :label="project.name" :value="project.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
@ -34,10 +36,8 @@
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
|
||||
<el-table-column align="center" prop="flowName" label="流程定义名称"></el-table-column>
|
||||
<el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
|
||||
<el-table-column align="center" prop="flowName" label="流程名称"></el-table-column>
|
||||
<el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
|
||||
<el-table-column align="center" prop="version" label="版本号" width="90">
|
||||
<template #default="scope"> v{{ scope.row.version }}.0</template>
|
||||
@ -64,7 +64,7 @@
|
||||
<el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
|
||||
<el-table-column label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
|
||||
<el-button type="primary" link icon="View" @click="handleView(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -94,7 +94,12 @@ const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
|
||||
import UserSelect from '@/components/UserSelect';
|
||||
import { ref } from 'vue';
|
||||
import { UserVO } from '@/api/system/user/types';
|
||||
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
const userStore = useUserStore();
|
||||
const projects = computed(() => [
|
||||
{ id: '0', name: '全部项目' }, // 添加空选项
|
||||
...userStore.projects
|
||||
]);
|
||||
const userSelectRef = ref<InstanceType<typeof UserSelect>>();
|
||||
// 遮罩层
|
||||
const loading = ref(true);
|
||||
@ -111,11 +116,12 @@ const total = ref(0);
|
||||
// 模型定义表格数据
|
||||
const taskList = ref([]);
|
||||
// 查询参数
|
||||
const queryParams = ref<TaskQuery>({
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
nodeName: undefined,
|
||||
flowName: undefined,
|
||||
projectId: '0',
|
||||
flowCode: undefined,
|
||||
createByIds: []
|
||||
});
|
||||
|
@ -12,11 +12,13 @@
|
||||
<el-form-item label="任务名称" prop="nodeName">
|
||||
<el-input v-model="queryParams.nodeName" placeholder="请输入任务名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程定义名称" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="流程名称" label-width="100" prop="flowName">
|
||||
<el-input v-model="queryParams.flowName" placeholder="请输入流程名称" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="流程定义编码" label-width="100" prop="flowCode">
|
||||
<el-input v-model="queryParams.flowCode" placeholder="请输入流程定义编码" @keyup.enter="handleQuery" />
|
||||
<el-form-item label="项目" prop="projectId">
|
||||
<el-select v-model="queryParams.projectId" placeholder="全部" clearable filterable style="width: 150px; margin-right: 20px">
|
||||
<el-option v-for="project in projects" :key="project.id" :label="project.name" :value="project.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
@ -33,10 +35,8 @@
|
||||
</el-row>
|
||||
</template>
|
||||
<el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column align="center" type="index" label="序号" width="60"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程定义名称"></el-table-column>
|
||||
<el-table-column align="center" prop="flowCode" label="流程定义编码"></el-table-column>
|
||||
<el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="流程名称"></el-table-column>
|
||||
<el-table-column align="center" prop="categoryName" label="流程分类"></el-table-column>
|
||||
<el-table-column align="center" prop="nodeName" label="任务名称"></el-table-column>
|
||||
<el-table-column align="center" prop="createByName" label="申请人"></el-table-column>
|
||||
@ -60,7 +60,7 @@
|
||||
<el-table-column align="center" prop="createTime" label="创建时间" width="160"></el-table-column>
|
||||
<el-table-column label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" size="small" icon="Edit" @click="handleOpen(scope.row)">办理</el-button>
|
||||
<el-button type="primary" link icon="Edit" @click="handleOpen(scope.row)">办理</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -88,7 +88,12 @@ const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'))
|
||||
import UserSelect from '@/components/UserSelect';
|
||||
import { ref } from 'vue';
|
||||
import { UserVO } from '@/api/system/user/types';
|
||||
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
const userStore = useUserStore();
|
||||
const projects = computed(() => [
|
||||
{ id: '0', name: '全部项目' }, // 添加空选项
|
||||
...userStore.projects
|
||||
]);
|
||||
const userSelectRef = ref<InstanceType<typeof UserSelect>>();
|
||||
//提交组件
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
@ -112,13 +117,14 @@ const selectUserIds = ref<Array<number | string>>([]);
|
||||
//申请人选择数量
|
||||
const userSelectCount = ref(0);
|
||||
// 查询参数
|
||||
const queryParams = ref<TaskQuery>({
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
nodeName: undefined,
|
||||
flowName: undefined,
|
||||
flowCode: undefined,
|
||||
createByIds: []
|
||||
createByIds: [],
|
||||
projectId: '0'
|
||||
});
|
||||
onMounted(() => {
|
||||
getWaitingList();
|
||||
|
Reference in New Issue
Block a user