yuanxingsheji/项目管理/市场商务管理/市场商务管理.html

2069 lines
80 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>项目管理 - 市场商务管理</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
color: #333;
background-color: #f0f2f5;
}
.app-container {
display: flex;
min-height: 100vh;
overflow: hidden;
}
/* 侧边栏样式 */
.sidebar {
width: 220px;
background-color: #304156;
color: #fff;
transition: width 0.3s;
flex-shrink: 0;
overflow-y: auto;
}
.sidebar.collapsed {
width: 64px;
}
.main-content {
flex: 1;
padding: 20px;
overflow-y: auto;
transition: margin-left 0.3s;
}
.sidebar.collapsed + .main-content {
margin-left: -156px;
}
.logo {
padding: 10px 0;
text-align: center;
position: relative;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.logo h2 {
font-size: 18px;
margin: 5px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 10px;
}
.toggle-sidebar {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
color: #fff;
}
/* 菜单项样式 */
.el-menu {
border-right: none;
background-color: transparent;
}
.el-menu-item, .el-submenu__title {
color: #fff;
height: 46px;
line-height: 46px;
}
.el-menu-item:hover, .el-submenu__title:hover {
background-color: rgba(0, 0, 0, 0.1) !important;
}
.el-menu-item.is-active {
background-color: rgba(0, 0, 0, 0.2) !important;
color: #409EFF !important;
}
.el-submenu .el-menu-item {
min-width: 0 !important;
padding-left: 50px !important;
background-color: #1f2d3d !important;
}
.el-submenu .el-menu-item:hover {
background-color: rgba(0, 0, 0, 0.1) !important;
}
.el-submenu__title {
padding-left: 20px !important;
}
.el-menu-item [class^=el-icon-], .el-submenu [class^=el-icon-] {
margin-right: 10px;
}
/* 主内容区样式 */
.module-title {
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #ebeef5;
}
.card-container {
background: #fff;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
margin-bottom: 20px;
}
/* 表格操作按钮 */
.table-actions {
margin-bottom: 15px;
display: flex;
justify-content: space-between;
}
/* 分页样式 */
.pagination-container {
margin-top: 20px;
text-align: right;
}
/* 表单样式 */
.form-container {
max-width: 800px;
margin: 0 auto;
}
/* 响应式调整 */
@media (max-width: 768px) {
.sidebar {
position: fixed;
z-index: 1000;
height: 100vh;
}
.sidebar.collapsed + .main-content {
margin-left: 0;
}
.main-content {
margin-left: 220px;
}
.sidebar.collapsed {
width: 0;
overflow: hidden;
}
}
</style>
</head>
<body>
<div id="app" class="app-container">
<!-- 侧边栏导航 -->
<div class="sidebar" :class="{collapsed: isCollapse}">
<div class="logo">
<h2>项目管理</h2>
<div class="toggle-sidebar" @click="toggleSidebar">
<i :class="isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"></i>
</div>
</div>
<el-menu
:default-active="activeModule"
class="el-menu-vertical"
:collapse="isCollapse"
:collapse-transition="false"
background-color="#304156"
text-color="#fff"
active-text-color="#409EFF"
>
<!-- 市场商务管理 -->
<el-submenu index="market">
<template slot="title">
<i class="el-icon-shopping-bag-1"></i>
<span>市场商务管理</span>
</template>
<!-- 项目来源 -->
<el-submenu index="project-source">
<template slot="title">项目来源</template>
<!-- 招采业务 -->
<el-submenu index="bidding">
<template slot="title">招采业务</template>
<el-menu-item index="bidding-search" @click="switchModule('bidding-search')">信息检索</el-menu-item>
<el-menu-item index="bidding-response" @click="switchModule('bidding-response')">投标响应</el-menu-item>
</el-submenu>
<!-- 市场营销 -->
<el-submenu index="marketing">
<template slot="title">市场营销</template>
<el-menu-item index="marketing-promotion" @click="switchModule('marketing-promotion')">营销推广</el-menu-item>
<el-menu-item index="framework-agreement" @click="switchModule('framework-agreement')">框架协议</el-menu-item>
<el-menu-item index="industry-business" @click="switchModule('industry-business')">同行业务</el-menu-item>
</el-submenu>
<!-- 自建项目 -->
<el-submenu index="self-project">
<template slot="title">自建项目</template>
<el-menu-item index="software-dev" @click="switchModule('software-dev')">软件开发</el-menu-item>
<el-menu-item index="hardware-dev" @click="switchModule('hardware-dev')">硬件开发</el-menu-item>
<el-menu-item index="ai-model" @click="switchModule('ai-model')">AI模型/算法工具</el-menu-item>
</el-submenu>
</el-submenu>
<!-- 项目合同管理 -->
<el-submenu index="contract">
<template slot="title">项目合同管理</template>
<el-menu-item index="income-contract" @click="switchModule('income-contract')">收入合同</el-menu-item>
<el-menu-item index="expense-contract" @click="switchModule('expense-contract')">支出合同</el-menu-item>
<el-menu-item index="cost-management" @click="switchModule('cost-management')">成本费用</el-menu-item>
</el-submenu>
</el-submenu>
<!-- 施工立项 -->
<el-menu-item index="construction" @click="switchModule('construction')">
<i class="el-icon-document-add"></i>
<span slot="title">施工立项</span>
</el-menu-item>
<!-- 组织实施管理 -->
<el-menu-item index="implementation" @click="switchModule('implementation')">
<i class="el-icon-s-management"></i>
<span slot="title">组织实施管理</span>
</el-menu-item>
</el-menu>
</div>
<!-- 主内容区 -->
<div class="main-content">
<!-- 招采业务 - 信息检索 -->
<div v-if="activeModule === 'bidding-search'">
<h2 class="module-title">招采业务 - 信息检索</h2>
<div class="card-container">
<div class="table-actions">
<el-input
placeholder="搜索招标项目"
v-model="biddingSearch.keyword"
clearable
style="width: 300px;"
@keyup.enter.native="searchBiddingInfo"
>
<el-button slot="append" icon="el-icon-search" @click="searchBiddingInfo"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-refresh" @click="refreshBiddingData">刷新数据</el-button>
<el-button type="success" icon="el-icon-download" @click="exportBiddingData">导出数据</el-button>
<el-button type="warning" icon="el-icon-setting" @click="showCrawlerSettings">爬虫设置</el-button>
</div>
</div>
<el-table :data="biddingData" border style="width: 100%">
<el-table-column prop="title" label="招标项目" width="300"></el-table-column>
<el-table-column prop="publisher" label="招标单位" width="180"></el-table-column>
<el-table-column prop="budget" label="预算金额" width="120" align="right"></el-table-column>
<el-table-column prop="deadline" label="截止时间" width="180"></el-table-column>
<el-table-column prop="source" label="来源平台" width="120"></el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '进行中' ? 'success' : 'info'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewBiddingDetail(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="markAsInterested(scope.row)">关注</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleBiddingSizeChange"
@current-change="handleBiddingCurrentChange"
:current-page="biddingSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="biddingSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="biddingTotal">
</el-pagination>
</div>
</div>
<!-- 招标详情对话框 -->
<el-dialog title="招标详情" :visible.sync="biddingDetailVisible" width="70%">
<div v-if="currentBidding">
<el-descriptions :column="2" border>
<el-descriptions-item label="项目名称">{{ currentBidding.title }}</el-descriptions-item>
<el-descriptions-item label="招标单位">{{ currentBidding.publisher }}</el-descriptions-item>
<el-descriptions-item label="预算金额">{{ currentBidding.budget }}</el-descriptions-item>
<el-descriptions-item label="截止时间">{{ currentBidding.deadline }}</el-descriptions-item>
<el-descriptions-item label="项目地点">{{ currentBidding.location }}</el-descriptions-item>
<el-descriptions-item label="项目周期">{{ currentBidding.duration }}</el-descriptions-item>
<el-descriptions-item label="招标范围" :span="2">{{ currentBidding.scope }}</el-descriptions-item>
<el-descriptions-item label="资质要求" :span="2">{{ currentBidding.qualification }}</el-descriptions-item>
<el-descriptions-item label="招标文件" :span="2">
<el-link type="primary" :href="currentBidding.docUrl" target="_blank">下载招标文件</el-link>
</el-descriptions-item>
</el-descriptions>
<div style="margin-top: 20px;">
<h3>招标内容</h3>
<div v-html="currentBidding.content" style="border: 1px solid #ebeef5; padding: 10px; border-radius: 4px;"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="biddingDetailVisible = false">关闭</el-button>
<el-button type="primary" @click="goToBiddingResponse">投标响应</el-button>
</span>
</el-dialog>
<!-- 爬虫设置对话框 -->
<el-dialog title="爬虫设置" :visible.sync="crawlerSettingsVisible" width="50%">
<el-form :model="crawlerSettings" label-width="120px">
<el-form-item label="爬取频率">
<el-select v-model="crawlerSettings.frequency" style="width: 200px;">
<el-option label="每小时" value="hourly"></el-option>
<el-option label="每天" value="daily"></el-option>
<el-option label="每周" value="weekly"></el-option>
</el-select>
</el-form-item>
<el-form-item label="关键词过滤">
<el-tag
v-for="tag in crawlerSettings.keywords"
:key="tag"
closable
@close="removeKeyword(tag)"
style="margin-right: 10px;"
>
{{ tag }}
</el-tag>
<el-input
v-model="newKeyword"
size="small"
style="width: 150px;"
@keyup.enter.native="addKeyword"
>
<el-button slot="append" icon="el-icon-plus" @click="addKeyword"></el-button>
</el-input>
</el-form-item>
<el-form-item label="来源平台">
<el-checkbox-group v-model="crawlerSettings.platforms">
<el-checkbox label="中国招标投标公共服务平台"></el-checkbox>
<el-checkbox label="各省市公共资源交易中心"></el-checkbox>
<el-checkbox label="企业自有招标平台"></el-checkbox>
<el-checkbox label="其他第三方平台"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="自动通知">
<el-switch v-model="crawlerSettings.autoNotify"></el-switch>
<span style="margin-left: 10px;">{{ crawlerSettings.autoNotify ? '已开启' : '已关闭' }}</span>
</el-form-item>
<el-form-item label="通知方式" v-if="crawlerSettings.autoNotify">
<el-checkbox-group v-model="crawlerSettings.notifyMethods">
<el-checkbox label="站内消息"></el-checkbox>
<el-checkbox label="电子邮件"></el-checkbox>
<el-checkbox label="手机短信"></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="crawlerSettingsVisible = false">取消</el-button>
<el-button type="primary" @click="saveCrawlerSettings">保存设置</el-button>
</span>
</el-dialog>
</div>
<!-- 招采业务 - 投标响应 -->
<div v-if="activeModule === 'bidding-response'">
<h2 class="module-title">招采业务 - 投标响应</h2>
<div class="card-container">
<el-tabs v-model="biddingResponseTab">
<el-tab-pane label="投标项目" name="projects">
<div class="table-actions">
<el-input
placeholder="搜索投标项目"
v-model="biddingResponseSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewBiddingDialog">新建投标</el-button>
<el-button icon="el-icon-refresh" @click="refreshBiddingResponse">刷新</el-button>
</div>
</div>
<el-table :data="biddingResponseData" border style="width: 100%">
<el-table-column prop="projectName" label="项目名称" width="250"></el-table-column>
<el-table-column prop="publisher" label="招标单位" width="150"></el-table-column>
<el-table-column prop="budget" label="预算金额" width="120" align="right"></el-table-column>
<el-table-column prop="deadline" label="截止时间" width="150"></el-table-column>
<el-table-column prop="status" label="投标状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '已中标' ? 'success' :
scope.row.status === '已投标' ? 'primary' :
scope.row.status === '准备中' ? 'warning' : 'info'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="progress" label="进度" width="150">
<template slot-scope="scope">
<el-progress :percentage="scope.row.progress" :status="scope.row.status === '已中标' ? 'success' : ''"></el-progress>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button size="mini" @click="viewBiddingResponse(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editBiddingResponse(scope.row)"
:disabled="scope.row.status === '已中标' || scope.row.status === '已投标'">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleBiddingResponseSizeChange"
@current-change="handleBiddingResponseCurrentChange"
:current-page="biddingResponseSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="biddingResponseSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="biddingResponseTotal">
</el-pagination>
</div>
</el-tab-pane>
<el-tab-pane label="商务标书" name="documents">
<div class="table-actions">
<el-input
placeholder="搜索标书"
v-model="documentSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewDocumentDialog">新建标书</el-button>
<el-button icon="el-icon-refresh" @click="refreshDocuments">刷新</el-button>
</div>
</div>
<el-table :data="documentData" border style="width: 100%">
<el-table-column prop="name" label="标书名称" width="250"></el-table-column>
<el-table-column prop="project" label="关联项目" width="200"></el-table-column>
<el-table-column prop="type" label="标书类型" width="120">
<template slot-scope="scope">
<el-tag>{{ scope.row.type }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="version" label="版本" width="100"></el-table-column>
<el-table-column prop="updateTime" label="更新时间" width="180"></el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '已完成' ? 'success' : 'warning'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button size="mini" @click="viewDocument(scope.row)">查看</el-button>
<el-button size="mini" type="primary" @click="editDocument(scope.row)">编辑</el-button>
<el-button size="mini" type="success" @click="generateDocument(scope.row)">生成</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleDocumentSizeChange"
@current-change="handleDocumentCurrentChange"
:current-page="documentSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="documentSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="documentTotal">
</el-pagination>
</div>
</el-tab-pane>
<el-tab-pane label="报价文件" name="quotations">
<div class="table-actions">
<el-input
placeholder="搜索报价文件"
v-model="quotationSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewQuotationDialog">新建报价</el-button>
<el-button icon="el-icon-refresh" @click="refreshQuotations">刷新</el-button>
</div>
</div>
<el-table :data="quotationData" border style="width: 100%">
<el-table-column prop="name" label="报价文件" width="250"></el-table-column>
<el-table-column prop="project" label="关联项目" width="200"></el-table-column>
<el-table-column prop="totalPrice" label="总报价" width="120" align="right"></el-table-column>
<el-table-column prop="profitRate" label="利润率" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.profitRate >= 20 ? 'success' : scope.row.profitRate >= 10 ? 'warning' : 'danger'">
{{ scope.row.profitRate }}%
</el-tag>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="更新时间" width="180"></el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '已确认' ? 'success' : 'warning'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button size="mini" @click="viewQuotation(scope.row)">查看</el-button>
<el-button size="mini" type="primary" @click="editQuotation(scope.row)">编辑</el-button>
<el-button size="mini" type="success" @click="confirmQuotation(scope.row)"
:disabled="scope.row.status === '已确认'">确认</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleQuotationSizeChange"
@current-change="handleQuotationCurrentChange"
:current-page="quotationSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="quotationSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="quotationTotal">
</el-pagination>
</div>
</el-tab-pane>
<el-tab-pane label="中标通知" name="notices">
<div class="table-actions">
<el-input
placeholder="搜索中标通知"
v-model="noticeSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-download" @click="exportNotices">导出数据</el-button>
<el-button icon="el-icon-refresh" @click="refreshNotices">刷新</el-button>
</div>
</div>
<el-table :data="noticeData" border style="width: 100%">
<el-table-column prop="projectName" label="项目名称" width="250"></el-table-column>
<el-table-column prop="publisher" label="招标单位" width="150"></el-table-column>
<el-table-column prop="winningPrice" label="中标金额" width="120" align="right"></el-table-column>
<el-table-column prop="noticeDate" label="通知日期" width="150"></el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '已签约' ? 'success' :
scope.row.status === '已确认' ? 'primary' : 'warning'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button size="mini" @click="viewNotice(scope.row)">查看</el-button>
<el-button size="mini" type="primary" @click="processNotice(scope.row)">处理</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleNoticeSizeChange"
@current-change="handleNoticeCurrentChange"
:current-page="noticeSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="noticeSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="noticeTotal">
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</div>
<!-- 新建投标对话框 -->
<el-dialog title="新建投标项目" :visible.sync="newBiddingDialogVisible" width="50%">
<el-form :model="newBiddingForm" :rules="biddingRules" ref="newBiddingForm" label-width="120px">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="newBiddingForm.projectName"></el-input>
</el-form-item>
<el-form-item label="招标单位" prop="publisher">
<el-input v-model="newBiddingForm.publisher"></el-input>
</el-form-item>
<el-form-item label="预算金额" prop="budget">
<el-input v-model="newBiddingForm.budget" style="width: 200px;">
<template slot="append">万元</template>
</el-input>
</el-form-item>
<el-form-item label="截止时间" prop="deadline">
<el-date-picker
v-model="newBiddingForm.deadline"
type="datetime"
placeholder="选择日期时间"
value-format="yyyy-MM-dd HH:mm:ss">
</el-date-picker>
</el-form-item>
<el-form-item label="项目地点" prop="location">
<el-cascader
v-model="newBiddingForm.location"
:options="locationOptions"
style="width: 100%;"
></el-cascader>
</el-form-item>
<el-form-item label="项目类型" prop="projectType">
<el-select v-model="newBiddingForm.projectType" style="width: 100%;">
<el-option label="风电叶片检查" value="wind-power"></el-option>
<el-option label="风电运维" value="maintenance"></el-option>
<el-option label="风电安装" value="installation"></el-option>
<el-option label="其他" value="other"></el-option>
</el-select>
</el-form-item>
<el-form-item label="招标文件" prop="docUrl">
<el-upload
class="upload-demo"
action=""
:on-change="handleBiddingFileChange"
:auto-upload="false"
:file-list="biddingFileList"
>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">请上传招标文件</div>
</el-upload>
</el-form-item>
<el-form-item label="项目描述" prop="description">
<el-input type="textarea" v-model="newBiddingForm.description" :rows="3"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="newBiddingDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitNewBidding">确定</el-button>
</span>
</el-dialog>
</div>
<!-- 市场营销 - 营销推广 -->
<div v-if="activeModule === 'marketing-promotion'">
<h2 class="module-title">市场营销 - 营销推广</h2>
<div class="card-container">
<el-tabs v-model="marketingTab">
<el-tab-pane label="营销活动" name="activities">
<div class="table-actions">
<el-input
placeholder="搜索营销活动"
v-model="activitySearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewActivityDialog">新建活动</el-button>
<el-button icon="el-icon-refresh" @click="refreshActivities">刷新</el-button>
</div>
</div>
<el-table :data="activityData" border style="width: 100%">
<el-table-column prop="name" label="活动名称" width="250"></el-table-column>
<el-table-column prop="type" label="活动类型" width="120">
<template slot-scope="scope">
<el-tag>{{ scope.row.type }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="startDate" label="开始时间" width="180"></el-table-column>
<el-table-column prop="endDate" label="结束时间" width="180"></el-table-column>
<el-table-column prop="budget" label="预算" width="120" align="right"></el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '进行中' ? 'success' :
scope.row.status === '已结束' ? 'info' : 'warning'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewActivity(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editActivity(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleActivitySizeChange"
@current-change="handleActivityCurrentChange"
:current-page="activitySearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="activitySearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="activityTotal">
</el-pagination>
</div>
</el-tab-pane>
<el-tab-pane label="客户管理" name="clients">
<div class="table-actions">
<el-input
placeholder="搜索客户"
v-model="clientSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewClientDialog">新增客户</el-button>
<el-button icon="el-icon-refresh" @click="refreshClients">刷新</el-button>
</div>
</div>
<el-table :data="clientData" border style="width: 100%">
<el-table-column prop="name" label="客户名称" width="200"></el-table-column>
<el-table-column prop="industry" label="所属行业" width="150"></el-table-column>
<el-table-column prop="contact" label="联系人" width="120"></el-table-column>
<el-table-column prop="phone" label="联系电话" width="150"></el-table-column>
<el-table-column prop="level" label="客户等级" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.level === 'A' ? 'success' :
scope.row.level === 'B' ? 'primary' : 'warning'">
{{ scope.row.level }}级
</el-tag>
</template>
</el-table-column>
<el-table-column prop="lastContact" label="最后联系" width="180"></el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewClient(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editClient(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleClientSizeChange"
@current-change="handleClientCurrentChange"
:current-page="clientSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="clientSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="clientTotal">
</el-pagination>
</div>
</el-tab-pane>
<el-tab-pane label="营销效果" name="effect">
<div style="margin-bottom: 20px;">
<el-date-picker
v-model="effectDateRange"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
style="width: 300px;"
>
</el-date-picker>
<el-button type="primary" @click="loadEffectData" style="margin-left: 20px;">查询</el-button>
</div>
<div style="display: flex; margin-bottom: 20px;">
<div style="flex: 1; margin-right: 20px;">
<el-card shadow="hover">
<div slot="header">新增客户</div>
<div style="font-size: 24px; text-align: center;">{{ effectData.newClients }}</div>
</el-card>
</div>
<div style="flex: 1; margin-right: 20px;">
<el-card shadow="hover">
<div slot="header">商机数量</div>
<div style="font-size: 24px; text-align: center;">{{ effectData.opportunities }}</div>
</el-card>
</div>
<div style="flex: 1;">
<el-card shadow="hover">
<div slot="header">转化率</div>
<div style="font-size: 24px; text-align: center;">{{ effectData.conversionRate }}%</div>
</el-card>
</div>
</div>
<div style="height: 400px; margin-bottom: 20px;">
<div id="effectChart" style="width: 100%; height: 100%;"></div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
<!-- 市场营销 - 框架协议 -->
<div v-if="activeModule === 'framework-agreement'">
<h2 class="module-title">市场营销 - 框架协议</h2>
<div class="card-container">
<div class="table-actions">
<el-input
placeholder="搜索框架协议"
v-model="agreementSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewAgreementDialog">新建协议</el-button>
<el-button icon="el-icon-refresh" @click="refreshAgreements">刷新</el-button>
</div>
</div>
<el-table :data="agreementData" border style="width: 100%">
<el-table-column prop="name" label="协议名称" width="250"></el-table-column>
<el-table-column prop="client" label="客户名称" width="200"></el-table-column>
<el-table-column prop="startDate" label="开始日期" width="150"></el-table-column>
<el-table-column prop="endDate" label="结束日期" width="150"></el-table-column>
<el-table-column prop="amount" label="预估金额" width="120" align="right"></el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '有效' ? 'success' : 'info'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button size="mini" @click="viewAgreement(scope.row)">查看</el-button>
<el-button size="mini" type="primary" @click="editAgreement(scope.row)">编辑</el-button>
<el-button size="mini" type="danger" @click="terminateAgreement(scope.row)"
:disabled="scope.row.status !== '有效'">终止</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleAgreementSizeChange"
@current-change="handleAgreementCurrentChange"
:current-page="agreementSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="agreementSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="agreementTotal">
</el-pagination>
</div>
</div>
</div>
<!-- 市场营销 - 同行业务 -->
<div v-if="activeModule === 'industry-business'">
<h2 class="module-title">市场营销 - 同行业务</h2>
<div class="card-container">
<el-tabs v-model="industryTab">
<el-tab-pane label="竞争对手" name="competitors">
<div class="table-actions">
<el-input
placeholder="搜索竞争对手"
v-model="competitorSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewCompetitorDialog">新增对手</el-button>
<el-button icon="el-icon-refresh" @click="refreshCompetitors">刷新</el-button>
</div>
</div>
<el-table :data="competitorData" border style="width: 100%">
<el-table-column prop="name" label="公司名称" width="250"></el-table-column>
<el-table-column prop="strength" label="优势领域" width="200"></el-table-column>
<el-table-column prop="marketShare" label="市场份额" width="120">
<template slot-scope="scope">
{{ scope.row.marketShare }}%
</template>
</el-table-column>
<el-table-column prop="recentProjects" label="近期项目" width="150"></el-table-column>
<el-table-column label="竞争等级" width="120">
<template slot-scope="scope">
<el-rate
v-model="scope.row.level"
disabled
show-text
:texts="['弱', '一般', '较强', '强', '很强']"
></el-rate>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewCompetitor(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editCompetitor(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleCompetitorSizeChange"
@current-change="handleCompetitorCurrentChange"
:current-page="competitorSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="competitorSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="competitorTotal">
</el-pagination>
</div>
</el-tab-pane>
<el-tab-pane label="市场分析" name="analysis">
<div style="margin-bottom: 20px;">
<el-date-picker
v-model="analysisYear"
type="year"
placeholder="选择年份"
value-format="yyyy"
style="width: 200px;"
>
</el-date-picker>
<el-button type="primary" @click="loadAnalysisData" style="margin-left: 20px;">查询</el-button>
</div>
<div style="height: 400px; margin-bottom: 20px;">
<div id="marketShareChart" style="width: 100%; height: 100%;"></div>
</div>
<div style="height: 400px;">
<div id="priceTrendChart" style="width: 100%; height: 100%;"></div>
</div>
</el-tab-pane>
<el-tab-pane label="议价策略" name="strategy">
<div style="margin-bottom: 20px;">
<el-button type="primary" icon="el-icon-plus" @click="showNewStrategyDialog">新建策略</el-button>
</div>
<el-table :data="strategyData" border style="width: 100%">
<el-table-column prop="name" label="策略名称" width="250"></el-table-column>
<el-table-column prop="target" label="目标客户" width="200"></el-table-column>
<el-table-column prop="discount" label="折扣范围" width="120">
<template slot-scope="scope">
{{ scope.row.discount }}%
</template>
</el-table-column>
<el-table-column prop="conditions" label="适用条件" width="200"></el-table-column>
<el-table-column prop="effectiveness" label="有效性" width="120">
<template slot-scope="scope">
<el-tag :type="scope.row.effectiveness === '高' ? 'success' :
scope.row.effectiveness === '中' ? 'warning' : 'danger'">
{{ scope.row.effectiveness }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewStrategy(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editStrategy(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleStrategySizeChange"
@current-change="handleStrategyCurrentChange"
:current-page="strategySearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="strategySearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="strategyTotal">
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
<!-- 自建项目 - 软件开发 -->
<div v-if="activeModule === 'software-dev'">
<h2 class="module-title">自建项目 - 软件开发</h2>
<div class="card-container">
<div class="table-actions">
<el-input
placeholder="搜索软件项目"
v-model="softwareSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewSoftwareDialog">新建项目</el-button>
<el-button icon="el-icon-refresh" @click="refreshSoftwareProjects">刷新</el-button>
</div>
</div>
<el-table :data="softwareData" border style="width: 100%">
<el-table-column prop="name" label="项目名称" width="250"></el-table-column>
<el-table-column prop="type" label="项目类型" width="150">
<template slot-scope="scope">
<el-tag>{{ scope.row.type }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="manager" label="项目经理" width="120"></el-table-column>
<el-table-column prop="startDate" label="开始日期" width="150"></el-table-column>
<el-table-column prop="endDate" label="计划完成" width="150"></el-table-column>
<el-table-column prop="progress" label="进度" width="150">
<template slot-scope="scope">
<el-progress :percentage="scope.row.progress" :status="scope.row.progress === 100 ? 'success' : ''"></el-progress>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewSoftwareProject(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editSoftwareProject(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleSoftwareSizeChange"
@current-change="handleSoftwareCurrentChange"
:current-page="softwareSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="softwareSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="softwareTotal">
</el-pagination>
</div>
</div>
</div>
<!-- 项目合同管理 - 收入合同 -->
<div v-if="activeModule === 'income-contract'">
<h2 class="module-title">项目合同管理 - 收入合同</h2>
<div class="card-container">
<div class="table-actions">
<el-input
placeholder="搜索收入合同"
v-model="incomeContractSearch.keyword"
clearable
style="width: 300px;"
>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<div>
<el-button type="primary" icon="el-icon-plus" @click="showNewIncomeContractDialog">新建合同</el-button>
<el-button icon="el-icon-refresh" @click="refreshIncomeContracts">刷新</el-button>
</div>
</div>
<el-table :data="incomeContractData" border style="width: 100%">
<el-table-column prop="code" label="合同编号" width="150"></el-table-column>
<el-table-column prop="name" label="合同名称" width="250"></el-table-column>
<el-table-column prop="client" label="客户名称" width="200"></el-table-column>
<el-table-column prop="amount" label="合同金额" width="150" align="right"></el-table-column>
<el-table-column prop="signDate" label="签订日期" width="150"></el-table-column>
<el-table-column prop="status" label="合同状态" width="150">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '履行中' ? 'success' :
scope.row.status === '已完成' ? 'info' : 'warning'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button size="mini" @click="viewIncomeContract(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="editIncomeContract(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleIncomeContractSizeChange"
@current-change="handleIncomeContractCurrentChange"
:current-page="incomeContractSearch.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="incomeContractSearch.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="incomeContractTotal">
</el-pagination>
</div>
</div>
</div>
<!-- 施工立项 -->
<div v-if="activeModule === 'construction'">
<h2 class="module-title">施工立项</h2>
<div class="card-container">
<el-alert
title="此功能已实现,请从导航菜单进入具体功能"
type="info"
show-icon
:closable="false"
>
</el-alert>
</div>
</div>
<!-- 组织实施管理 -->
<div v-if="activeModule === 'implementation'">
<h2 class="module-title">组织实施管理</h2>
<div class="card-container">
<el-alert
title="此功能已实现,请从导航菜单进入具体功能"
type="info"
show-icon
:closable="false"
>
</el-alert>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.2/dist/echarts.min.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
isCollapse: false,
activeModule: 'bidding-search',
// 招采业务 - 信息检索
biddingSearch: {
keyword: '',
page: 1,
limit: 10
},
biddingData: [
{
title: '某风电场2023年叶片检查服务采购项目',
publisher: '某风电有限公司',
budget: '120.00万元',
deadline: '2023-12-15 17:00',
source: '中国招标投标网',
status: '进行中',
location: '内蒙古自治区',
duration: '6个月',
scope: '风电场50台机组叶片检查服务',
qualification: '具备风电叶片检查资质',
docUrl: 'https://example.com/bidding-docs/123',
content: '<p>本项目为某风电场2023年叶片检查服务采购包括但不限于</p><ul><li>叶片外观检查</li><li>无损检测</li><li>缺陷记录与评估</li><li>检查报告编制</li></ul>'
},
// 更多数据...
],
biddingTotal: 20,
currentBidding: null,
biddingDetailVisible: false,
crawlerSettingsVisible: false,
crawlerSettings: {
frequency: 'daily',
keywords: ['风电', '叶片', '检查', '运维'],
platforms: ['中国招标投标公共服务平台', '各省市公共资源交易中心'],
autoNotify: true,
notifyMethods: ['站内消息', '电子邮件']
},
newKeyword: '',
// 招采业务 - 投标响应
biddingResponseTab: 'projects',
biddingResponseSearch: {
keyword: '',
page: 1,
limit: 10
},
biddingResponseData: [
{
projectName: '某风电场2023年叶片检查服务采购项目',
publisher: '某风电有限公司',
budget: '120.00万元',
deadline: '2023-12-15 17:00',
status: '准备中',
progress: 30
},
// 更多数据...
],
biddingResponseTotal: 15,
documentSearch: {
keyword: '',
page: 1,
limit: 10
},
documentData: [
{
name: '某风电场叶片检查技术标书',
project: '某风电场2023年叶片检查',
type: '技术标',
version: '1.0',
updateTime: '2023-11-10 14:30',
status: '进行中'
},
// 更多数据...
],
documentTotal: 8,
quotationSearch: {
keyword: '',
page: 1,
limit: 10
},
quotationData: [
{
name: '某风电场叶片检查报价单',
project: '某风电场2023年叶片检查',
totalPrice: '1,080,000.00',
profitRate: 15,
updateTime: '2023-11-08 10:15',
status: '草稿'
},
// 更多数据...
],
quotationTotal: 5,
noticeSearch: {
keyword: '',
page: 1,
limit: 10
},
noticeData: [
{
projectName: '某风电场2022年叶片检查服务',
publisher: '某风电有限公司',
winningPrice: '980,000.00',
noticeDate: '2023-01-15',
status: '已签约'
},
// 更多数据...
],
noticeTotal: 3,
newBiddingDialogVisible: false,
newBiddingForm: {
projectName: '',
publisher: '',
budget: '',
deadline: '',
location: [],
projectType: '',
docUrl: '',
description: ''
},
biddingRules: {
projectName: [
{ required: true, message: '请输入项目名称', trigger: 'blur' }
],
publisher: [
{ required: true, message: '请输入招标单位', trigger: 'blur' }
]
},
locationOptions: [
{
value: '北京市',
label: '北京市',
children: [
{ value: '东城区', label: '东城区' },
// 更多区县...
]
},
// 更多省市...
],
biddingFileList: [],
// 市场营销 - 营销推广
marketingTab: 'activities',
activitySearch: {
keyword: '',
page: 1,
limit: 10
},
activityData: [
{
name: '2023年风电运维技术研讨会',
type: '会议',
startDate: '2023-10-15 09:00',
endDate: '2023-10-16 17:00',
budget: '50,000.00',
status: '已结束'
},
// 更多数据...
],
activityTotal: 12,
clientSearch: {
keyword: '',
page: 1,
limit: 10
},
clientData: [
{
name: '某风电集团有限公司',
industry: '风电',
contact: '张经理',
phone: '13800138000',
level: 'A',
lastContact: '2023-11-08'
},
// 更多数据...
],
clientTotal: 25,
effectDateRange: ['2023-01-01', '2023-12-31'],
effectData: {
newClients: 15,
opportunities: 8,
conversionRate: 35
},
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit('pick', [start, end]);
}
}, {
text: '最近三个月',
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit('pick', [start, end]);
}
}]
},
// 市场营销 - 框架协议
agreementSearch: {
keyword: '',
page: 1,
limit: 10
},
agreementData: [
{
name: '某风电集团2023-2025年叶片检查框架协议',
client: '某风电集团有限公司',
startDate: '2023-01-01',
endDate: '2025-12-31',
amount: '5,000,000.00',
status: '有效'
},
// 更多数据...
],
agreementTotal: 5,
// 市场营销 - 同行业务
industryTab: 'competitors',
competitorSearch: {
keyword: '',
page: 1,
limit: 10
},
competitorData: [
{
name: '某风电技术服务有限公司',
strength: '叶片维修',
marketShare: 25,
recentProjects: '多个风场运维',
level: 4
},
// 更多数据...
],
competitorTotal: 8,
analysisYear: '2023',
strategySearch: {
keyword: '',
page: 1,
limit: 10
},
strategyData: [
{
name: '长期合作客户优惠',
target: '框架协议客户',
discount: '5-10',
conditions: '合同金额大于100万',
effectiveness: '高'
},
// 更多数据...
],
strategyTotal: 6,
// 自建项目 - 软件开发
softwareSearch: {
keyword: '',
page: 1,
limit: 10
},
softwareData: [
{
name: '风电叶片智能检查系统',
type: '管理平台',
manager: '张工程师',
startDate: '2023-01-15',
endDate: '2023-12-31',
progress: 75
},
// 更多数据...
],
softwareTotal: 3,
// 项目合同管理 - 收入合同
incomeContractSearch: {
keyword: '',
page: 1,
limit: 10
},
incomeContractData: [
{
code: 'HT2023001',
name: '某风电场叶片检查服务合同',
client: '某风电有限公司',
amount: '980,000.00',
signDate: '2023-01-20',
status: '履行中'
},
// 更多数据...
],
incomeContractTotal: 5
}
},
mounted() {
// 初始化图表
this.initCharts();
},
methods: {
toggleSidebar() {
this.isCollapse = !this.isCollapse;
},
switchModule(module) {
this.activeModule = module;
},
// 招采业务 - 信息检索
searchBiddingInfo() {
this.$message(`搜索招标信息: ${this.biddingSearch.keyword}`);
// 实际应用中这里应该调用API获取数据
},
refreshBiddingData() {
this.$message('刷新招标数据');
// 实际应用中这里应该调用API获取数据
},
exportBiddingData() {
this.$message('导出招标数据');
},
showCrawlerSettings() {
this.crawlerSettingsVisible = true;
},
viewBiddingDetail(row) {
this.currentBidding = row;
this.biddingDetailVisible = true;
},
markAsInterested(row) {
this.$confirm(`确定要关注招标项目 "${row.title}" 吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '已关注该项目!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消操作'
});
});
},
goToBiddingResponse() {
this.biddingDetailVisible = false;
this.switchModule('bidding-response');
},
addKeyword() {
if (this.newKeyword && !this.crawlerSettings.keywords.includes(this.newKeyword)) {
this.crawlerSettings.keywords.push(this.newKeyword);
this.newKeyword = '';
}
},
removeKeyword(tag) {
this.crawlerSettings.keywords = this.crawlerSettings.keywords.filter(item => item !== tag);
},
saveCrawlerSettings() {
this.$message.success('爬虫设置已保存');
this.crawlerSettingsVisible = false;
},
handleBiddingSizeChange(val) {
this.biddingSearch.limit = val;
this.refreshBiddingData();
},
handleBiddingCurrentChange(val) {
this.biddingSearch.page = val;
this.refreshBiddingData();
},
// 招采业务 - 投标响应
showNewBiddingDialog() {
this.newBiddingDialogVisible = true;
},
refreshBiddingResponse() {
this.$message('刷新投标响应数据');
// 实际应用中这里应该调用API获取数据
},
viewBiddingResponse(row) {
this.$message(`查看投标响应: ${row.projectName}`);
},
editBiddingResponse(row) {
this.$message(`编辑投标响应: ${row.projectName}`);
},
refreshDocuments() {
this.$message('刷新标书数据');
// 实际应用中这里应该调用API获取数据
},
viewDocument(row) {
this.$message(`查看标书: ${row.name}`);
},
editDocument(row) {
this.$message(`编辑标书: ${row.name}`);
},
generateDocument(row) {
this.$message(`生成标书: ${row.name}`);
},
refreshQuotations() {
this.$message('刷新报价数据');
// 实际应用中这里应该调用API获取数据
},
viewQuotation(row) {
this.$message(`查看报价: ${row.name}`);
},
editQuotation(row) {
this.$message(`编辑报价: ${row.name}`);
},
confirmQuotation(row) {
this.$confirm(`确定要确认报价 "${row.name}" 吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
row.status = '已确认';
this.$message({
type: 'success',
message: '报价已确认!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消操作'
});
});
},
refreshNotices() {
this.$message('刷新中标通知数据');
// 实际应用中这里应该调用API获取数据
},
exportNotices() {
this.$message('导出中标通知数据');
},
viewNotice(row) {
this.$message(`查看中标通知: ${row.projectName}`);
},
processNotice(row) {
this.$message(`处理中标通知: ${row.projectName}`);
},
handleBiddingFileChange(file, fileList) {
this.biddingFileList = fileList;
},
submitNewBidding() {
this.$refs.newBiddingForm.validate(valid => {
if (valid) {
this.$message.success('新建投标项目成功');
this.newBiddingDialogVisible = false;
this.refreshBiddingResponse();
} else {
return false;
}
});
},
handleBiddingResponseSizeChange(val) {
this.biddingResponseSearch.limit = val;
this.refreshBiddingResponse();
},
handleBiddingResponseCurrentChange(val) {
this.biddingResponseSearch.page = val;
this.refreshBiddingResponse();
},
handleDocumentSizeChange(val) {
this.documentSearch.limit = val;
this.refreshDocuments();
},
handleDocumentCurrentChange(val) {
this.documentSearch.page = val;
this.refreshDocuments();
},
handleQuotationSizeChange(val) {
this.quotationSearch.limit = val;
this.refreshQuotations();
},
handleQuotationCurrentChange(val) {
this.quotationSearch.page = val;
this.refreshQuotations();
},
handleNoticeSizeChange(val) {
this.noticeSearch.limit = val;
this.refreshNotices();
},
handleNoticeCurrentChange(val) {
this.noticeSearch.page = val;
this.refreshNotices();
},
// 市场营销 - 营销推广
showNewActivityDialog() {
this.$message('显示新建营销活动对话框');
},
refreshActivities() {
this.$message('刷新营销活动数据');
// 实际应用中这里应该调用API获取数据
},
viewActivity(row) {
this.$message(`查看营销活动: ${row.name}`);
},
editActivity(row) {
this.$message(`编辑营销活动: ${row.name}`);
},
showNewClientDialog() {
this.$message('显示新增客户对话框');
},
refreshClients() {
this.$message('刷新客户数据');
// 实际应用中这里应该调用API获取数据
},
viewClient(row) {
this.$message(`查看客户: ${row.name}`);
},
editClient(row) {
this.$message(`编辑客户: ${row.name}`);
},
loadEffectData() {
this.$message('加载营销效果数据');
// 实际应用中这里应该调用API获取数据
this.initEffectChart();
},
handleActivitySizeChange(val) {
this.activitySearch.limit = val;
this.refreshActivities();
},
handleActivityCurrentChange(val) {
this.activitySearch.page = val;
this.refreshActivities();
},
handleClientSizeChange(val) {
this.clientSearch.limit = val;
this.refreshClients();
},
handleClientCurrentChange(val) {
this.clientSearch.page = val;
this.refreshClients();
},
// 市场营销 - 框架协议
showNewAgreementDialog() {
this.$message('显示新建框架协议对话框');
},
refreshAgreements() {
this.$message('刷新框架协议数据');
// 实际应用中这里应该调用API获取数据
},
viewAgreement(row) {
this.$message(`查看框架协议: ${row.name}`);
},
editAgreement(row) {
this.$message(`编辑框架协议: ${row.name}`);
},
terminateAgreement(row) {
this.$confirm(`确定要终止框架协议 "${row.name}" 吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
row.status = '已终止';
this.$message({
type: 'success',
message: '协议已终止!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消操作'
});
});
},
handleAgreementSizeChange(val) {
this.agreementSearch.limit = val;
this.refreshAgreements();
},
handleAgreementCurrentChange(val) {
this.agreementSearch.page = val;
this.refreshAgreements();
},
// 市场营销 - 同行业务
showNewCompetitorDialog() {
this.$message('显示新增竞争对手对话框');
},
refreshCompetitors() {
this.$message('刷新竞争对手数据');
// 实际应用中这里应该调用API获取数据
},
viewCompetitor(row) {
this.$message(`查看竞争对手: ${row.name}`);
},
editCompetitor(row) {
this.$message(`编辑竞争对手: ${row.name}`);
},
loadAnalysisData() {
this.$message('加载市场分析数据');
// 实际应用中这里应该调用API获取数据
this.initMarketShareChart();
this.initPriceTrendChart();
},
showNewStrategyDialog() {
this.$message('显示新建议价策略对话框');
},
viewStrategy(row) {
this.$message(`查看议价策略: ${row.name}`);
},
editStrategy(row) {
this.$message(`编辑议价策略: ${row.name}`);
},
handleCompetitorSizeChange(val) {
this.competitorSearch.limit = val;
this.refreshCompetitors();
},
handleCompetitorCurrentChange(val) {
this.competitorSearch.page = val;
this.refreshCompetitors();
},
handleStrategySizeChange(val) {
this.strategySearch.limit = val;
// 实际应用中这里应该调用API获取数据
},
handleStrategyCurrentChange(val) {
this.strategySearch.page = val;
// 实际应用中这里应该调用API获取数据
},
// 自建项目 - 软件开发
showNewSoftwareDialog() {
this.$message('显示新建软件项目对话框');
},
refreshSoftwareProjects() {
this.$message('刷新软件项目数据');
// 实际应用中这里应该调用API获取数据
},
viewSoftwareProject(row) {
this.$message(`查看软件项目: ${row.name}`);
},
editSoftwareProject(row) {
this.$message(`编辑软件项目: ${row.name}`);
},
handleSoftwareSizeChange(val) {
this.softwareSearch.limit = val;
this.refreshSoftwareProjects();
},
handleSoftwareCurrentChange(val) {
this.softwareSearch.page = val;
this.refreshSoftwareProjects();
},
// 项目合同管理 - 收入合同
showNewIncomeContractDialog() {
this.$message('显示新建收入合同对话框');
},
refreshIncomeContracts() {
this.$message('刷新收入合同数据');
// 实际应用中这里应该调用API获取数据
},
viewIncomeContract(row) {
this.$message(`查看收入合同: ${row.name}`);
},
editIncomeContract(row) {
this.$message(`编辑收入合同: ${row.name}`);
},
handleIncomeContractSizeChange(val) {
this.incomeContractSearch.limit = val;
this.refreshIncomeContracts();
},
handleIncomeContractCurrentChange(val) {
this.incomeContractSearch.page = val;
this.refreshIncomeContracts();
},
// 图表初始化
initCharts() {
// 初始化营销效果图表
this.initEffectChart();
// 初始化市场份额图表
this.initMarketShareChart();
// 初始化价格趋势图表
this.initPriceTrendChart();
},
initEffectChart() {
const chart = echarts.init(document.getElementById('effectChart'));
chart.setOption({
title: {
text: '营销活动效果趋势',
left: 'center'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['新增客户', '商机数量', '转化率'],
bottom: 10
},
grid: {
left: '3%',
right: '4%',
bottom: '15%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: [
{
type: 'value',
name: '数量',
position: 'left'
},
{
type: 'value',
name: '转化率(%)',
position: 'right',
max: 100
}
],
series: [
{
name: '新增客户',
type: 'line',
data: [5, 8, 10, 12, 15, 18, 20, 22, 25, 28, 30, 32],
smooth: true,
itemStyle: {
color: '#409EFF'
}
},
{
name: '商机数量',
type: 'line',
data: [2, 3, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22],
smooth: true,
itemStyle: {
color: '#67C23A'
}
},
{
name: '转化率',
type: 'line',
yAxisIndex: 1,
data: [40, 38, 50, 50, 53, 56, 60, 64, 64, 64, 67, 69],
smooth: true,
itemStyle: {
color: '#E6A23C'
}
}
]
});
},
initMarketShareChart() {
const chart = echarts.init(document.getElementById('marketShareChart'));
chart.setOption({
title: {
text: '2023年风电叶片检查市场份额',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 10,
data: ['我公司', '竞争对手A', '竞争对手B', '竞争对手C', '其他']
},
series: [
{
name: '市场份额',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '18',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ value: 35, name: '我公司', itemStyle: { color: '#409EFF' } },
{ value: 25, name: '竞争对手A', itemStyle: { color: '#67C23A' } },
{ value: 20, name: '竞争对手B', itemStyle: { color: '#E6A23C' } },
{ value: 15, name: '竞争对手C', itemStyle: { color: '#F56C6C' } },
{ value: 5, name: '其他', itemStyle: { color: '#909399' } }
]
}
]
});
},
initPriceTrendChart() {
const chart = echarts.init(document.getElementById('priceTrendChart'));
chart.setOption({
title: {
text: '2023年风电叶片检查服务价格趋势',
left: 'center'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['我公司报价', '行业平均价', '最低价'],
bottom: 10
},
grid: {
left: '3%',
right: '4%',
bottom: '15%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: {
type: 'value',
name: '价格(万元/台)'
},
series: [
{
name: '我公司报价',
type: 'line',
data: [2.5, 2.6, 2.55, 2.4, 2.3, 2.2, 2.1, 2.0, 1.95, 1.9, 1.85, 1.8],
smooth: true,
itemStyle: {
color: '#409EFF'
}
},
{
name: '行业平均价',
type: 'line',
data: [2.8, 2.7, 2.65, 2.6, 2.5, 2.4, 2.3, 2.2, 2.1, 2.0, 1.95, 1.9],
smooth: true,
itemStyle: {
color: '#67C23A'
}
},
{
name: '最低价',
type: 'line',
data: [2.2, 2.1, 2.0, 1.9, 1.8, 1.7, 1.6, 1.55, 1.5, 1.45, 1.4, 1.35],
smooth: true,
itemStyle: {
color: '#F56C6C'
}
}
]
});
}
}
});
</script>
</body>
</html>