Commit 2a86db2b authored by 高宇's avatar 高宇

修复 bug;

parent 1e079817
......@@ -23,7 +23,7 @@
{
"icon": "fa-book",
"isRouteShow": 1,
"title": "商机列表",
"title": "商机信息",
"appName": portalName,
"url": "/project"
},
......@@ -64,6 +64,14 @@
isRouteShow: 1,
title: "评测投票",
url: "/rating"
},
{
appName: "purchaseContracts",
icon: "fa-shopping-bag",
id: 1,
isRouteShow: 1,
title: "采购合同",
url: "/contract"
}
],
homePage: {
......
import ElementApi from './apis/project'
import sales from './apis/sales'
import contract from './apis/contract'
import salesContract from './apis/salesContract'
import product from './apis/product'
import addressBook from './apis/addressBook'
import rating from './apis/rating'
import contract from './apis/contract'
const usingJSONP = process.env.NODE_ENV !== 'production'
const API_HOST = process.env.API_HOST
const API_PORT = process.env.API_PORT
......@@ -28,7 +30,16 @@ const option = {
}
let apis = {}
apis = Object.assign(apis, ElementApi, sales, contract, product, addressBook, rating)
apis = Object.assign(apis, ElementApi, sales, salesContract, product, addressBook, rating, contract, {
// 搜索供应商名称
searchSupplierByName: {
url: '/vue/search/supplier-by-name'
},
// 搜索客户名称列表
searchClientByName: {
url: '/vue/search/client-by-name'
}
})
export default {
option,
...apis
......
export default {
getContractFilter: {
url: '/vue/sales-contract/get-filter'
url: '/vue/purchase-contract/get-filter'
},
getContractList: {
url: '/vue/sales-contract/list'
url: '/vue/purchase-contract/list'
},
getContractClient: {
url: '/vue/sales-contract/of-client'
url: '/vue/purchase-contract/of-client'
},
// 获取新建销售合同 option
getContractNewOptions: {
url: '/vue/sales-contract/get-new'
},
// 新建销售合同保存
saveContractAdd: {
url: '/vue/sales-contract/save-new'
},
// 获取销售合同编辑信息
getContractEdit: {
url: '/vue/sales-contract/get-edit'
url: '/vue/purchase-contract/get-edit'
},
// 销售合同编辑保存
saveContractEdit: {
url: '/vue/sales-contract/save-edit'
url: '/vue/purchase-contract/save-edit'
},
// 删除销售合同
delContract: {
url: '/vue/sales-contract/delete'
saveContractAdd: {
url: '/vue/purchase-contract/save-new'
},
getContractNewOptions: {
url: '/vue/purchase-contract/get-new'
},
uploadSingle: {
url: '/vue/upload/single'
delContract: {
url: '/vue/purchase-contract/delete'
}
}
......@@ -194,10 +194,5 @@ export default {
// 2 获取产品系列筛选
getProductSerieFilter: {
url: '/vue/product/get-filter-product-serie'
},
// 搜索供应商名称
searchSupplierByName: {
url: '/vue/search/supplier-by-name'
}
}
......@@ -52,10 +52,6 @@ export default {
url: '/vue/project/of-client'
},
// 搜索客户名称列表
searchClientByName: {
url: '/vue/search/client-by-name'
},
// 搜索客户联系人
searchContactByClientId: {
url: '/vue/search/contact-by-client-id'
......
......@@ -64,9 +64,5 @@ export default {
},
getSalesProduct: {
url: '/vue/sales-order/get-product'
},
// 搜索供应商名称
searchSupplierByName: {
url: '/vue/search/supplier-by-name'
}
}
export default {
getSalesContractFilter: {
url: '/vue/sales-contract/get-filter'
},
getSalesContractList: {
url: '/vue/sales-contract/list'
},
getSalesContractClient: {
url: '/vue/sales-contract/of-client'
},
// 获取新建销售合同 option
getSalesContractNewOptions: {
url: '/vue/sales-contract/get-new'
},
// 新建销售合同保存
saveSalesContractAdd: {
url: '/vue/sales-contract/save-new'
},
// 获取销售合同编辑信息
getSalesContractEdit: {
url: '/vue/sales-contract/get-edit'
},
// 销售合同编辑保存
saveSalesContractEdit: {
url: '/vue/sales-contract/save-edit'
},
// 删除销售合同
delSalesContract: {
url: '/vue/sales-contract/delete'
},
uploadSingle: {
url: '/vue/upload/single'
}
}
<template>
<div>
<el-row class="form-content">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-row class="form-content">
<el-col :span="4" v-for="(item, key) in filter" :key="key">
<el-form-item>
<span slot="label" v-if="item.key !== 'Filter[sort]'">
......@@ -36,8 +36,8 @@
></el-cascader>
</el-form-item>
</el-col>
</el-form>
</el-row>
</el-row>
</el-form>
</div>
</template>
......@@ -228,7 +228,8 @@
.form-content-time-top .el-radio-button__inner:hover {
border-color: #DCDFE6 !important;
}
.form-content-time-top .form-content-time-range .el-form-item .el-form-item__content{
.form-content-time-top .form-content-time-range .el-form-item .el-form-item__content {
display: flex;
font-size: 12px;
}
......
......@@ -11,7 +11,7 @@
:hide-loading="true"
:trigger-on-focus="false"
:fetch-suggestions="querySearchAsync"
placeholder="输入查找客户"
:placeholder="label"
:disabled="singleSearchDisabled || disabled"
@select="handleSelect"
></el-autocomplete>
......
......@@ -5,7 +5,7 @@
<span>{{label}}</span>
</el-col>
<el-col :span="14">
<el-select v-model="item" :placeholder="label" size="mini" @change="selectChange" filterable="filterable" :disabled="this.disabled">
<el-select v-model="item" clearable :placeholder="label" size="mini" @change="selectChange" filterable="filterable" :disabled="this.disabled">
<template slot="prefix" v-if="prefix.text !== ''">
{{prefix.text}}
</template>
......
<template>
<div>
<el-row class="form-content">
<el-form ref="clientTimeRange" :model="clientTimeRange" size="mini" label-position="top">
<el-col :span="8" :xs="{span: 24, offset: 0}" class="form-content-time-top">
<el-col :span="8" :xs="{span: 24, offset: 0}" class="form-content-time-top">
<el-form ref="clientTimeRange" :model="clientTimeRange" size="mini" label-position="top">
<el-form-item label="签订日期">
<div class="form-content-time-range">
<el-date-picker
......@@ -23,8 +23,8 @@
<el-button type="primary" size="mini" @click="setSearchTime">确定</el-button>
</div>
</el-form-item>
</el-col>
</el-form>
</el-form>
</el-col>
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-col :span="4" v-for="(item, key) in filter" :key="key">
<el-form-item>
......@@ -61,7 +61,9 @@
</el-form-item>
</el-col>
</el-form>
</el-row>
</div>
</template>
......@@ -256,8 +258,13 @@
border-color: #DCDFE6 !important;
}
.form-content-time-top .el-form-item .el-form-item__content .form-content-time-range{
.form-content-time-top .el-form-item .el-form-item__content .form-content-time-range {
display: flex;
font-size: 12px;
}
</style>
<style>
.sales-contract {
height: 125px;
}
</style>
......@@ -2,13 +2,13 @@
<section>
<div class="content">
<client-header ref="clientHeader"
title="销售合同"
title="采购合同"
:title-span="6"
:model="form"
search-key="SalesContractSearch"
search-key="PurchaseContractSearch"
key-code="keyword"
type="keyword"
button-title="新建销售合同 "
button-title="新建采购合同"
:reset-form="resetForm"
:add-new-user="addNewContract"
:search-keyword="searchKeyword"></client-header>
......@@ -25,17 +25,17 @@
@update:image="imgs => {setImage(imgs)}"
@update:showProject="project => {showProject(project)}">
<span slot="opearate">
<!--:disabled="!item.can_delete"-->
<el-button class="pull-right"
type="primary"
size="mini"
:disabled="!item.can_delete"
@click="delContract(item.id)">
<i class="fa fa-trash-o faa-shake"></i> 删除
</el-button>
<!--:disabled="!item.can_update"-->
<el-button class="pull-right"
type="primary"
size="mini"
:disabled="!item.can_update"
@click.prevent.stop="editContract(item)">
<i class="fa fa-edit"></i> 编辑
</el-button>
......@@ -143,7 +143,7 @@
list: []
},
form: {
'SalesContractSearch[keyword]': ''
'PurchaseContractSearch[keyword]': ''
},
filter: [],
pagenation: {
......@@ -151,7 +151,7 @@
},
totalcount: 0,
loading: false,
formSearchKey: 'SalesContractSearch'
formSearchKey: 'PurchaseContractSearch'
}
},
methods: {
......@@ -213,14 +213,36 @@
},
addNewContract () {
this.operationPage = 'addContract'
this.operationTitle = '新建销售合同'
this.operationTitle = '新建采购合同'
this.$nextTick(() => {
this.$refs.sidePopup.show(this.$refs[this.operationPage].init())
})
},
delContract (id) {
this.$confirm('确认删除吗?', '提示').then(() => {
requestAPI(api.delContract, {
data: {
id
}
}).then(() => {
this.$message('删除成功!')
this.getList()
}, error => {
if (Array.isArray(error.msg)) {
error.msg.forEach(item => {
this.$notify.error({
title: '错误',
message: item.error
})
})
}
})
}).catch(_ => {
})
},
editContract (row) {
this.operationPage = 'editContract'
this.operationTitle = '编辑销售合同'
this.operationTitle = '编辑采购合同'
this.$nextTick(() => {
this.$refs.sidePopup.show(this.$refs[this.operationPage].init(row.id))
})
......@@ -229,26 +251,9 @@
Object.assign(this.form, form)
this.getList()
},
resetListData (list) {
// ['产品销售', '运维服务'][parseInt(item.contract_type) - 1]
list.forEach(item => {
item.contractType = ['产品销售', '运维服务'][parseInt(item.contract_type) - 1]
if (Object.keys(item.client.salesRep).length > 0) {
item.salesRep = item.client.salesRep.name
} else {
item.salesRep = '(未设置)'
}
if (Object.keys(item.createdBy).length > 0) {
item.createdUser = item.createdBy.name
} else {
item.createdUser = '(未设置)'
}
})
return list
},
resetForm () {
this.pagenation.page = 1
this.$refs.clientForm.resetForm()
this.$refs.clientForm && this.$refs.clientForm.resetForm()
Object.keys(this.form).forEach(item => {
this.form[item] = ''
})
......@@ -269,7 +274,7 @@
page: this.pagenation.page
}
}).then(res => {
this.result.list = this.resetListData(res.list)
this.result.list = res.list
// this.pagenation.page = res.pagenation.thispage
this.totalcount = res.pagenation.totalcount
// this.totalcount = 8
......
<template>
<section>
<div class="content">
<client-header ref="clientHeader"
:title="'客户名称:' + model.name"
:title-span="12"
type=""></client-header>
<div class="page-body-content">
<client-nav :trigger="addContract" trigger-text="新建采购合同"></client-nav>
<div v-loading="loading">
<ScheduleItem
v-for="(item, key) in result.list"
:item="item"
:key="key"
@update:image="imgs => {setImage(imgs)}"
@update:showProject="project => {showProject(project)}">
<span slot="opearate">
<el-button class="pull-right"
type="primary"
size="mini"
:disabled="!item.can_delete"
@click="delContract(item.id)">
<i class="fa fa-trash-o faa-shake"></i> 删除
</el-button>
<el-button class="pull-right"
type="primary"
size="mini"
:disabled="!item.can_update"
@click.prevent.stop="editContract(item)">
<i class="fa fa-edit"></i> 编辑
</el-button>
<el-button class="pull-right"
type="primary"
size="mini"
@click.prevent.stop="leaveMessageSch(item)">
<span :class="['badge', {'badge-unread': item.unread > 0}]"
v-if="item.commentCount">{{item.commentCount.comment}}</span>
<i class="fa fa-commenting"></i> 留言
</el-button>
</span>
</ScheduleItem>
<div v-if="result.list.length === 0">
<el-card class="box-card">
未查询到数据!
</el-card>
</div>
</div>
<Pagenation
@update:pager="pager => {updatePage(pager)}"
:pager.sync="pagenation"
:total="totalcount">
</Pagenation>
<leave-message
v-click-outside="lmClose"
ref="leaveMessage"
:lmTemplate="lmTemplate"
:type="1">
</leave-message>
</div>
</div>
<side-popup ref="sidePopup" :title="operationTitle" v-click-outside="popupClose">
<component :is="operationPage" :ref="operationPage" @close="getList => {close(getList)}"></component>
</side-popup>
</section>
</template>
<script>
import ScheduleItem from '../scheduleItem'
import clientHeader from '../../common/clientHeader'
import Pagenation from '../../common/schedulePagenation'
import clickOutside from '@/lib/bind'
import addContract from '../operation/addContract'
import editContract from '../operation/editContract'
import viewProject from '../operation/viewProject'
import {
requestAPI,
api
} from '@/lib/commonMixin'
export default {
name: '',
directives: {
clickOutside
},
data () {
return {
lmTemplate: [
{
name: '客户名称',
value: 'client.name',
default: ''
},
{
name: '合同类型',
value: 'contractType',
default: ''
},
{
name: '总额',
value: 'amount',
default: '',
prepend: '¥'
},
{
name: '客户经理',
value: 'salesRep',
default: ''
},
{
name: '录入人',
value: 'createdUser',
default: ''
},
{
name: '签订日期',
value: 'signed_at',
default: ''
}
],
operationPage: '',
operationTitle: '',
clientName: '',
model: {
name: ''
},
result: {
list: []
},
pagenation: {
page: 1
},
totalcount: 0,
loading: false
}
},
components: {
ScheduleItem,
clientHeader,
Pagenation,
addContract,
editContract,
viewProject
},
methods: {
showProject (project) {
this.operationPage = 'viewProject'
this.operationTitle = '商机信息'
requestAPI(api.getProjectEdit, {
data: {
id: project.key
}
}).then(res => {
this.$refs.sidePopup.show(this.$refs[this.operationPage].init(res))
})
},
addContract () {
this.operationPage = 'addContract'
this.operationTitle = '新建采购合同'
this.$nextTick(() => {
this.$refs.sidePopup.show(this.$refs[this.operationPage].init())
})
},
editContract (row) {
this.operationPage = 'editContract'
this.operationTitle = '编辑采购合同'
this.$nextTick(() => {
this.$refs.sidePopup.show(this.$refs[this.operationPage].init(row.id))
})
},
close (getList) {
this.$refs.sidePopup.close()
if (getList) {
this.getList()
}
},
leaveMessageSch (item) {
this.$refs.leaveMessage.btnShow(item)
},
lmClose () {
this.$refs.leaveMessage &&
this.$refs.leaveMessage.btnClose()
},
popupClose () {
this.$refs.sidePopup &&
this.$refs.sidePopup.close()
},
updatePage (pager) {
Object.assign(this.pagenation, pager)
this.getList(true)
},
getList (toTop) {
if (this.loading) {
return
}
this.loading = true
requestAPI(api.getContractList, {
data: {
id: this.$route.params.id,
page: this.pagenation.page
}
}).then(res => {
this.result.list = res.list
// this.pagenation.page = res.pagenation.thispage
this.totalcount = res.pagenation.totalcount
// this.totalcount = 8
if (toTop) {
this.$el.querySelector('.page-body-content').scrollTo(0, 0)
}
}).finally(_ => {
this.loading = false
})
}
},
created () {
requestAPI(api.getClient, {
data: {
id: this.$route.params.id
}
}).then(res => {
Object.keys(res.model).forEach(item => {
this.$set(this.model, item, res.model[item])
})
this.getList()
}, error => {
if (Array.isArray(error.msg)) {
error.msg.forEach(item => {
this.$notify.error({
title: '错误',
message: item.error
})
})
}
})
}
}
</script>
<style scoped lang="scss">
@include c('schedule-right') {
> .el-row {
> .el-col {
margin-bottom: 4px;
.el-button {
margin: 0 2px;
padding: 7px;
}
.date-time {
color: #649FD7;
}
}
}
.badge {
border-radius: 2px;
color: #333744;
background: #ffffff;
vertical-align: baseline;
display: inline;
padding: 2px 6px;
}
span.badge-unread {
&:hover {
border-color: #de321d
}
color: #fff;
background-color: #e54c3a;
border-color: #a32516
}
}
</style>
......@@ -32,7 +32,7 @@
methods: {
saveContract () {
let form = this.$refs.operationContract.getForm()
let subData = setModule(form.SalesContracts, 'SalesContracts')
let subData = setModule(form.PurchaseContracts, 'PurchaseContracts')
requestAPI(api.saveContractAdd, {
data: {...subData}
}).then(res => {
......
......@@ -33,7 +33,8 @@
methods: {
saveContract () {
let form = this.$refs.operationContract.getForm()
let subData = setModule(form.SalesContracts, 'SalesContracts')
console.log(form)
let subData = setModule(form.PurchaseContracts, 'PurchaseContracts')
requestAPI(api.saveContractEdit, {
data: {
...subData
......
......@@ -19,7 +19,7 @@
<template slot-scope="scope">
<a @click="toView(scope.row.client_id)" v-if="scope.row.toView">{{scope.row.value}}
</a>
<span :class="setClass(scope.row)" v-else>{{scope.row.value}}</span>
<span :class="setClass(scope.row)" v-else v-html="scope.row.value"></span>
</template>
</el-table-column>
</el-table>
......@@ -53,21 +53,21 @@
{
title: '未回款金额',
value: '',
key: 'collected',
key: 'uncollected',
style: true,
prepend: '¥'
},
{
title: '未开发票',
title: '未开发票金额',
value: '',
key: 'issued_invoices',
key: 'unissued_invoice',
style: true,
prepend: '¥'
},
{
title: '利润率',
value: '',
key: 'projectStatus.name'
key: 'profit_pct'
},
{
title: '商机类型',
......
......@@ -5,9 +5,9 @@
<el-row :gutter="10">
<el-col :span="24" class="entity-name">
<i class="fa fa-fw fa-star" aria-hidden="true"></i>
<a @click="toView(item)" v-if="Object.keys(item.client).length > 0">&nbsp;{{ item.client.name }}
<a @click="toView(item)" v-if="Object.keys(item.supplier).length > 0">&nbsp;{{ item.supplier.name }}
</a>
<span v-else>客户名称{{noneText}}</span>
<span v-else>供应商{{noneText}}</span>
</el-col>
<el-col :span="12" class="entity-name" v-if="Object.keys(item.createdBy).length > 0">
<img class="user-avatar rounded-circle" :src="item.createdBy.avatar.name">
......@@ -30,36 +30,34 @@
{{item.amount !== '' ? item.amount : noneText}}
</el-col>
<el-col :span="6" :xs="24">
客户经理: {{item.salesRep}}
采购人: {{item.handlerPerson.name}}
</el-col>
<el-col :span="6" :xs="24">
签订日期: <span class="date-time">{{item.signed_at !== '' ? item.signed_at : noneText}}</span>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="6" :xs="24">
客户名称:
<a href="javascript:;" v-if="Object.keys(item.client).length > 0" @click="toView(item)">
{{Object.keys(item.client).length > 0 ? item.client.name : noneText}}
</a>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
项目名称:
<a href="javascript:;" size="mini" @click.prevent.stop="showProject(item.project)" v-if="Object.keys(item.project).length > 0">
<a href="javascript:;" v-if="Object.keys(item.project).length > 0" @click.prevent.stop="showProject(item.project)">
{{Object.keys(item.project).length > 0 ? item.project.name : noneText}}
</a>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
合同类型:
<span class="border border-info text-info rounded px-1"
v-if="item.contract_type !== ''">{{['产品销售', '运维服务'][parseInt(item.contract_type) - 1]}}</span>
<span v-else>{{noneText}}</span>
<span class="border border-info text-info rounded px-1">{{item.contract_type_display}}</span>
</el-col>
<el-col :span="6" :xs="24">
上传合同:
<a :href="getScanUrl(item, 'contractScan')" target="_blank" v-if="Object.keys(item.contractScan).length > 0">
<i class="fa fa-fw fa-file-pdf-o"></i>
</a>
<span v-else class="text-danger">扫描件待上传</span>
</el-col>
<el-col :span="6" :xs="24">
上传签收单:
<a :href="getScanUrl(item, 'receiptScan')" target="_blank" v-if="Object.keys(item.receiptScan).length > 0">
<i class="fa fa-fw fa-file-image-o"></i>
</a>
<span v-else class="text-danger">扫描件待上传</span>
......@@ -67,22 +65,21 @@
</el-row>
<el-row :gutter="10">
<el-col :span="6" :xs="24">
<span class="border border-danger text-danger rounded px-1">服务截止日期</span> :
{{item.expire_date !== '' ? item.expire_date : noneText}}
</el-col>
<el-col :span="6" :xs="24">
<span class="border border-danger text-danger rounded px-1">下次巡检日期</span> :
{{item.remind_date !== '' ? item.remind_date : noneText}}
签订日期:
{{item.signed_at !== '' ? item.signed_at : noneText}}
</el-col>
<el-col :span="6" :xs="24">
<span class="border border-danger text-danger rounded px-1">SLA</span> :
{{item.sla !== '' ? item.sla : noneText}}
客户经理 :
<span v-if="Object.keys(item.client).length > 0 && Object.keys(item.client.salesRep).length > 0">
{{item.client.salesRep.name}}
</span>
<span v-else>{{noneText}}</span>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12" :xs="24">
<span class="border border-danger text-danger rounded px-1">备注</span> :
{{item.description !== '' ? item.description : noneText}}
<span v-html="setDesc(item.description)"></span>
</el-col>
<el-col :span="12" :xs="24">
<slot name="opearate">
......@@ -107,6 +104,12 @@
}
},
methods: {
setDesc (desc) {
if (desc !== '') {
return desc.replace(/\n/g, '<br />')
}
return this.noneText
},
showProject (project) {
this.$emit('update:showProject', project)
},
......
......@@ -17,7 +17,7 @@
return [
{
title: '产品信息',
routerName: 'productList',
routerName: 'product',
appName: 'products'
},
{
......
......@@ -181,7 +181,12 @@
requestAPI(api.getProductEdit, {
data: {id}
}).then(res => {
console.log(res)
Object.keys(res.options).forEach(key => {
this.$set(this.options, key, res.options[key])
})
Object.keys(this.Products).forEach(item => {
this.Products[item] = res.model[item]
})
})
}
},
......
......@@ -26,7 +26,7 @@
label="产品分类">
<template slot="header" slot-scope="scope">
<div style="line-height: 18px;">产品分类</div>
<el-select v-model="form['ProductComponents[product_type]']" placeholder="请选择" size="mini">
<el-select clearable v-model="form['ProductComponents[product_type]']" placeholder="请选择" size="mini">
<el-option
v-for="item in productType"
:key="item.id"
......
<template>
<div>
<el-row class="form-content">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-row class="form-content">
<el-col :span="4" v-for="(item, key) in filter" :key="key">
<el-form-item>
<span slot="label" v-if="item.key !== 'Filter[sort]'">
......@@ -26,8 +27,9 @@
</el-select>
</el-form-item>
</el-col>
</el-form>
</el-row>
</el-row>
</el-form>
</div>
</template>
......@@ -119,7 +121,7 @@
border-color: #DCDFE6 !important;
}
.form-content-time-top .el-form-item .el-form-item__content .form-content-time-range{
.form-content-time-top .el-form-item .el-form-item__content .form-content-time-range {
display: flex;
font-size: 12px;
}
......
......@@ -20,7 +20,7 @@
label="产品分类">
<template slot="header" slot-scope="scope">
<div style="line-height: 18px;">产品分类</div>
<el-select v-model="form.productType" placeholder="请选择" size="mini">
<el-select v-model="form.productType" clearable placeholder="请选择" size="mini" @change="updateProduceType">
<el-option
v-for="item in productType"
:key="item.id"
......@@ -37,7 +37,7 @@
label="产品类别">
<template slot="header" slot-scope="scope">
<div style="line-height: 18px;">产品类别</div>
<el-select v-model="form.productComponent" placeholder="请选择" size="mini">
<el-select clearable v-model="form.productComponent" placeholder="请选择" size="mini" @change="updateProductComponent">
<el-option
v-for="item in productComponent"
:key="item.id"
......@@ -54,7 +54,7 @@
label="产品品牌">
<template slot="header" slot-scope="scope">
<div style="line-height: 18px;">产品品牌</div>
<el-select v-model="form.productBrand" placeholder="请选择" size="mini">
<el-select clearable v-model="form.productBrand" placeholder="请选择" size="mini" @change="updateProductBrand">
<el-option
v-for="item in productBrand"
:key="item.id"
......@@ -95,6 +95,15 @@
}
},
methods: {
updateProduceType () {
this.$emit('update:form', {productType: this.form.productType})
},
updateProductComponent () {
this.$emit('update:form', {productComponent: this.form.productComponent})
},
updateProductBrand () {
this.$emit('update:form', {productBrand: this.form.productBrand})
},
tableRowClassName ({row, rowIndex}) {
if (rowIndex % 2 === 0) {
return 'stripe-class'
......@@ -109,15 +118,7 @@
})
}
},
props: ['tableList', 'productComponent', 'productType', 'productBrand', 'loading'],
watch: {
form: {
handler (val) {
this.$emit('update:form', val)
},
deep: true
}
}
props: ['tableList', 'productComponent', 'productType', 'productBrand', 'loading']
}
</script>
......
......@@ -87,7 +87,8 @@
productType: [],
productBrand: [],
productComponent: [],
subForm: {}
subForm: {},
formKey: 'ProductSeries'
}
},
components: {
......@@ -122,19 +123,24 @@
})
},
updateForm (form) {
if (form.productType !== '' && form.productType !== this.subForm.productType) {
if (form.productType) {
requestAPI(api.getProductComponent, {
data: {
product_type: form.productType
}
}).then(res => {
this.$refs.productSerieTable.resetComponent()
this.productComponent = []
// this.productComponent = []
this.productComponent = res
})
} else {
this.productComponent = []
}
this.subForm = Object.assign({}, this.form, form)
console.log(this.subForm)
let subData = {}
Object.keys(form).forEach(item => {
subData[this.formKey + '[' + item + ']'] = form[item]
})
this.subForm = Object.assign({}, this.form, this.subForm, subData)
this.getList()
},
searchKeyword (search) {
......
......@@ -25,16 +25,20 @@
<el-row :gutter="10">
<el-col :span="6" :xs="24">
产品分类:
<span class="border border-danger text-danger rounded px-1">{{item.productType.name}}</span>
<span class="border border-danger text-danger rounded px-1" v-if="Object.keys(item.productType).length > 0">{{item.productType.name}}</span>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
类别: <span class="border border-danger text-danger rounded px-1">{{item.productComponent.name}}</span>
类别: <span class="border border-danger text-danger rounded px-1" v-if="Object.keys(item.productComponent).length > 0">{{item.productComponent.name}}</span>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
系列: <span class="border border-danger text-danger rounded px-1">{{item.productSerie.name}}</span>
系列: <span class="border border-danger text-danger rounded px-1" v-if="Object.keys(item.productSerie).length > 0">{{item.productSerie.name}}</span>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
自定义: <span class="border border-danger text-danger rounded px-1">{{item.productMisc.name}}</span>
自定义: <span class="border border-danger text-danger rounded px-1" v-if="Object.keys(item.productMisc).length > 0">{{item.productMisc.name}}</span>
<span v-else>{{noneText}}</span>
</el-col>
</el-row>
<el-row :gutter="10">
......
......@@ -4,7 +4,7 @@
<el-form-item :show-message="false" :error="errorData['client_id'] ? errorData['client_id'] : ''">
<single-search-input
:required="true"
api="searchSupplierByName"
api="searchClientByName"
:form-serch-item="Projects.client_id"
:form-show-text="searchText"
label="客户名称"
......
<template>
<div>
<el-row class="form-content-time-top">
<el-form ref="clientTimeForm" :model="clientTimeForm" size="mini">
<el-col :span="8" :xs="24">
<div :style="setFormStyle()">
<el-row class="form-content-time-top form-content">
<el-col :span="8" :xs="24">
<el-form ref="clientTimeForm" :model="clientTimeForm" size="mini">
<el-form-item label="成交日期:" label-width="42">
<el-radio-group v-model="clientTimeForm[formSearchKey + '[period]']" size="mini">
<el-radio-button label="thisweek">本周</el-radio-button>
......@@ -12,33 +12,35 @@
<el-radio-button label="nextmonth">下月</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-form>
<el-form ref="clientTimeRange" :model="clientTimeRange" size="mini">
<el-col :span="8" :offset="8" :xs="{span: 24, offset: 0}" class="form-content-time-range">
</el-form>
</el-col>
<el-col :span="8" :offset="8" :xs="{span: 24, offset: 0}">
<el-form ref="clientTimeRange" :model="clientTimeRange" size="mini">
<el-form-item label-width="0" class="pull-right">
<el-date-picker
size="mini"
v-model="clientTimeRange.from"
type="date"
value-format="yyyy-MM-dd"
placeholder="开始时间">
</el-date-picker>
<el-date-picker
size="mini"
v-model="clientTimeRange.to"
type="date"
value-format="yyyy-MM-dd"
placeholder="结束时间">
</el-date-picker>
<el-button type="primary" size="mini" @click="setSearchTime">确定</el-button>
<div class="form-content-time-range">
<el-date-picker
size="mini"
v-model="clientTimeRange.from"
type="date"
value-format="yyyy-MM-dd"
placeholder="开始时间">
</el-date-picker>
<el-date-picker
size="mini"
v-model="clientTimeRange.to"
type="date"
value-format="yyyy-MM-dd"
placeholder="结束时间">
</el-date-picker>
<el-button type="primary" size="mini" @click="setSearchTime">确定</el-button>
</div>
</el-form-item>
</el-col>
</el-form>
</el-form>
</el-col>
</el-row>
<el-row class="form-content">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-row class="form-content">
<el-col :span="4" v-for="(item, key) in filter" :key="key">
<el-form-item>
<span slot="label" v-if="item.key !== 'Filter[sort]'">
......@@ -73,8 +75,8 @@
></el-cascader>
</el-form-item>
</el-col>
</el-form>
</el-row>
</el-row>
</el-form>
</div>
</template>
......@@ -102,6 +104,18 @@
},
props: ['filter', 'formSearchKey'],
methods: {
setFormStyle () {
if (navigator.appVersion.indexOf('MSIE') !== -1) {
let len = this.filter.length
if (len > 5) {
return {minHeight: '185px'}
} else if (len > 10) {
return {minHeight: '225px'}
} else {
return {minHeight: '110px'}
}
}
},
setCascader (item, key) {
if (item.cascader.length === 1) {
this.clientForm[item.key] = item.cascader[0]
......@@ -268,8 +282,10 @@
.form-content-time-top .el-radio-button__inner:hover {
border-color: #DCDFE6 !important;
}
.form-content-time-top .form-content-time-range .el-form-item .el-form-item__content{
.form-content-time-top .el-form-item .el-form-item__content .form-content-time-range {
display: flex;
font-size: 12px;
}
</style>
......@@ -39,7 +39,7 @@
label="职位">
<template slot="header" slot-scope="scope">
<div>职位</div>
<el-select v-model="departmentPosition" size="mini" placeholder="请选择">
<el-select v-model="departmentPosition" clearable size="mini" placeholder="请选择">
<el-option
v-for="item in departmentPositionData"
:key="item.key"
......
......@@ -18,7 +18,7 @@
width="200">
<template slot="header" slot-scope="scope">
<div>部门</div>
<el-select v-model="department" size="mini" placeholder="请选择">
<el-select clearable v-model="department" size="mini" placeholder="请选择">
<el-option
v-for="item in departmentData"
:key="item.key"
......@@ -38,7 +38,7 @@
width="200">
<template slot="header" slot-scope="scope">
<div>职位</div>
<el-select v-model="departmentPosition" size="mini" placeholder="请选择">
<el-select clearable v-model="departmentPosition" size="mini" placeholder="请选择">
<el-option
v-for="item in departmentPositionData"
:key="item.key"
......
......@@ -6,6 +6,7 @@
:form-serch-item="SalesOrders.client_id"
:form-show-text="searchText"
:set-option="setClientOption"
:required="true"
api="searchClientByName"
label="客户名称"
:single-search-disabled="singleSearchDisabled"
......
<template>
<div>
<el-row class="form-content">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-row class="form-content">
<el-col :span="4" v-for="(item, key) in filter" :key="key">
<el-form-item>
<span slot="label" v-if="item.key !== 'Filter[sort]'">
......@@ -36,8 +36,8 @@
></el-cascader>
</el-form-item>
</el-col>
</el-form>
</el-row>
</el-row>
</el-form>
</div>
</template>
......@@ -228,7 +228,8 @@
.form-content-time-top .el-radio-button__inner:hover {
border-color: #DCDFE6 !important;
}
.form-content-time-top .form-content-time-range .el-form-item .el-form-item__content{
.form-content-time-top .form-content-time-range .el-form-item .el-form-item__content {
display: flex;
font-size: 12px;
}
......
......@@ -219,17 +219,6 @@
setError (error) {
return this.errorData[error] ? this.errorData[error] : ''
},
querySearchAsync (queryString, cb) {
requestAPI(api.searchSupplierByName, {
data: {
name: queryString
}
}).then(res => {
cb(res.map(i => {
return {value: i.name, key: i.key}
}))
})
},
handleSelect (item, row) {
row.supplier_id = item.key.toString()
},
......
<template>
<div :style="setFormStyle()">
<el-row class="form-content-time-top form-content">
<el-col :span="8" :xs="{span: 24, offset: 0}">
<el-form ref="clientTimeRange" :model="clientTimeRange" size="mini" label-position="top">
<el-form-item label="签订日期">
<div class="form-content-time-range">
<el-date-picker
size="mini"
v-model="clientTimeRange.from"
type="date"
value-format="yyyy-MM-dd"
placeholder="开始时间">
</el-date-picker>
<el-date-picker
size="mini"
v-model="clientTimeRange.to"
type="date"
value-format="yyyy-MM-dd"
placeholder="结束时间">
</el-date-picker>
<el-button type="primary" size="mini" @click="setSearchTime">确定</el-button>
</div>
</el-form-item>
</el-form>
</el-col>
<el-form size="mini" :model="clientForm" label-width="0" label-position="top">
<el-col :span="4" v-for="(item, key) in filter" :key="key">
<el-form-item>
<span slot="label" v-if="item.key !== 'Filter[sort]'">
<a @click.prevent="timeSort" v-if="item.key === 'Filter[name]'">
{{item.name}}
<i :class="['fa', setSortIcon()]"></i>
</a>
<span v-else>
{{item.name}}
</span>
</span>
<el-select clearable
v-model="clientForm[item.key]"
placeholder="请选择"
v-if="!item.itemKey && item.key !== 'Filter[sort]'" size="mini">
<el-option v-for="(option, optKey) in item.value"
:key="optKey"
:label="option.name"
:value="option.key">
<span style="font-size: 12px;">{{option.name}}</span>
</el-option>
</el-select>
<el-cascader
:ref="'elCasc' + key"
v-model="item.cascader"
:props="props"
clearable
change-on-select
v-if="item.itemKey"
:options="item.value"
@change="setCascader(item, key)"
></el-cascader>
</el-form-item>
</el-col>
</el-form>
</el-row>
</div>
</template>
<script>
import {findWhere} from '../../lib/viewHelper'
import $ from 'jquery'
const timeItem = ['period']
export default {
name: 'client-form',
data () {
return {
clientTimeForm: {},
clientTimeRange: {
from: '',
to: ''
},
clientForm: {},
props: {
label: 'name',
value: 'key',
children: 'child'
}
}
},
props: ['filter', 'formSearchKey'],
methods: {
setFormStyle () {
if (navigator.appVersion.indexOf('MSIE') !== -1) {
let len = this.filter.length
if (len > 3) {
return {minHeight: '125px'}
} else if (len > 10) {
return {minHeight: '165px'}
} else {
return {minHeight: '110px'}
}
}
},
setCascader (item, key) {
if (item.cascader.length === 1) {
this.clientForm[item.key] = item.cascader[0]
this.clientForm[item.itemKey] = ''
} else if (item.cascader.length === 2) {
this.clientForm[item.itemKey] = item.cascader[0]
this.clientForm[item.key] = item.cascader[1]
} else {
this.clientForm[item.itemKey] = ''
this.clientForm[item.key] = ''
}
},
setDefault (filter) {
filter.forEach(item => {
if (item.default) {
let keys = findWhere(item.value, item.default, 'key')
if (keys.node) {
if (keys.parentNode) {
this.clientForm[item.itemKey] = keys.parentNode.key
this.clientForm[item.key] = keys.node.key
item.cascader = [keys.parentNode.key, keys.node.key]
} else {
this.clientForm[item.itemKey] = ''
this.clientForm[item.key] = keys.node.key
item.cascader = [keys.node.key]
}
}
}
})
},
init (isCascader) {
this.$watch('clientForm', (val) => {
this.$emit('update:clientList', Object.assign({}, val, this.clientTimeForm))
}, {deep: true})
this.$watch('clientTimeForm', (val) => {
let perid = val[this.formSearchKey + '[period]']
this.$emit('update:clientList', Object.assign({}, {[this.formSearchKey + '[period]']: perid}, this.clientForm))
}, {deep: true})
let _this = this
if (isCascader) {
$(document).ready(() => {
$(document).on('mouseleave', '.el-cascader-menus', () => {
Object.keys(_this.$refs).forEach(item => {
_this.$refs[item][0].menuVisible = false
})
})
})
}
},
setSortIcon () {
if (this.clientForm['Filter[sort]'] === '') {
return 'fa-sort-amount-desc'
} else if (this.clientForm['Filter[sort]'] === 'DESC') {
return 'fa-sort-amount-desc'
} else {
return 'fa-sort-amount-asc'
}
},
timeSort () {
if (this.clientForm['Filter[sort]'] === '') {
this.clientForm['Filter[sort]'] = 'ASC'
} else if (this.clientForm['Filter[sort]'] === 'ASC') {
this.clientForm['Filter[sort]'] = 'DESC'
} else {
this.clientForm['Filter[sort]'] = 'ASC'
}
},
setSearchTime () {
let from = this.clientTimeRange.from
let to = this.clientTimeRange.to
this.$emit('update:clientList', Object.assign({}, {
[this.formSearchKey + '[from]']: from,
[this.formSearchKey + '[to]']: to
}, this.clientTimeForm, this.clientForm))
},
resetForm () {
Object.keys(this.clientForm).forEach(item => {
this.clientForm[item] = ''
})
Object.keys(this.clientTimeRange).forEach(item => {
this.clientTimeRange[item] = ''
})
}
},
mounted () {
},
watch: {
'clientTimeRange.from' (val) {
if (new Date(val) >= new Date(this.clientTimeRange.to)) {
this.clientTimeRange.to = val
}
if (this.clientTimeRange.to === '') {
this.clientTimeRange.to = val
}
},
'clientTimeRange.to' (val) {
if (new Date(val) <= new Date(this.clientTimeRange.from)) {
this.clientTimeRange.from = val
}
if (this.clientTimeRange.from === '') {
this.clientTimeRange.from = val
}
},
'filter' (val) {
let isCascader = false
val.forEach(item => {
if (item.itemKey) {
this.$set(this.clientForm, item.itemKey, '')
this.$set(item, 'cascader', [])
isCascader = true
}
this.$set(this.clientForm, item.key, '')
})
this.$nextTick(() => {
this.init(isCascader)
this.setDefault(val)
})
},
'formSearchKey': {
handler (val) {
if (val !== '') {
timeItem.forEach(item => {
this.$set(this.clientTimeForm, val + '[' + item + ']', '')
})
}
},
immediate: true
}
}
}
</script>
<style scoped>
.form-content-time-top {
background: #FFF;
}
.form-content-time-top .el-form-item {
margin: 7px 0 9px;
}
.form-content-time-top .el-col {
padding: 0 15px;
}
</style>
<style>
.form-content .el-form-item__label {
font-size: 12px;
font-weight: normal;
padding: 0 2px 0 0;
}
.form-content-time-top .el-radio-button__orig-radio:checked + .el-radio-button__inner {
color: #fff !important;
background-color: #333744 !important;
border-color: #282b35 !important;
box-shadow: -1px 0 0 0 #282b35;
}
.form-content-time-top .el-radio-button:first-child .el-radio-button__inner {
border-left: 1px solid #DCDFE6;
}
.form-content-time-top .el-radio-button__inner:hover {
border-color: #DCDFE6 !important;
}
.form-content-time-top .el-form-item .el-form-item__content .form-content-time-range {
display: flex;
font-size: 12px;
}
</style>
<style>
.sales-contract {
height: 125px;
}
</style>
......@@ -193,7 +193,7 @@
return
}
this.loading = true
requestAPI(api.getContractList, {
requestAPI(api.getSalesContractList, {
data: {
id: this.$route.params.id,
page: this.pagenation.page
......
This diff is collapsed.
<template>
<section>
<operation-contract
ref="operationContract"
type="add"
:error-data="errorData">
<span slot="operationBtn">
<el-button type="primary" @click="saveContract" size="mini">保存</el-button>
<el-button @click="close()" size="mini">关闭</el-button>
</span>
</operation-contract>
</section>
</template>
<script>
import {
requestAPI,
api
} from '@/lib/commonMixin'
import operationContract from './operationContract'
import {setModule} from '../../../lib/viewHelper'
export default {
name: '',
components: {
operationContract
},
data () {
return {
errorData: {}
}
},
methods: {
saveContract () {
let form = this.$refs.operationContract.getForm()
let subData = setModule(form.SalesContracts, 'SalesContracts')
requestAPI(api.saveSalesContractAdd, {
data: {...subData}
}).then(res => {
this.$message({
message: '保存成功!',
type: 'success'
})
this.close(true)
}, error => {
error.msg.forEach(item => {
this.$set(this.errorData, item.name, item.error)
})
})
},
close (getList) {
this.$emit('close', getList)
},
init () {
this.$refs.operationContract.initAdd()
}
},
created () {
}
}
</script>
<style scoped>
</style>
<template>
<section>
<operation-contract
ref="operationContract"
type="edit"
:error-data="errorData">
<span slot="operationBtn">
<el-button type="primary" @click="saveContract" size="mini">保存</el-button>
<el-button @click="close()" size="mini">关闭</el-button>
</span>
</operation-contract>
</section>
</template>
<script>
import {
requestAPI,
api
} from '@/lib/commonMixin'
import operationContract from './operationContract'
import {setModule} from '../../../lib/viewHelper'
export default {
name: '',
components: {
operationContract
},
data () {
return {
errorData: {}
}
},
methods: {
saveContract () {
let form = this.$refs.operationContract.getForm()
let subData = setModule(form.SalesContracts, 'SalesContracts')
requestAPI(api.saveSalesContractEdit, {
data: {
...subData
}
}).then(res => {
this.$message({
message: '保存成功!',
type: 'success'
})
this.close(true)
}, error => {
error.msg.forEach(item => {
this.$set(this.errorData, item.name, item.error)
})
})
},
close (getList) {
this.$emit('close', getList)
},
init (id) {
this.$refs.operationContract.initEdit(id)
}
},
created () {
}
}
</script>
<style scoped>
</style>
This diff is collapsed.
<template>
<section class="view-project">
<el-table
:data="tableData"
border
stripe
style="width: 100%"
:show-header="false">
<el-table-column
prop="title"
min-width="25%">
<template slot-scope="scope">
<b>{{scope.row.title}}</b>
</template>
</el-table-column>
<el-table-column
prop="value"
min-width="75%">
<template slot-scope="scope">
<a @click="toView(scope.row.client_id)" v-if="scope.row.toView">{{scope.row.value}}
</a>
<span :class="setClass(scope.row)" v-else v-html="scope.row.value"></span>
</template>
</el-table-column>
</el-table>
</section>
</template>
<script>
export default {
name: '',
data () {
return {
tableData: [
{
title: '客户名称',
value: '',
key: 'client.name',
toView: true,
client_id: ''
},
{
title: '项目名称',
value: '',
key: 'project_title'
},
{
title: '商机金额',
value: '',
key: 'budget',
prepend: '¥'
},
{
title: '未回款金额',
value: '',
key: 'uncollected',
style: true,
prepend: '¥'
},
{
title: '未开发票金额',
value: '',
key: 'unissued_invoice',
style: true,
prepend: '¥'
},
{
title: '利润率',
value: '',
key: 'profit_pct'
},
{
title: '商机类型',
value: '',
key: 'projectTags'
},
{
title: '商机状态',
value: '',
key: 'projectStatus.name'
},
{
title: '销售阶段',
value: '',
key: 'projectProgress.name'
},
{
title: '销售预测',
value: '',
key: 'salesForecast.name'
},
{
title: '合同类型',
value: '',
key: 'contract_type_display'
},
{
title: '采购方式',
value: '',
key: 'purchaseType.name'
},
{
title: '商机来源',
value: '',
key: 'opportunityFrom.name'
},
{
title: '阶段停留',
value: '',
key: 'remain_display'
},
{
title: '成交日期',
value: '',
key: 'bargain_date'
},
{
title: '客户经理',
value: '',
key: 'salesRep.name'
},
{
title: '售前支持',
value: '',
key: 'projectArchitects',
type: 'array'
},
{
title: '商机内容',
value: '',
key: 'description'
},
{
title: '商机批注',
value: '',
key: 'comment',
type: 'html'
},
{
title: '更新时间',
value: '',
key: 'updated_at'
}
]
}
},
methods: {
init (data) {
this.setTableData(data.model)
},
setClass (row) {
if (row.style) {
if (parseInt(row.value.split('¥')[1]) > 0) {
return ['text-danger']
}
}
},
setTableData (model) {
this.tableData.forEach(item => {
// console.log(this.getObjByPath(model, item.key, {}), item.title)
let val = this.getObjByPath(model, item.key, {prepend: item.prepend})
// console.log(val, item.title, item.key)
if (val.indexOf('undefined') === -1) {
item.value = val
} else {
item.value = '(未设置)'
}
if (item.type === 'array') {
if (model[item.key].length > 0) {
item.value = model[item.key].map(i => i.name + i.value * 100 + '%').join(' ')
} else {
item.value = '(未设置)'
}
}
if (item.toView) {
item.client_id = model.client_id
}
})
// console.log(this.tableData)
},
getObjByPath (obj, path, option) {
let names = path.split('.')
let firstName = names.shift()
let member = obj[firstName]
let prepend = option.prepend ? option.prepend : ''
let append = option.append ? option.append : ''
if (Array.isArray(member)) {
return prepend + member.map(i => i.name).join(',') + append
}
if (member && names.length) {
return this.getObjByPath(member, names.join('.'), option)
}
return prepend + member + append
},
toView (id) {
this.$router.push({
app: 'client',
name: 'viewClient',
params: {
id
}
})
// console.log(obj)
}
},
created () {
}
}
</script>
<style>
.view-project .el-table td, .view-project .el-table th{
padding: 4px 0;
font-size: 12.25px;
}
</style>
<template>
<section class="client-schedule-item">
<el-row class="client-schedule-row">
<el-col :span="4" :xs="24" class="client-schedule-left" :style="{'background-color': item.bgcolor}">
<el-row :gutter="10">
<el-col :span="24" class="entity-name">
<i class="fa fa-fw fa-star" aria-hidden="true"></i>
<a @click="toView(item)" v-if="Object.keys(item.client).length > 0">&nbsp;{{ item.client.name }}
</a>
<span v-else>客户名称{{noneText}}</span>
</el-col>
<el-col :span="12" class="entity-name" v-if="Object.keys(item.createdBy).length > 0">
<img class="user-avatar rounded-circle" :src="item.createdBy.avatar.name">
<span class="black">{{ item.createdBy.name }}</span>
</el-col>
<el-col :span="12" v-else><i class="fa fa-fw fa-user"></i> {{noneText}}
</el-col>
</el-row>
</el-col>
<el-col :span="20" :xs="24" class="client-schedule-right">
<el-row :gutter="10">
<el-col :span="6" :xs="24" class="show-picture">
合同编号:
<span>
{{item.serial_no !== '' ? item.serial_no : noneText}}
</span>
</el-col>
<el-col :span="6" :xs="24">
<span class="border border-info text-info rounded px-1">总额</span> :
{{item.amount !== '' ? item.amount : noneText}}
</el-col>
<el-col :span="6" :xs="24">
客户经理: {{item.salesRep}}
</el-col>
<el-col :span="6" :xs="24">
签订日期: <span class="date-time">{{item.signed_at !== '' ? item.signed_at : noneText}}</span>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="6" :xs="24">
项目名称:
<a href="javascript:;" size="mini" @click.prevent.stop="showProject(item.project)" v-if="Object.keys(item.project).length > 0">
{{Object.keys(item.project).length > 0 ? item.project.name : noneText}}
</a>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
合同类型:
<span class="border border-info text-info rounded px-1"
v-if="item.contract_type !== ''">{{['产品销售', '运维服务'][parseInt(item.contract_type) - 1]}}</span>
<span v-else>{{noneText}}</span>
</el-col>
<el-col :span="6" :xs="24">
上传合同:
<a :href="getScanUrl(item, 'contractScan')" target="_blank" v-if="Object.keys(item.contractScan).length > 0">
<i class="fa fa-fw fa-file-pdf-o"></i>
</a>
<span v-else class="text-danger">扫描件待上传</span>
</el-col>
<el-col :span="6" :xs="24">
上传签收单:
<a :href="getScanUrl(item, 'receiptScan')" target="_blank" v-if="Object.keys(item.receiptScan).length > 0">
<i class="fa fa-fw fa-file-image-o"></i>
</a>
<span v-else class="text-danger">扫描件待上传</span>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="6" :xs="24">
<span class="border border-danger text-danger rounded px-1">服务截止日期</span> :
{{item.expire_date !== '' ? item.expire_date : noneText}}
</el-col>
<el-col :span="6" :xs="24">
<span class="border border-danger text-danger rounded px-1">下次巡检日期</span> :
{{item.remind_date !== '' ? item.remind_date : noneText}}
</el-col>
<el-col :span="6" :xs="24">
<span class="border border-danger text-danger rounded px-1">SLA</span> :
{{item.sla !== '' ? item.sla : noneText}}
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="12" :xs="24">
<span class="border border-danger text-danger rounded px-1">备注</span> :
{{item.description !== '' ? item.description : noneText}}
</el-col>
<el-col :span="12" :xs="24">
<slot name="opearate">
</slot>
</el-col>
</el-row>
</el-col>
</el-row>
</section>
</template>
<script>
export default {
name: 'scheduleItem',
props: {
item: Object
},
data () {
return {
noneText: '(未设置)'
}
},
methods: {
showProject (project) {
this.$emit('update:showProject', project)
},
splitFileName (text) {
var pattern = /\.{1}[a-z]{1,}$/
if (pattern.exec(text) !== null) {
return (text.slice(0, pattern.exec(text).index))
} else {
return text
}
},
getScanUrl (item, key) {
let names = item[key].name.split('/')
let name = names[names.length - 1]
return '/attachment/view?name=' + this.splitFileName(name)
},
setBr (text) {
if (text === '') {
return this.noneText
} else {
return text.replace(/\n/g, '<br />')
}
},
toView (item) {
this.$router.push({
app: 'client',
name: 'viewClient',
params: {
id: item.client_id
}
})
},
toDetailView (item) {
this.$router.push({
app: 'salesOrders',
name: 'salesOrderView',
params: {
id: item.id
}
})
}
},
computed: {
isNullClient () {
return !this.item.client
},
isPublic () {
return !!this.item.is_public
}
},
mounted () {
}
}
</script>
<style scoped lang="scss">
.text-info {
color: #17a2b8 !important;
}
.border-info {
border-color: #17a2b8 !important;
}
.colRed {
color: red;
border: 1px solid red;
}
.colGreen {
color: green;
border: 1px solid green;
}
.colRed, .colGreen, .col {
border-radius: .25rem;
padding: 0 .25rem;
}
.rounded-circle {
border-radius: 50% !important;
}
.user-avatar {
width: 16px;
max-width: 16px;
height: 16px;
max-height: 16px;
}
@include c('schedule-item') {
margin-bottom: 10px;
font-size: 12px;
.border {
border: 1px solid #dee2e6;
}
.border-success {
border-color: #28a745 !important;
}
.border-danger {
border-color: #dc3545;
}
.text-success {
color: #28a745 !important;
}
.text-danger {
color: #E45744;
}
.rounded {
border-radius: .25rem !important;
}
.px-1 {
padding: 0 .25rem;
}
}
@include c('schedule-item:first-child') {
.client-schedule-left {
border-radius: 5px 0 0 0;
}
}
@include c('schedule-row') {
background-color: white;
display: flex;
flex-wrap: wrap;
}
@include c('schedule-left') {
background-color: #FF6A6A;
min-height: 100%;
padding: 10px 15px 6px;
.fa-fw {
width: 1.28571429em;
}
> .el-row {
> .el-col {
margin-bottom: 4px;
}
}
.el-row div:first-child, .el-row div:first-child a, .entity-name, .entity-name a {
color: white;
}
.entity-name .black {
color: #000000;
}
span {
display: inline-block;
padding-left: 3px;
}
span.np {
padding-left: 0;
}
@include e('private') {
display: inline-block;
// border: 1px solid black;
padding-right: 5px;
border-radius: 5px;
width: 40px;
height: 20px;
}
}
@include c('schedule-right') {
height: 100%;
padding: 10px 15px 6px;
> .el-row {
> .el-col {
margin-bottom: 4px;
.el-button {
margin: 0 2px;
padding: 7px;
}
.date-time, .show-picture {
color: #649FD7;
}
.show-picture {
cursor: pointer;
}
}
}
.badge {
border-radius: 2px;
color: #333744;
background: #ffffff;
vertical-align: baseline;
display: inline;
padding: 2px 6px;
text-align: center;
}
span.badge-unread {
&:hover {
border-color: #de321d
}
color: #fff;
background-color: #e54c3a;
border-color: #a32516
}
@include e('item') {
display: flex;
flex-direction: column;
justify-content: space-around;
padding: 5px 0 5px 5px;
flex: 1;
}
@include e('status') {
color: red;
}
@include e('content') {
display: inline-block;
border: 1px solid red;
border-radius: 5px;
height: 20px;
padding: 0 5px 0 5px;
color: red;
}
}
</style>
......@@ -6,6 +6,7 @@ import salesContracts from './routes/salesContracts'
import products from './routes/products'
import address from './routes/addressBook'
import rating from './routes/rating'
import contract from './routes/contract'
let routes = []
let salesRours = []
const appName = 'project'
......@@ -31,6 +32,9 @@ let RouterInit = () => {
portal.createApp('rating', {}, app => {
app.mapRoute(rating)
})
portal.createApp('purchaseContracts', '', app => {
app.mapRoute(contract)
})
}
export default RouterInit
import contractList from '../components/contract/list'
import contractOfClient from '../components/contract/ofClient/contractOfClient'
const projectTitle = '金畅逍BMS - '
const routes = [
{
path: '/contract',
name: 'contractList',
component: contractList,
meta: {
title: projectTitle + '采购合同'
}
},
{
path: '/ofClient/:id',
name: 'ofClient',
component: contractOfClient,
meta: {
title: projectTitle + '采购合同'
}
}
]
export default routes
......@@ -10,7 +10,7 @@ const projectTitle = '金畅逍BMS - '
const routes = [
{
path: '/product',
name: 'productList',
name: 'product',
component: productList,
meta: {
title: projectTitle + '产品信息'
......
......@@ -17,7 +17,7 @@ const routes = [
name: 'ofClient',
component: projectOfClient,
meta: {
title: projectTitle + '客户信息'
title: projectTitle + '商机列表'
}
},
{
......
import contractList from '../components/contract/list'
import contractOfClient from '../components/contract/contractOfClient/contractOfClient'
import contractList from '../components/salesContracts/list'
import contractOfClient from '../components/salesContracts/contractOfClient/contractOfClient'
const projectTitle = '金畅逍BMS - '
const routes = [
{
path: '/salesContract',
name: 'contractList',
name: 'salesContractList',
component: contractList,
meta: {
title: projectTitle + '销售记录'
title: projectTitle + '销售合同'
}
},
{
......@@ -15,7 +15,7 @@ const routes = [
name: 'ofClient',
component: contractOfClient,
meta: {
title: projectTitle + '客户信息'
title: projectTitle + '销售合同'
}
}
]
......
......@@ -13078,6 +13078,9 @@ input[type=file] {
width: calc(100% - 120px);
padding-bottom: 15px;
}
.content > div {
flex-grow: 1;
}
@media only screen and (max-width: 880px) {
.content {
width: 100%;
......@@ -13112,14 +13115,31 @@ input[type=file] {
padding: 15px 15px 0;
}
.page-body-content .text-danger {
color: #dc3545!important;
color: #dc3545 !important;
}
.el-form--label-top .el-form-item__label {
line-height: 1.5!important;
line-height: 1.5 !important;
font-weight: 400;
}
.el-form--label-top .el-form-item__label {
padding: 0!important;
padding: 0 !important;
}
.content .page-body-content .el-button--primary {
color: #343743 !important;
background-color: #fff !important;
border-color: #d6d7d9 !important;
}
.content .page-body-content .el-button--primary:hover {
color: #fff !important;
border-color: #52555f !important;
background-color: #52555f !important;
}
.content .page-body-content .el-button--primary.is-disabled {
color: #C0C4CC !important;
cursor: not-allowed;
background-image: none;
background-color: #FFF !important;
border-color: #EBEEF5 !important;
}
.content .header-search .btn {
display: inline-block;
......@@ -13142,41 +13162,52 @@ input[type=file] {
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
.content .el-button--primary {
color: #343743!important;
background-color: #fff!important;
border-color: #d6d7d9!important;
}
.content .el-button--primary:hover {
color: #fff!important;
border-color: #52555f!important;
background-color: #52555f!important;
}
.content .el-button.is-disabled {
color: #C0C4CC!important;
cursor: not-allowed;
background-image: none;
background-color: #FFF!important;
border-color: #EBEEF5!important;
}
.content .header-search .fa-fw {
color: #333744;
font-size: 28px;
}
.content .search-form {
.content .header-search .el-form-item__content .el-input-group {
vertical-align: 0px;
}
.content .header-search .el-button--primary {
color: #fff;
background-color: #333744;
border-color: #282b35;
border-bottom: 1px solid #333744;
}
.content .header-search .el-button--primary:hover {
color: #fff;
background-color: #1d1f27;
border-color: #0e0f12;
}
.content .header-search .el-button--danger {
color: #fff;
background-color: #EB7567;
border-color: #e86150;
}
.content .header-search .el-button--danger:hover {
color: #fff;
background-color: #e54c3a;
border-color: #de321d;
}
.content .header-search .search-form {
display: flex;
flex-wrap: wrap;
}
.content .search-form .el-form-item--mini.el-form-item {
.content .header-search .search-form .el-form-item--mini.el-form-item {
margin-bottom: 0;
margin-right: 4px;
}
.content .search-form .el-form-item__content > .el-button {
.content .header-search .search-form > .el-button {
margin: 0 2px;
}
.content .search-form .el-form-item__content .el-button--mini {
.content .header-search .search-form .el-button--mini {
padding: 7px;
}
.content .search-form .el-form-item__content .el-input-group__append .el-button--mini {
.content .header-search .search-form .el-input-group__append {
border-color: #333744;
}
.content .header-search .search-form .el-input-group__append .el-button--mini {
border-radius: 0 3px 3px 0;
}
.form-content {
......@@ -13193,6 +13224,17 @@ input[type=file] {
.form-content .el-col .el-cascader {
width: 100%;
}
.form-content .form-content-time-range .el-button--mini {
color: #fff;
background-color: #333744;
border-color: #282b35;
border-bottom: 1px solid #333744;
padding: 7px;
border-radius: 0 3px 3px 0;
}
.form-content .form-content-time-range .el-date-editor:last-of-type {
border-radius: 3px 0 0 3px;
}
/*--------Page Components--------*/
/*#region navbar*/
.navbar {
......@@ -13990,6 +14032,7 @@ input[type=file] {
.navbar .navbar-logo img {
float: left;
height: 40px;
width: auto;
margin-right: 5px;
margin-top: 5px;
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment