工程统计页面完善

This commit is contained in:
BianLzhaoMin 2025-09-17 15:09:05 +08:00
parent c56ebff990
commit b6dd7cd59f
10 changed files with 1025 additions and 233 deletions

View File

@ -6,4 +6,4 @@ ENV = 'production'
VUE_APP_ENV = 'production'
# 实名制管理系统/生产环境
VUE_APP_BASE_API = '/hd-realname/prod-api'
VUE_APP_BASE_API = '/hd-real-name'

View File

@ -1068,12 +1068,25 @@ export default {
this.$refs.salaryCardInfoFormRef.validate(
async (valid4) => {
if (valid4) {
const fieldsToCheck_1 = [
let fieldsToCheck_1 = [
'contractCode', //
'wageCriterion', //
'contractStopDate', //
'contractStartDate', //
]
if (
this.contractInfoForm
.contractTermType ===
'以完成一定工作为期限的合同'
) {
fieldsToCheck_1 =
fieldsToCheck_1.filter(
(item) =>
item !==
'contractStopDate',
)
}
const fieldsToCheck_2 = [
'bankName', //
'bankCardCode', //

View File

@ -273,12 +273,21 @@ export default {
//
checkFormStatus() {
//
const fieldsList = [
let fieldsList = [
'contractCode', //
'wageCriterion', //
'contractStopDate', //
'contractStartDate', //
]
if (
this.contractInfoForm.contractTermType ===
'以完成一定工作为期限的合同'
) {
fieldsList = fieldsList.filter(
(item) => item !== 'contractStopDate',
)
}
const imageFieldsToCheck = this.contractImageList.slice(0, -1) //
//

View File

@ -0,0 +1,177 @@
<template>
<!-- 公司统计 -->
<div style="padding: 0 20px">
<div class="section-container">
<div class="section-header">
<div class="section-title">
<div class="title-indicator"></div>
<span>公司统计</span>
</div>
</div>
<div class="table-container">
<el-table
:data="companyCountData"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle"
stripe
border
>
<el-table-column
:key="item.prop"
:prop="item.prop"
align="center"
:label="item.label"
show-overflow-tooltip
v-for="item in columnData"
/>
</el-table>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'CompanyCount',
props: {},
data() {
return {
companyCountData: [
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
],
columnData: [
{
label: '公司名称',
prop: 'entryTime',
},
{
label: '工程数量',
prop: 'exitTime',
},
{
label: '分包数量',
prop: 'contractName',
},
{
label: '实发工资(元)',
prop: 'subcontractorName',
},
{
label: '累计支付工资(元)',
prop: 'totalEntryCount',
},
],
}
},
created() {},
watch: {},
methods: {
//
tableHeaderStyle() {
return {
backgroundColor: '#f5f7fa',
color: '#606266',
fontWeight: '500',
fontSize: '14px',
textAlign: 'center',
}
},
//
tableCellStyle() {
return {
fontSize: '14px',
color: '#606266',
padding: '12px 8px',
}
},
},
}
</script>
<style lang="scss" scoped>
@import '@/assets/styles/variables.scss';
.section-container {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-top: 20px;
overflow: hidden;
.section-header {
padding: 20px 24px 16px;
border-bottom: 1px solid #f0f0f0;
.section-title {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 600;
color: #1f2937;
.title-indicator {
width: 4px;
height: 20px;
background: #3b82f6;
border-radius: 2px;
margin-right: 12px;
}
}
}
.table-container {
padding: 0;
::v-deep .el-table {
border: none;
.el-table__header-wrapper {
.el-table__header {
th {
border-bottom: 1px solid #e4e7ed;
border-right: 1px solid #e4e7ed;
&:last-child {
border-right: none;
}
}
}
}
.el-table__body-wrapper {
.el-table__body {
tr {
&:hover {
background-color: #f8f9fa;
}
td {
border-bottom: 1px solid #f0f0f0;
border-right: 1px solid #f0f0f0;
&:last-child {
border-right: none;
}
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,64 @@
<template>
<!-- 数据筛选 -->
<div class="data-filter">
<div class="data-filter-title">数据筛选</div>
<div style="margin-top: 14px">
<el-radio-group v-model="radio2" size="medium">
<el-radio-button label="2025"></el-radio-button>
<el-radio-button label="2024"></el-radio-button>
<el-radio-button label="2023"></el-radio-button>
</el-radio-group>
</div>
<div style="margin-top: 14px">
<el-radio-group v-model="radio3" size="medium">
<el-radio-button label="全部"></el-radio-button>
<el-radio-button label="一季度"></el-radio-button>
<el-radio-button label="二季度"></el-radio-button>
<el-radio-button label="三季度"></el-radio-button>
<el-radio-button label="四季度"></el-radio-button>
</el-radio-group>
</div>
<div style="margin-top: 14px">
<el-radio-group v-model="radio4" size="medium">
<el-radio-button label="全部"></el-radio-button>
<el-radio-button label="1月"></el-radio-button>
<el-radio-button label="2月"></el-radio-button>
<el-radio-button label="3月"></el-radio-button>
<el-radio-button label="4月"></el-radio-button>
<el-radio-button label="5月"></el-radio-button>
<el-radio-button label="6月"></el-radio-button>
<el-radio-button label="7月"></el-radio-button>
<el-radio-button label="8月"></el-radio-button>
<el-radio-button label="9月"></el-radio-button>
<el-radio-button label="10月"></el-radio-button>
<el-radio-button label="11月"></el-radio-button>
<el-radio-button label="12月"></el-radio-button>
</el-radio-group>
</div>
</div>
</template>
<script>
export default {
name: 'DataFilter',
data() {
return {
radio2: '2025',
radio3: '全部',
radio4: '全部',
}
},
}
</script>
<style scoped lang="scss">
.data-filter-title {
font-size: 18px;
font-weight: 600;
color: #000;
font-family: 'PingFang SC';
}
.data-filter {
margin-bottom: 20px;
}
</style>

View File

@ -0,0 +1,257 @@
<template>
<!-- 工程统计 -->
<div style="padding: 0 20px">
<div class="section-container">
<div class="section-header">
<div class="section-title">
<div class="title-indicator"></div>
<span>工程统计</span>
</div>
</div>
<div class="table-container">
<el-form
:inline="true"
label-width="auto"
:model="projectCountQueryParams"
style="margin-top: 20px; padding-left: 20px"
>
<el-form-item label="考勤日期">
<el-input
v-model="projectCountQueryParams.entryTime"
placeholder="请输入工程名称"
/>
</el-form-item>
<el-form-item>
<el-button
size="mini"
type="primary"
icon="el-icon-search"
@click="handleQuery"
>
查询
</el-button>
<el-button
plain
size="mini"
type="warning"
icon="el-icon-refresh"
@click="resetQuery"
>
重置
</el-button>
<el-button
plain
size="mini"
type="success"
icon="el-icon-download"
@click="handleExport"
>
导出
</el-button>
</el-form-item>
</el-form>
<el-table
border
stripe
:data="projectCountData"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle"
>
<el-table-column
align="center"
:key="item.prop"
:prop="item.prop"
:label="item.label"
show-overflow-tooltip
v-for="item in columnData"
/>
</el-table>
<div style="padding-right: 20px">
<pagination
:total="total"
@pagination="getAttInfoData"
:page.sync="projectCountQueryParams.pageNum"
:limit.sync="projectCountQueryParams.pageSize"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ProjectCount',
props: {},
data() {
return {
total: 100,
projectCountQueryParams: {
entryTime: '',
},
projectCountData: [
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
],
columnData: [
{
label: '工程名称',
prop: 'entryTime',
},
{
label: '所属分公司',
prop: 'exitTime',
},
{
label: '分包数量',
prop: 'contractName',
},
{
label: '实发工资(元)',
prop: 'subcontractorName',
},
{
label: '累计支付工资(元)',
prop: 'totalEntryCount',
},
],
}
},
created() {},
watch: {},
methods: {
//
tableHeaderStyle() {
return {
backgroundColor: '#f5f7fa',
color: '#606266',
fontWeight: '500',
fontSize: '14px',
textAlign: 'center',
}
},
//
tableCellStyle() {
return {
fontSize: '14px',
color: '#606266',
padding: '12px 8px',
}
},
//
handleQuery() {
// this.getAttInfoData()
},
//
resetQuery() {
this.attInfoQueryParams = {
entryTime: '',
}
},
//
handleExport() {
// this.download(
// '/bmw/workerLight/attExportByWorker',
// {
// ...this.attInfoQueryParams,
// },
// '.xlsx',
// )
},
//
getAttInfoData() {
// this.getAttInfoData()
},
},
}
</script>
<style lang="scss" scoped>
@import '@/assets/styles/variables.scss';
.section-container {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-top: 20px;
overflow: hidden;
padding: 20px 0;
.section-header {
padding: 20px 24px 16px;
border-bottom: 1px solid #f0f0f0;
.section-title {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 600;
color: #1f2937;
.title-indicator {
width: 4px;
height: 20px;
background: #3b82f6;
border-radius: 2px;
margin-right: 12px;
}
}
}
.table-container {
padding: 0;
::v-deep .el-table {
border: none;
.el-table__header-wrapper {
.el-table__header {
th {
border-bottom: 1px solid #e4e7ed;
border-right: 1px solid #e4e7ed;
&:last-child {
border-right: none;
}
}
}
}
.el-table__body-wrapper {
.el-table__body {
tr {
&:hover {
background-color: #f8f9fa;
}
td {
border-bottom: 1px solid #f0f0f0;
border-right: 1px solid #f0f0f0;
&:last-child {
border-right: none;
}
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,177 @@
<template>
<!-- 分公司统计 -->
<div style="padding: 0 20px">
<div class="section-container">
<div class="section-header">
<div class="section-title">
<div class="title-indicator"></div>
<span>分公司统计</span>
</div>
</div>
<div class="table-container">
<el-table
:data="subCompanyCountData"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle"
stripe
border
>
<el-table-column
:key="item.prop"
:prop="item.prop"
align="center"
:label="item.label"
show-overflow-tooltip
v-for="item in columnData"
/>
</el-table>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SubCompanyCount',
props: {},
data() {
return {
subCompanyCountData: [
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
],
columnData: [
{
label: '公司名称',
prop: 'entryTime',
},
{
label: '工程数量',
prop: 'exitTime',
},
{
label: '分包数量',
prop: 'contractName',
},
{
label: '实发工资(元)',
prop: 'subcontractorName',
},
{
label: '累计支付工资(元)',
prop: 'totalEntryCount',
},
],
}
},
created() {},
watch: {},
methods: {
//
tableHeaderStyle() {
return {
backgroundColor: '#f5f7fa',
color: '#606266',
fontWeight: '500',
fontSize: '14px',
textAlign: 'center',
}
},
//
tableCellStyle() {
return {
fontSize: '14px',
color: '#606266',
padding: '12px 8px',
}
},
},
}
</script>
<style lang="scss" scoped>
@import '@/assets/styles/variables.scss';
.section-container {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-top: 20px;
overflow: hidden;
.section-header {
padding: 20px 24px 16px;
border-bottom: 1px solid #f0f0f0;
.section-title {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 600;
color: #1f2937;
.title-indicator {
width: 4px;
height: 20px;
background: #3b82f6;
border-radius: 2px;
margin-right: 12px;
}
}
}
.table-container {
padding: 0;
::v-deep .el-table {
border: none;
.el-table__header-wrapper {
.el-table__header {
th {
border-bottom: 1px solid #e4e7ed;
border-right: 1px solid #e4e7ed;
&:last-child {
border-right: none;
}
}
}
}
.el-table__body-wrapper {
.el-table__body {
tr {
&:hover {
background-color: #f8f9fa;
}
td {
border-bottom: 1px solid #f0f0f0;
border-right: 1px solid #f0f0f0;
&:last-child {
border-right: none;
}
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,255 @@
<template>
<!-- 分包统计 -->
<div style="padding: 0 20px">
<div class="section-container">
<div class="section-header">
<div class="section-title">
<div class="title-indicator"></div>
<span>分包统计</span>
</div>
</div>
<div class="table-container">
<el-form
:inline="true"
label-width="auto"
:model="subCountQueryParams"
style="margin-top: 20px; padding-left: 20px"
>
<el-form-item label="考勤日期">
<el-input
v-model="subCountQueryParams.entryTime"
placeholder="请输入工程名称"
/>
</el-form-item>
<el-form-item>
<el-button
size="mini"
type="primary"
icon="el-icon-search"
@click="handleQuery"
>
查询
</el-button>
<el-button
plain
size="mini"
type="warning"
icon="el-icon-refresh"
@click="resetQuery"
>
重置
</el-button>
<el-button
plain
size="mini"
type="success"
icon="el-icon-download"
@click="handleExport"
>
导出
</el-button>
</el-form-item>
</el-form>
<el-table
border
stripe
:data="subCountData"
style="width: 100%"
:header-cell-style="tableHeaderStyle"
:cell-style="tableCellStyle"
>
<el-table-column
align="center"
:key="item.prop"
:prop="item.prop"
:label="item.label"
show-overflow-tooltip
v-for="item in columnData"
/>
</el-table>
<div style="padding-right: 20px">
<pagination
:total="total"
@pagination="getSubCountData"
:page.sync="subCountQueryParams.pageNum"
:limit.sync="subCountQueryParams.pageSize"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SubCount',
props: {},
data() {
return {
total: 100,
subCountQueryParams: {
entryTime: '',
pageNum: 1,
pageSize: 10,
},
subCountData: [
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
{
entryTime: '2025-01-01',
exitTime: '2025-01-01',
contractName: '工程1',
subcontractorName: '分包1',
totalEntryCount: 10,
},
],
columnData: [
{
label: '分包名称',
prop: 'entryTime',
},
{
label: '工程数量',
prop: 'exitTime',
},
{
label: '实发工资(元)',
prop: 'subcontractorName',
},
{
label: '累计支付工资(元)',
prop: 'totalEntryCount',
},
],
}
},
created() {},
watch: {},
methods: {
//
tableHeaderStyle() {
return {
backgroundColor: '#f5f7fa',
color: '#606266',
fontWeight: '500',
fontSize: '14px',
textAlign: 'center',
}
},
//
tableCellStyle() {
return {
fontSize: '14px',
color: '#606266',
padding: '12px 8px',
}
},
//
handleQuery() {
// this.getAttInfoData()
},
//
resetQuery() {
this.attInfoQueryParams = {
entryTime: '',
}
},
//
handleExport() {
// this.download(
// '/bmw/workerLight/attExportByWorker',
// {
// ...this.attInfoQueryParams,
// },
// '.xlsx',
// )
},
//
getSubCountData() {
// this.getAttInfoData()
},
},
}
</script>
<style lang="scss" scoped>
@import '@/assets/styles/variables.scss';
.section-container {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-top: 20px;
overflow: hidden;
padding: 20px 0;
.section-header {
padding: 20px 24px 16px;
border-bottom: 1px solid #f0f0f0;
.section-title {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 600;
color: #1f2937;
.title-indicator {
width: 4px;
height: 20px;
background: #3b82f6;
border-radius: 2px;
margin-right: 12px;
}
}
}
.table-container {
padding: 0;
::v-deep .el-table {
border: none;
.el-table__header-wrapper {
.el-table__header {
th {
border-bottom: 1px solid #e4e7ed;
border-right: 1px solid #e4e7ed;
&:last-child {
border-right: none;
}
}
}
}
.el-table__body-wrapper {
.el-table__body {
tr {
&:hover {
background-color: #f8f9fa;
}
td {
border-bottom: 1px solid #f0f0f0;
border-right: 1px solid #f0f0f0;
&:last-child {
border-right: none;
}
}
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,60 @@
<template>
<!-- 工资统计 -->
<div class="wage-details-container">
<div class="section-header">
<span>工资统计</span>
<span>(已归档工资)</span>
</div>
<CompanyCount />
<SubCompanyCount />
<ProjectCount />
<SubCount />
</div>
</template>
<script>
import CompanyCount from './companyCount.vue'
import SubCompanyCount from './subCompanyCount.vue'
import ProjectCount from './projectCount.vue'
import SubCount from './subCount.vue'
export default {
name: 'PersonInfoCard',
components: {
CompanyCount,
SubCompanyCount,
ProjectCount,
SubCount,
},
data() {
return {}
},
created() {},
watch: {},
methods: {},
}
</script>
<style lang="scss" scoped>
@import '@/assets/styles/variables.scss';
.wage-details-container {
padding-bottom: 20px;
border-radius: 12px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
background-color: #fff;
border: 1px solid #f0f0f0;
.section-header {
padding: 16px 10px;
font-size: 18px;
font-weight: 600;
color: #000;
font-family: 'PingFang SC';
background-color: #f5f7fa;
border-bottom: 1px solid #f0f0f0;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
}
}
</style>

View File

@ -1,239 +1,19 @@
<template>
<div class="not-dev-container app-container">
<div class="not-dev-content">
<div class="not-dev-image">
<svg
width="400"
height="400"
viewBox="0 0 400 400"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<!-- 背景圆形 -->
<circle
cx="200"
cy="200"
r="180"
fill="#F8FAFC"
stroke="#E2E8F0"
stroke-width="2"
/>
<!-- 主要图标建筑工地或开发中的图标 -->
<rect
x="120"
y="140"
width="160"
height="120"
rx="8"
fill="#3B82F6"
opacity="0.1"
/>
<rect
x="130"
y="150"
width="140"
height="100"
rx="4"
fill="#3B82F6"
opacity="0.2"
/>
<!-- 脚手架结构 -->
<rect
x="110"
y="120"
width="8"
height="160"
fill="#94A3B8"
/>
<rect
x="282"
y="120"
width="8"
height="160"
fill="#94A3B8"
/>
<rect
x="110"
y="120"
width="180"
height="8"
fill="#94A3B8"
/>
<rect
x="110"
y="200"
width="180"
height="8"
fill="#94A3B8"
/>
<rect
x="110"
y="280"
width="180"
height="8"
fill="#94A3B8"
/>
<!-- 工具图标 -->
<circle cx="160" cy="180" r="15" fill="#F59E0B" />
<circle cx="240" cy="180" r="15" fill="#10B981" />
<circle cx="200" cy="220" r="15" fill="#EF4444" />
<!-- 进度条 -->
<rect
x="120"
y="320"
width="160"
height="8"
rx="4"
fill="#E2E8F0"
/>
<rect
x="120"
y="320"
width="80"
height="8"
rx="4"
fill="#3B82F6"
/>
<!-- 装饰性元素 -->
<circle
cx="150"
cy="80"
r="4"
fill="#3B82F6"
opacity="0.6"
/>
<circle
cx="250"
cy="90"
r="3"
fill="#10B981"
opacity="0.6"
/>
<circle
cx="180"
cy="70"
r="2"
fill="#F59E0B"
opacity="0.6"
/>
</svg>
</div>
<div class="not-dev-text">
<h2 class="title">即将上线</h2>
<p class="subtitle">敬请期待...</p>
</div>
</div>
<!-- 工资统计 -->
<div class="app-container">
<DataFilter />
<WageDetails />
</div>
</template>
<script>
import DataFilter from './components/dataFilter.vue'
import WageDetails from './components/wage-details.vue'
export default {
name: 'NotDev',
data() {
return {}
name: 'WageCount',
components: {
DataFilter,
WageDetails,
},
}
</script>
<style lang="scss" scoped>
.not-dev-container {
display: flex;
align-items: center;
justify-content: center;
// min-height: 100vh;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
.not-dev-content {
text-align: center;
padding: 40px;
border-radius: 16px;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
.not-dev-image {
margin-bottom: 32px;
svg {
filter: drop-shadow(0 8px 16px rgba(59, 130, 246, 0.15));
transition: transform 0.3s ease;
&:hover {
transform: translateY(-8px);
}
}
}
.not-dev-text {
.title {
font-size: 32px;
font-weight: 600;
color: #1e3a8a;
margin: 0 0 16px 0;
letter-spacing: 2px;
}
.subtitle {
font-size: 18px;
color: #64748b;
margin: 0;
font-weight: 400;
letter-spacing: 1px;
}
}
}
}
//
@media (max-width: 768px) {
.not-dev-container {
padding: 20px;
.not-dev-content {
padding: 30px 20px;
.not-dev-image svg {
width: 300px;
height: 300px;
}
.not-dev-text {
.title {
font-size: 28px;
}
.subtitle {
font-size: 16px;
}
}
}
}
}
@media (max-width: 480px) {
.not-dev-container {
.not-dev-content {
.not-dev-image svg {
width: 250px;
height: 250px;
}
.not-dev-text {
.title {
font-size: 24px;
}
.subtitle {
font-size: 14px;
}
}
}
}
}
</style>