Browse Source

Merge branch 'devlop' of http://git.qniao.cn/dengxiongfei/paper-shopkeeper-app into devlop

# Conflicts:
#	pages.json
devlop
杨阁辉 4 years ago
parent
commit
6214b51f4f
14 changed files with 607 additions and 43 deletions
  1. 5
      App.vue
  2. 2
      apis/addUserApi.js
  3. 15
      apis/commonApi.js
  4. 15
      pages.json
  5. 231
      pages/add-record/index.vue
  6. 6
      pages/add-user/index.vue
  7. 11
      pages/client-detail/basic-information.vue
  8. 9
      pages/enterprise-info/index.vue
  9. 177
      pages/follow-up-records/index.vue
  10. 18
      pages/follow-up-records/timeLine.vue
  11. 87
      pages/follow-up-records/timelineItem.vue
  12. 10
      pages/login/index.vue
  13. 4
      pages/mine/index.vue
  14. 60
      utils/hook.js

5
App.vue

@ -16,5 +16,8 @@ export default {
<style> <style>
/*每个页面公共css */ /*每个页面公共css */
@import url('./common/css/reset.scss'); @import url('./common/css/reset.scss');
@import '@/static/icon/iconfont.css';
@import '@/static/icon/iconfont.css';
page {
height: 100%;
}
</style> </style>

2
apis/addUserApi.js

@ -16,7 +16,7 @@ export function getCompanyInfoById(data) {
}) })
} }
// 根据id查询企业详细信息
// 添加客户
export function addCustomer(data) { export function addCustomer(data) {
return http.post({ return http.post({
url: '/yyt-uec/supplier/create/customer', url: '/yyt-uec/supplier/create/customer',

15
apis/commonApi.js

@ -1,4 +1,5 @@
import http from '../utils/http/index.js' import http from '../utils/http/index.js'
import store from '@/store/index'
let areaCache = null let areaCache = null
/** /**
* 获取省市区街道 * 获取省市区街道
@ -22,6 +23,20 @@ export function getArea(data = {}) {
} }
let baseInfo = null let baseInfo = null
// 处理store同步问题
function syncStore(res) {
if (res.enterpriseList && res.enterpriseList.length > 0) {
let supplierInfo = res.enterpriseList[0]
store.commit('setSupplierInfo', {
id: supplierInfo.id,
name: supplierInfo.name,
fddEnterpriseStatus: supplierInfo.fddEnterpriseStatus,
supplierId: supplierInfo.supplier.id
})
store.commit('setUserInfo', { name: supplierInfo.employeeName, userId: res.userId, mobile: res.mobile, avatar: null })
}
}
/** /**
* 获取当前账号的基础信息 * 获取当前账号的基础信息
* @param {object} data 参数,暂时不需要,可以传{} * @param {object} data 参数,暂时不需要,可以传{}

15
pages.json

@ -215,7 +215,20 @@
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
}
},
{
"path": "pages/follow-up-records/index",
"style": {
"navigationBarTitleText": "跟进记录"
}
},
{
"path": "pages/add-record/index",
"style": {
"navigationBarTitleText": "新增跟进记录",
"navigationStyle": "custom"
}
}
,{ ,{
"path" : "pages/paper-detail/index", "path" : "pages/paper-detail/index",
"style" : "style" :

231
pages/add-record/index.vue

@ -0,0 +1,231 @@
<template>
<view class="warpper">
<qnHeader class="header">
<view class="header-title">跟进记录</view>
<view class="right-title">保存</view>
</qnHeader>
<view class="paper-price">
<view class="">
<view class="paper-price-image-title">
<text class="add-paper-start"><uni-icons custom-prefix="iconfont" type="icon-required" size="14" color="#F5222D"></uni-icons></text>
<text class="add-paper-title">拜访对象</text>
</view>
<view class="paper-price-image">
<qn-easyinput
class="paper-price-textArea bf-height"
:maxlength="200"
:styles="{ disableColor: '#F7F8FA' }"
v-model="form.remark"
:inputBorder="false"
type="textarea"
placeholder="请输入拜访对象"
></qn-easyinput>
</view>
</view>
<view class="">
<view class="paper-price-image-title">
<text class="add-paper-start"><uni-icons custom-prefix="iconfont" type="icon-required" size="14" color="#F5222D"></uni-icons></text>
<text class="add-paper-title">沟通记录</text>
</view>
<view class="paper-price-image">
<qn-easyinput
class="paper-price-textArea gt-height"
:maxlength="200"
:styles="{ disableColor: '#F7F8FA' }"
v-model="form.remark"
:inputBorder="false"
type="textarea"
placeholder="请输入与客户的沟通记录"
></qn-easyinput>
</view>
</view>
<view class="">
<view class="paper-price-image-title">
<text class="add-paper-start"><uni-icons custom-prefix="iconfont" type="icon-required" size="14" color="#F5222D"></uni-icons></text>
<text class="add-paper-title">备注信息</text>
</view>
<view class="paper-price-image">
<qn-easyinput
class="paper-price-textArea bf-height"
:maxlength="200"
:styles="{ disableColor: '#F7F8FA' }"
v-model="form.remark"
:inputBorder="false"
type="textarea"
placeholder="请输入备注"
></qn-easyinput>
<view class="location">
<image class="icon" src="/static/imgs/client-detail/address-icon.png"></image>
<text class="text">广州市天河区</text>
<uni-icons size="16" type="bottom"></uni-icons>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import qnHeader from '@/components/qn-header/qn-header.vue'
export default {
components: {qnHeader},
data() {
return {
form: {}
}
}
}
</script>
<style lang="scss" scoped>
.warpper {
background-color: #ffffff;
height: 100%;
.header {
justify-content: space-between;
}
.header-title {
font-size: 36rpx;
color: #000000;
letter-spacing: 0;
text-align: center;
font-weight: 500;
}
.right-title {
font-size: 28rpx;
color: #007aff;
text-align: center;
line-height: 40rpx;
font-weight: 500;
}
.add-paper-start {
font-size: 28rpx;
color: #f5222d;
letter-spacing: 0;
font-weight: 400;
}
.add-paper-title {
font-size: 28rpx;
color: #000000;
letter-spacing: 0;
font-weight: 500;
}
.paper-price {
background-color: #ffffff;
padding: 20rpx 0rpx;
.paper-price-form {
background: #f7f8fa;
border-radius: 8rpx;
margin: 22rpx 32rpx;
padding: 22rpx 32rpx;
line-height: 60rpx;
margin-bottom: 30rpx;
}
.paper-price-item {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.flex {
display: flex;
margin-left: 4px;
align-items: center;
}
}
.delete-text {
font-size: 28rpx;
color: #f5222d;
letter-spacing: 0;
font-weight: 400;
}
.paper-price-main {
padding: 22rpx 32rpx;
height: 88rpx;
align-items: center;
border-bottom: 2rpx solid #dddddd;
}
.paper-price-image-title {
padding: 0rpx 32rpx;
align-items: center;
}
.paper-price-image {
padding: 16rpx 32rpx;
}
.paper-price-textArea {
background: #f7f8fa;
border-radius: 20rpx;
padding: 10rpx;
}
.paper-price-title {
font-size: 28rpx;
color: #000000;
letter-spacing: 0;
font-weight: 600;
}
.paper-price-subtitle {
font-size: 24rpx;
color: #888888;
font-weight: 400;
}
.dian {
background: #adbac9;
width: 10rpx;
height: 10rpx;
border-radius: 50%;
// margin-top: 28rpx;
margin-right: 10rpx;
}
.label_text {
font-size: 28rpx;
color: #888888;
letter-spacing: 0;
font-weight: 400;
}
.label_value {
padding-bottom: 5rpx;
border-bottom: 2rpx solid #d8d8d8;
width: 65%;
text-align: right;
}
.label-select {
display: flex;
align-items: center;
justify-content: flex-end;
}
.text-left {
margin-left: 10rpx;
}
.text-right {
margin-right: 10rpx;
}
}
.bf-height{
height: 155rpx;
}
.gt-height {
height: 210rpx;
}
.location{
display: flex;
flex-direction: row;
align-items: center;
padding-top: 20rpx;
.icon {
width: 32rpx;
height: 32rpx;
}
.text{
font-size: 26rpx;
color: #888888;
letter-spacing: 0;
text-align: left;
font-weight: 400;
padding-left: 10rpx;
}
}
}
</style>

6
pages/add-user/index.vue

@ -393,9 +393,9 @@ export default {
}, },
selectedImage(type) { selectedImage(type) {
uploadImage() uploadImage()
.then((url) => {
if (url) {
this.form[type] = url
.then((urls) => {
if (urls) {
this.form[type] = urls[0]
} }
}) })
.catch((e) => { .catch((e) => {

11
pages/client-detail/basic-information.vue

@ -4,7 +4,7 @@
<view class="card-box"> <view class="card-box">
<view class="card-header"> <view class="card-header">
<view class="left-text">基本信息</view> <view class="left-text">基本信息</view>
<view class="right-text">跟进记录</view>
<view class="right-text" @tap="gotoTap">跟进记录</view>
</view> </view>
<view class="card-content"> <view class="card-content">
<view class="info"> <view class="info">
@ -212,7 +212,8 @@
<script> <script>
import uGap from '@/components/u-gap/u-gap.vue' import uGap from '@/components/u-gap/u-gap.vue'
import { getBaseInfo } from '@/apis/clientDetailApi'
import { getBaseInfo } from '@/apis/clientDetailApi'
import { go2 } from '@/utils/hook.js'
export default { export default {
components: { components: {
uGap uGap
@ -236,7 +237,11 @@ export default {
seemoreFlag: true seemoreFlag: true
} }
}, },
methods: {
methods: {
gotoTap() {
go2('follow-up-records')
},
getBaseInfo() { getBaseInfo() {
getBaseInfo({customerId: this.customerId }).then(res => { getBaseInfo({customerId: this.customerId }).then(res => {
// console.log('', res) // console.log('', res)

9
pages/enterprise-info/index.vue

@ -366,9 +366,10 @@ export default {
}, },
selectedImage(type) { selectedImage(type) {
uploadImage() uploadImage()
.then((url) => {
if (url) {
this.form[type] = url
.then((urls) => {
if (urls) {
this.form[type] = urls[0]
console.log('urls', urls)
} }
}) })
.catch((e) => { .catch((e) => {
@ -381,7 +382,7 @@ export default {
cancel() { cancel() {
// //
if (this.operation === 'add') { if (this.operation === 'add') {
go2('client', true)
go2('client', {}, true)
} else { } else {
back() back()
} }

177
pages/follow-up-records/index.vue

@ -0,0 +1,177 @@
<template>
<view class="warpper">
<timeline>
<timelineItem v-for="(item, index) in 4" :key="index">
<view class="time">
2021年12月28日 12:30:45
</view>
<view class="tripItem">
<view class="row">
<view class="title">跟进人</view>
<view class="value">贾晓堂 18877799220</view>
</view>
<view class="row">
<view class="title">拜访对象</view>
<view class="value">张翼德 18826104989</view>
</view>
<view class="row">
<view class="title">沟通内容</view>
<view class="value">已经对该供应商进行了需求调研并已经对纸掌柜产品进行推广盘商表示愿意支付使用该产品</view>
</view>
<view class="row">
<view class="title">备注信息</view>
<view class="value">客户说希望有特色功能</view>
</view>
<view class="row">
<view class="title"></view>
<view class="value">
<image class="icon" src="/static/imgs/client-detail/address-icon.png"></image>
<text class="location">广州市天河区</text>
</view>
</view>
</view>
</timelineItem>
<view class="see-more">
<text>查看更多</text>
<image class="icon" :src="!seemoreFlag ? '/static/imgs/client-detail/arrow-up-icon.png' : '/static/imgs/client-detail/arrow-down-icon.png'"></image>
</view>
</timeline>
<qn-footer fixed height="120rpx">
<view class="button-area">
<!-- <view class="button button__cancel" @click="back">
<text class="text">取消</text>
</view> -->
<view class="button button__submit" @click="addTap">
<text class="text" style="color: white">新增跟进</text>
</view>
</view>
</qn-footer>
</view>
</template>
<script>
import timeline from './timeLine.vue'
import timelineItem from './timelineItem.vue'
import qnFooter from '@/components/qn-footer/qn-footer.vue'
import { go2 } from '@/utils/hook.js'
export default {
components: {
timeline,
timelineItem,
qnFooter
},
data() {
return {}
},
methods:{
addTap() {
go2('add-record')
},
}
}
</script>
<style lang="scss">
.warpper {
background-color: #FFFFFF;
.time {
font-size: 26rpx;
color: #000000;
letter-spacing: 0;
font-weight: 400;
}
.tripItem {
margin-top: 20rpx;
// height: 140rpx;
padding: 20rpx 30rpx;
// height: 376rpx;
background: #F7F8FA;
border-radius: 8rpx;
.row {
display: flex;
flex-direction: row;
padding: 16rpx 0rpx;
.title {
flex: 0 0 140rpx;
font-size: 28rpx;
color: #888888;
letter-spacing: 0;
font-weight: 400;
}
.value {
display: flex;
align-items: center;
flex: 1;
font-size: 28rpx;
color: #333333;
letter-spacing: 0;
font-weight: 400;
line-height: 1.3;
}
.icon {
width: 32rpx;
height: 32rpx;
}
.location{
font-size: 26rpx;
color: #888888;
letter-spacing: 0;
text-align: left;
line-height: 32rpx;
font-weight: 400;
padding-left: 10rpx;
}
}
}
.see-more {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding-top: 20rpx;
background: #ffffff;
// border-top: 2rpx solid #dddddd;
// padding: 0rpx 32rpx;
font-size: 28rpx;
color: #007aff;
letter-spacing: 0;
text-align: center;
font-weight: 400;
.icon {
width: 24rpx;
height: 24rpx;
}
}
.button-area {
width: 750rpx;
padding: 0 32rpx;
display: flex;
flex-direction: row;
align-items: center;
// justify-content: space-between;
.button {
flex-grow: 0;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10rpx;
.text {
font-size: 30rpx;
font-weight: 500;
text-align: center;
}
}
.button__cancel {
width: 270rpx;
height: 88rpx;
border: 2rpx solid #979797;
}
.button__submit {
width: 100%;
height: 88rpx;
background: #007aff;
}
}
}
</style>

18
pages/follow-up-records/timeLine.vue

@ -0,0 +1,18 @@
<template>
<view class="timeline">
<slot></slot>
</view>
</template>
<script>
export default {
components:{
}
}
</script>
<style scoped lang="less">
.timeline {
padding: 36rpx 32rpx 0rpx 45rpx;
}
</style>

87
pages/follow-up-records/timelineItem.vue

@ -0,0 +1,87 @@
<template>
<view class="timelineItem">
<view class="timeItem">
<view class="leftTime">
{{leftTime}}
</view>
<view class="line">
<view class="out" :style="{background: color == '' ? '' : color}">
<view class="inner" :style="{background: color == '' ? '' : color}"></view>
</view>
</view>
<view class="rightContent">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
export default {
props:{
leftTime:{
type:String,
default:''
},
color:{
type:String,
default:''
}
},
data(){
return {
}
}
}
</script>
<style scoped lang="less">
.timelineItem {
.timeItem {
display: flex;
.leftTime {
// width: 45rpx;
// padding: 0 29rpx 0rpx 0rpx;
font-size:22rpx;
font-weight:500;
color:rgba(51,51,51,1);
// margin-right: 10rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.line {
width: 4rpx;
background: #B2D7FF;
position: relative;
.out {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: center;
align-items: center;
width: 28rpx;
height: 28rpx;
background : #007AFF;
border-radius: 50%;
.inner {
width: 18rpx;
height: 18rpx;
background : #007AFF;
border-radius: 50%;
}
}
}
.rightContent {
flex: 1;
padding: 0rpx 10rpx 16rpx 16rpx;
margin-left: 20rpx;
min-height: 50rpx;
}
}
}
</style>

10
pages/login/index.vue

@ -1,5 +1,5 @@
<template> <template>
<view>
<view style="background-color: white">
<uni-nav-bar :fixed="true" color="#ffffff" background-color="#ffffff" :status-bar="true" :border="false" left-icon="closeempty" @clickLeft="close" /> <uni-nav-bar :fixed="true" color="#ffffff" background-color="#ffffff" :status-bar="true" :border="false" left-icon="closeempty" @clickLeft="close" />
<view class="logo_area"> <view class="logo_area">
<image class="logo" src="/static/logo.png"></image> <image class="logo" src="/static/logo.png"></image>
@ -160,14 +160,6 @@ export default {
if (!res.enterpriseList || res.enterpriseList.length === 0) { if (!res.enterpriseList || res.enterpriseList.length === 0) {
go2('enterprise-info', { operation: 'add' }, true) go2('enterprise-info', { operation: 'add' }, true)
} else { } else {
let supplierInfo = res.enterpriseList[0]
store.commit('setSupplierInfo', {
id: supplierInfo.id,
name: supplierInfo.name,
fddEnterpriseStatus: supplierInfo.fddEnterpriseStatus,
supplierId: supplierInfo.supplier.id
})
store.commit('setUserInfo', { name: supplierInfo.employeeName, userId: res.userId, mobile: res.mobile, avatar: null })
go2('client') go2('client')
} }
} }

4
pages/mine/index.vue

@ -17,7 +17,7 @@
<view v-else> <view v-else>
<view class="user__name"> <view class="user__name">
<text class="name">{{ userInfo.name }}</text> <text class="name">{{ userInfo.name }}</text>
<image v-if="userInfo.fddEnterpriseStatus === fddStatus.UNCERTIFIED" class="image" src="/static/imgs/mine/certified-icon.png"></image>
<image v-if="userInfo.fddEnterpriseStatus === fddStatus.CERTIFIED_SUCCESS" class="image" src="/static/imgs/mine/certified-icon.png"></image>
<image v-else class="image" @click="certifyCompany()" src="/static/imgs/mine/non-certified-icon.png"></image> <image v-else class="image" @click="certifyCompany()" src="/static/imgs/mine/non-certified-icon.png"></image>
</view> </view>
<view style="margin-top: 10rpx"> <view style="margin-top: 10rpx">
@ -135,7 +135,7 @@
<script> <script>
import { exit, go2 } from '@/utils/hook.js' import { exit, go2 } from '@/utils/hook.js'
import { fddEnterpriseStatus } from '@/enums/index.js' import { fddEnterpriseStatus } from '@/enums/index.js'
import { getBaseInfo } from '@/apis/commonApi.js'
import { getBaseInfo, getVerifyUrl } from '@/apis/commonApi.js'
import qnDataPicker from '@/components/qn-data-picker/qn-data-picker.vue' import qnDataPicker from '@/components/qn-data-picker/qn-data-picker.vue'
import { dateTimeFormat } from '@/utils/index.js' import { dateTimeFormat } from '@/utils/index.js'
import { getOrderStatistics } from '@/apis/mineApi.js' import { getOrderStatistics } from '@/apis/mineApi.js'

60
utils/hook.js

@ -94,9 +94,10 @@ export function exit() {
/** /**
* 文件上传 * 文件上传
* @param {array} sourceType 上传的方式 album:相册 camera:相机 * @param {array} sourceType 上传的方式 album:相册 camera:相机
* @return {Promise} 以数组的形式返回对应的文件地址
* @param {number} count 上传的数量
* @return {Promise<string[]>} 以数组的形式返回对应的文件地址
*/ */
export function uploadImage(sourceType = ['album', 'camera']) {
export function uploadImage(sourceType = ['album', 'camera'], count = 1) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.chooseImage({ uni.chooseImage({
count: 1, count: 1,
@ -104,24 +105,16 @@ export function uploadImage(sourceType = ['album', 'camera']) {
sourceType: sourceType, sourceType: sourceType,
success: (res) => { success: (res) => {
const tempFilePaths = res.tempFilePaths const tempFilePaths = res.tempFilePaths
uni.uploadFile({
url: uploadUrl.image,
filePath: tempFilePaths[0],
name: 'image',
fileType: 'image',
success: (res) => {
let result = JSON.parse(res.data)
if (result.data) {
resolve(result.data)
} else {
reject(result.message)
}
},
fail: (err) => {
console.error('uploadFile error:', err)
reject(err)
}
let cache = tempFilePaths.map((path) => {
return uploadFile(path, 'image')
}) })
Promise.all(cache)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
}, },
fail: (err) => { fail: (err) => {
console.error('chooseImage error:', err) console.error('chooseImage error:', err)
@ -130,3 +123,32 @@ export function uploadImage(sourceType = ['album', 'camera']) {
}) })
}) })
} }
/**
* 单文件上传
* @param {string} path 文件路径
* @param {string} type 文件类型 image | file默认为image
* @returns {Promise<string>} 返回单文件上传地址
*/
export function uploadFile(path, type = 'image') {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: uploadUrl[type],
filePath: path,
name: type,
// fileType: type,
success: (res) => {
let result = JSON.parse(res.data)
if (result.data) {
resolve(result.data)
} else {
reject(result.message)
}
},
fail: (err) => {
console.error('uploadFile error:', err)
reject(err)
}
})
})
}
Loading…
Cancel
Save