Commit 63939368fa6da7938d6a179bd0efe6fcd5700de5

Authored by 史婷婷
1 parent efa1bbda

feat: 客户开发-增加功能按钮 -拜访记录(新增拜访记录),详情增加拜访记录展示(审核通过 才显示 拜访记录按钮)

@@ -47,6 +47,16 @@ export function createApi(params) { @@ -47,6 +47,16 @@ export function createApi(params) {
47 }) 47 })
48 } 48 }
49 49
  50 +// 新增拜访记录
  51 +export function createVisitRecordApi(params) {
  52 + return request({
  53 + url: `/customer/visitRecord`,
  54 + method: 'post',
  55 + data: params,
  56 + contentType: ContentTypeEnum.FORM_URLENCODED
  57 + })
  58 +}
  59 +
50 60
51 // 修改保存 61 // 修改保存
52 export function updateApi(params) { 62 export function updateApi(params) {
@@ -73,14 +73,22 @@ @@ -73,14 +73,22 @@
73 "navigationBarTextStyle": "black" 73 "navigationBarTextStyle": "black"
74 } 74 }
75 }, 75 },
76 - {  
77 - "path": "pages/dev_manage/modify",  
78 - "style": {  
79 - "navigationBarTitleText": "编辑客户开发",  
80 - "navigationBarBackgroundColor": "#ffffff",  
81 - "navigationBarTextStyle": "black"  
82 - }  
83 - }, 76 + {
  77 + "path": "pages/dev_manage/modify",
  78 + "style": {
  79 + "navigationBarTitleText": "编辑客户开发",
  80 + "navigationBarBackgroundColor": "#ffffff",
  81 + "navigationBarTextStyle": "black"
  82 + }
  83 + },
  84 + {
  85 + "path": "pages/dev_manage/visit_add",
  86 + "style": {
  87 + "navigationBarTitleText": "新增拜访记录",
  88 + "navigationBarBackgroundColor": "#ffffff",
  89 + "navigationBarTextStyle": "black"
  90 + }
  91 + },
84 { 92 {
85 "path": "pages/dev_manage/add", 93 "path": "pages/dev_manage/add",
86 "style": { 94 "style": {
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 getDicName('ENTERPRISE_TYPE', form.customerType, customerTypeOptions) }}</text> 15 getDicName('ENTERPRISE_TYPE', form.customerType, customerTypeOptions) }}</text>
16 </view> 16 </view>
17 <view class="row"><text class="label">产品品种</text><text class="value">{{ form.productVariety.name 17 <view class="row"><text class="label">产品品种</text><text class="value">{{ form.productVariety.name
18 - }}</text></view> 18 + }}</text></view>
19 <view class="row"><text class="label">月用量</text><text class="value">{{ form.monthlyUsage }}</text> 19 <view class="row"><text class="label">月用量</text><text class="value">{{ form.monthlyUsage }}</text>
20 </view> 20 </view>
21 <view class="row"><text class="label">目标量</text><text class="value">{{ form.targetQuantity }}</text> 21 <view class="row"><text class="label">目标量</text><text class="value">{{ form.targetQuantity }}</text>
@@ -30,9 +30,9 @@ @@ -30,9 +30,9 @@
30 </view> 30 </view>
31 <view class="row"><text class="label">宽度</text><text class="value">{{ form.width }}</text></view> 31 <view class="row"><text class="label">宽度</text><text class="value">{{ form.width }}</text></view>
32 <view class="row"><text class="label">材质要求</text><text class="value">{{ form.materialRequire 32 <view class="row"><text class="label">材质要求</text><text class="value">{{ form.materialRequire
33 - }}</text></view> 33 + }}</text></view>
34 <view class="row"><text class="label">品质要求</text><text class="value">{{ form.qualityRequire 34 <view class="row"><text class="label">品质要求</text><text class="value">{{ form.qualityRequire
35 - }}</text></view> 35 + }}</text></view>
36 <view class="row"><text class="label">同行</text><text class="value">{{ form.peer }}</text></view> 36 <view class="row"><text class="label">同行</text><text class="value">{{ form.peer }}</text></view>
37 </view> 37 </view>
38 <view class="section"> 38 <view class="section">
@@ -45,6 +45,7 @@ @@ -45,6 +45,7 @@
45 <view class="row"><text class="label">责任人</text><text class="value">{{ form.chargeUserName }}</text> 45 <view class="row"><text class="label">责任人</text><text class="value">{{ form.chargeUserName }}</text>
46 </view> 46 </view>
47 </view> 47 </view>
  48 + <VisitList mode="view" :list="form.visitRecords || []" />
48 </view> 49 </view>
49 </scroll-view> 50 </scroll-view>
50 <detail-buttons :buttons="displayButtons" @click="handleButtonClick" /> 51 <detail-buttons :buttons="displayButtons" @click="handleButtonClick" />
@@ -63,11 +64,14 @@ import { @@ -63,11 +64,14 @@ import {
63 getDicByCodeApi 64 getDicByCodeApi
64 } from '@/api/base.js' 65 } from '@/api/base.js'
65 import DetailButtons from '@/components/detail-buttons/index.vue' 66 import DetailButtons from '@/components/detail-buttons/index.vue'
  67 +import VisitList from './visitList.vue'
  68 +
66 69
67 export default { 70 export default {
68 name: 'DevManageDetail', 71 name: 'DevManageDetail',
69 components: { 72 components: {
70 - DetailButtons 73 + DetailButtons,
  74 + VisitList
71 }, 75 },
72 data() { 76 data() {
73 return { 77 return {
@@ -114,6 +118,12 @@ export default { @@ -114,6 +118,12 @@ export default {
114 event: 'audit' 118 event: 'audit'
115 }, 119 },
116 { 120 {
  121 + text: '拜访记录',
  122 + visible: true,
  123 + variant: 'primary',
  124 + event: 'visitAdd',
  125 + },
  126 + {
117 text: '取消', 127 text: '取消',
118 visible: true, 128 visible: true,
119 variant: 'outline', 129 variant: 'outline',
@@ -129,12 +139,13 @@ export default { @@ -129,12 +139,13 @@ export default {
129 computed: { 139 computed: {
130 displayButtons() { 140 displayButtons() {
131 const s = Number(this.form && this.form.status || 0) 141 const s = Number(this.form && this.form.status || 0)
132 - const t = this.todoType || '' 142 + const t = this.todoType || '';
133 return [ 143 return [
134 { ...this.buttons[0], visible: (s === 3 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:modify')) }, 144 { ...this.buttons[0], visible: (s === 3 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:modify')) },
135 { ...this.buttons[1], visible: this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:reviewDetail') }, 145 { ...this.buttons[1], visible: this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:reviewDetail') },
136 { ...this.buttons[2], visible: (s === 1 && t === 'WAIT' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:review')) }, 146 { ...this.buttons[2], visible: (s === 1 && t === 'WAIT' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:review')) },
137 - { ...this.buttons[3], visible: (s === 3 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:close')) } 147 + { ...this.buttons[3], visible: (s === 2 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:record')) },
  148 + { ...this.buttons[4], visible: (s === 3 && t === '' && this.$auth.hasPermi('customer-dev-manage:customer-dev-plan:close')) }
138 ] 149 ]
139 } 150 }
140 }, 151 },
@@ -188,6 +199,7 @@ export default { @@ -188,6 +199,7 @@ export default {
188 if (e === 'auditDetail') return this.onAuditDetail(btn && btn.params) 199 if (e === 'auditDetail') return this.onAuditDetail(btn && btn.params)
189 if (e === 'audit') return this.onAudit(btn && btn.params) 200 if (e === 'audit') return this.onAudit(btn && btn.params)
190 if (e === 'cancel') return this.onCancel(btn && btn.params) 201 if (e === 'cancel') return this.onCancel(btn && btn.params)
  202 + if (e === 'visitAdd') return this.onVisitAdd(btn && btn.params)
191 }, 203 },
192 onEdit() { 204 onEdit() {
193 const id = this.form.id || this.form.code || '' 205 const id = this.form.id || this.form.code || ''
@@ -227,6 +239,13 @@ export default { @@ -227,6 +239,13 @@ export default {
227 } 239 }
228 } 240 }
229 }) 241 })
  242 + },
  243 + onVisitAdd() {
  244 + console.log('onVisitAdd', this.form)
  245 + const id = this.form && (this.form.id || this.form.code) || ''
  246 + if (!id) return
  247 + const query = id ? ('?id=' + encodeURIComponent(id)) : ''
  248 + uni.navigateTo({ url: '/pages/dev_manage/visit_add' + query })
230 } 249 }
231 } 250 }
232 } 251 }
@@ -5,14 +5,14 @@ @@ -5,14 +5,14 @@
5 <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入客户名称" clearButton="auto" 5 <uni-search-bar v-model="searchKeyword" radius="6" placeholder="请输入客户名称" clearButton="auto"
6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search" 6 cancelButton="none" bgColor="#F3F3F3" textColor="rgba(0,0,0,0.4)" @confirm="search"
7 @input="onSearchInput" /> 7 @input="onSearchInput" />
8 - <view class="tool-icons">  
9 - <image class="tool-icon"  
10 - v-if="$auth.hasPermi('customer-dev-manage:customer-dev-plan:batchReview')"  
11 - :src="batchMode ? '/static/images/dev_manage/close_icon.png' : '/static/images/dev_manage/batch_icon.png'"  
12 - @click="toggleBatch" /> 8 + <view class="tool-icons">
  9 + <image class="tool-icon"
  10 + v-if="$auth.hasPermi('customer-dev-manage:customer-dev-plan:batchReview')"
  11 + :src="batchMode ? '/static/images/dev_manage/close_icon.png' : '/static/images/dev_manage/batch_icon.png'"
  12 + @click="toggleBatch" />
13 <image v-if="$auth.hasPermi('customer-dev-manage:customer-dev-plan:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" /> 13 <image v-if="$auth.hasPermi('customer-dev-manage:customer-dev-plan:add')" class="tool-icon" src="/static/images/dev_manage/add_icon.png" @click="onAdd" />
14 - <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />  
15 - </view> 14 + <image class="tool-icon" src="/static/images/dev_manage/filter_icon.png" @click="openFilter" />
  15 + </view>
16 </view> 16 </view>
17 17
18 <!-- 页内 tabs --> 18 <!-- 页内 tabs -->
@@ -356,11 +356,11 @@ @@ -356,11 +356,11 @@
356 }) 356 })
357 }) 357 })
358 }, 358 },
359 - onAdd() {  
360 - uni.navigateTo({  
361 - url: '/pages/dev_manage/add'  
362 - })  
363 - }, 359 + onAdd() {
  360 + uni.navigateTo({
  361 + url: '/pages/dev_manage/add'
  362 + })
  363 + },
364 // 列表接口(真实请求) 364 // 列表接口(真实请求)
365 fetchList({ 365 fetchList({
366 pageIndex, 366 pageIndex,
  1 +<template>
  2 + <view class="product" :class="{ 'history': mode == 'history' }">
  3 +
  4 + <!-- 详情-拜访记录 -->
  5 + <view class="header bp">
  6 + <image class="opCollapse" src="/static/images/title.png" />
  7 + <text class="title">拜访记录</text>
  8 + <view class="ops">
  9 + <view v-if="mode === 'view'" class="op1" @click="toggleViewCollapse">
  10 + <image class="opAdd" :src="collapsedView ? '/static/images/down.png' : '/static/images/up.png'" />
  11 + <text class="op">{{ collapsedView ? '展开' : '收起' }} </text>
  12 + </view>
  13 +
  14 + </view>
  15 + </view>
  16 + <view v-if="mode === 'view'" class="view-list" v-show="!collapsedView">
  17 + <view v-for="(item, idx) in items" :key="'v-' + idx" class="card">
  18 + <view class="row"><text class="label">拜访人姓名</text><text class="value">{{ item.userName }}</text></view>
  19 + <view class="row"><text class="label">拜访时间</text><text class="value">{{ item.visitTime }}</text></view>
  20 + <view class="row"><text class="label">拜访内容</text><text class="value">{{ item.visitContent }}</text></view>
  21 + </view>
  22 + </view>
  23 +
  24 + </view>
  25 +</template>
  26 +<script>
  27 +import { uuid } from '@/utils/uuid.js'
  28 +export default {
  29 + name: 'VisitList',
  30 + props: {
  31 + title: { type: String, default: '' },
  32 + mode: { type: String, default: 'add' },
  33 + list: { type: Array, default: () => [] },
  34 + },
  35 + data() {
  36 + return {
  37 + items: [],
  38 + collapsedView: false,
  39 + }
  40 + },
  41 + watch: {
  42 + items: {
  43 + handler() { this.emitChange() },
  44 + deep: true
  45 + },
  46 + list: {
  47 + handler(v) {
  48 + const arr = Array.isArray(v) ? v : []
  49 + this.items = arr.map(x => {
  50 + const it = { ...this.defaultItem(), ...x, collapsed: true }
  51 + return it
  52 + })
  53 + },
  54 + deep: true
  55 + },
  56 + },
  57 + created() {
  58 + const init = Array.isArray(this.list) && this.list.length > 0 ? this.list.map(v => ({ ...this.defaultItem(), ...v, collapsed: false })) : [{ ...this.defaultItem(), collapsed: false }]
  59 + this.items = init
  60 + },
  61 + methods: {
  62 + defaultItem() {
  63 + return { collapsed: false, packagingFee: '' }
  64 + },
  65 + toggleItem(idx) {
  66 + const it = this.items[idx]
  67 + if (!it) return
  68 + it.collapsed = !it.collapsed
  69 + this.$set(this.items, idx, it)
  70 + },
  71 + emitChange() {
  72 + console.log('emitChange__items', this.items)
  73 + const out = this.items.map(it => JSON.parse(JSON.stringify(it)))
  74 + console.log('emitChange__out', out)
  75 + this.$emit('input', out)
  76 + this.$emit('update:value', out)
  77 + this.$emit('change', out)
  78 + },
  79 + toggleViewCollapse() {
  80 + this.collapsedView = !this.collapsedView
  81 + },
  82 + }
  83 +}
  84 +</script>
  85 +<style lang="scss" scoped>
  86 +.header {
  87 + background-color: #fff;
  88 + display: flex;
  89 + align-items: center;
  90 + padding: 24rpx 32rpx;
  91 +
  92 + &.bp {
  93 + border-bottom: 1px solid #f0f0f0;
  94 + }
  95 +}
  96 +
  97 +.dot {
  98 + width: 16rpx;
  99 + height: 16rpx;
  100 + background: #3D48A3;
  101 + border-radius: 50%;
  102 + margin-right: 12rpx;
  103 +}
  104 +
  105 +.title {
  106 + font-size: 32rpx;
  107 + color: rgba(0, 0, 0, 0.9);
  108 + font-weight: 600;
  109 +}
  110 +
  111 +.ops {
  112 + margin-left: auto;
  113 +}
  114 +
  115 +.op {
  116 + color: $theme-primary;
  117 + font-size: 28rpx;
  118 + margin-left: 8rpx;
  119 +}
  120 +
  121 +.op1 {
  122 + display: flex;
  123 + align-items: center;
  124 +}
  125 +
  126 +.opAdd {
  127 + color: rgba(0, 0, 0, 0.6);
  128 + width: 40rpx;
  129 + height: 40rpx;
  130 +}
  131 +
  132 +.opCollapse {
  133 + color: rgba(0, 0, 0, 0.6);
  134 + width: 32rpx;
  135 + height: 28rpx;
  136 + margin-right: 16rpx;
  137 +}
  138 +
  139 +
  140 +::v-deep .uni-list {
  141 + background: transparent;
  142 +
  143 + &-item {
  144 + &__extra-text {
  145 + font-size: 32rpx;
  146 + }
  147 +
  148 + &__content-title {
  149 + font-size: 32rpx;
  150 + color: rgba(0, 0, 0, 0.9);
  151 + }
  152 +
  153 + &__container {
  154 + padding: 32rpx;
  155 +
  156 + .uni-easyinput {
  157 +
  158 + .is-disabled {
  159 + background-color: transparent !important;
  160 + }
  161 +
  162 + &__placeholder-class {
  163 + font-size: 32rpx;
  164 + color: rgba(0, 0, 0, 0.4);
  165 + }
  166 +
  167 + &__content {
  168 + border: none;
  169 +
  170 + &-input {
  171 + padding-left: 0 !important;
  172 + height: 48rpx;
  173 + line-height: 48rpx;
  174 + font-size: 32rpx;
  175 + }
  176 +
  177 + .content-clear-icon {
  178 + font-size: 44rpx !important;
  179 + }
  180 + }
  181 + }
  182 +
  183 + .amount-row {
  184 + flex: 1;
  185 + display: flex;
  186 + align-items: center;
  187 +
  188 + .uni-easyinput {
  189 + flex: 1;
  190 + }
  191 +
  192 + .unit {
  193 + margin-left: 16rpx;
  194 + color: rgba(0, 0, 0, 0.9);
  195 + }
  196 + }
  197 +
  198 + .item-title,
  199 + .uni-list-item__content {
  200 + flex: none;
  201 + min-height: 48rpx;
  202 + line-height: 48rpx;
  203 + font-size: 32rpx;
  204 + position: relative;
  205 + width: 210rpx;
  206 + margin-right: 32rpx;
  207 + color: rgba(0, 0, 0, 0.9);
  208 + padding-right: 0;
  209 +
  210 +
  211 + .required {
  212 + color: red;
  213 + position: absolute;
  214 + top: 50%;
  215 + transform: translateY(-50%);
  216 + left: -16rpx;
  217 + }
  218 + }
  219 +
  220 + }
  221 +
  222 + &.select-item {
  223 + &.is-empty {
  224 + .uni-list-item__extra-text {
  225 + color: rgba(0, 0, 0, 0.4) !important;
  226 + }
  227 + }
  228 +
  229 + &.is-filled {
  230 + .uni-list-item__extra-text {
  231 + color: rgba(0, 0, 0, 0.9) !important;
  232 + }
  233 + }
  234 +
  235 + .serial-number-row {
  236 + display: flex;
  237 + align-items: center;
  238 + }
  239 +
  240 + }
  241 +
  242 + &.mgb10 {
  243 + margin-bottom: 20rpx;
  244 + }
  245 +
  246 + }
  247 +
  248 + .title-header {
  249 + background-color: #fff;
  250 + display: flex;
  251 + align-items: center;
  252 + padding: 32rpx 32rpx 22rpx;
  253 +
  254 + &_icon {
  255 + width: 32rpx;
  256 + height: 28rpx;
  257 + margin-right: 16rpx;
  258 + }
  259 +
  260 + span {
  261 + color: rgba(0, 0, 0, 0.9);
  262 + font-size: 32rpx;
  263 + line-height: 44rpx;
  264 + font-weight: 600;
  265 + }
  266 + }
  267 +}
  268 +
  269 +/* 只读 easyinput 根据内容自适应高度 */
  270 +::v-deep .uni-list-item__container {
  271 + align-items: flex-start;
  272 +}
  273 +
  274 +.block-ops {
  275 + display: flex;
  276 + padding: 20rpx 32rpx 20rpx;
  277 + justify-content: space-around;
  278 +}
  279 +
  280 +.del {
  281 + color: #D54941;
  282 + font-size: 28rpx;
  283 + display: flex;
  284 + align-items: center;
  285 +
  286 + image {
  287 + width: 40rpx;
  288 + height: 40rpx;
  289 + }
  290 +}
  291 +
  292 +.toggle {
  293 + color: $theme-primary;
  294 + font-size: 28rpx;
  295 + display: flex;
  296 + align-items: center;
  297 +
  298 + image {
  299 + width: 40rpx;
  300 + height: 40rpx;
  301 + }
  302 +}
  303 +
  304 +.section {
  305 + background: #f1f1f1;
  306 + margin-bottom: 20rpx;
  307 +
  308 + .block {
  309 + background: #ffffff;
  310 + padding: 32rpx 0;
  311 + margin-bottom: 20rpx;
  312 +
  313 + &:last-child {
  314 + margin-bottom: 0;
  315 + }
  316 + }
  317 +
  318 + .row {
  319 + display: flex;
  320 + // margin-bottom: 24rpx;
  321 + line-height: 32rpx;
  322 + padding: 32rpx;
  323 + border-bottom: 1rpx solid #f2f2f2;
  324 +
  325 +
  326 + &.noneStyle {
  327 + border-bottom: 0;
  328 + border-bottom: none;
  329 + }
  330 +
  331 + &.row-spec {
  332 + align-items: center;
  333 + }
  334 + }
  335 +
  336 + .row:last-child {
  337 + margin-bottom: 0;
  338 + }
  339 +
  340 + .label {
  341 + width: 210rpx;
  342 + margin-right: 32rpx;
  343 + color: rgba(0, 0, 0, 0.9);
  344 + font-size: 32rpx;
  345 + line-height: 48rpx;
  346 + }
  347 +
  348 + .value {
  349 + flex: 1;
  350 + color: rgba(0, 0, 0, 0.9);
  351 + font-size: 32rpx;
  352 + white-space: pre-wrap;
  353 + word-break: break-all;
  354 + line-height: 48rpx;
  355 + }
  356 +
  357 + .value-spec {
  358 + height: 48rpx;
  359 + display: flex;
  360 + align-items: center;
  361 + color: #000000;
  362 +
  363 + &_box {
  364 + position: relative;
  365 + width: 60rpx;
  366 + height: 48rpx;
  367 +
  368 + &_1 {
  369 + font-size: 16rpx;
  370 + position: absolute;
  371 + top: -10rpx;
  372 + left: 0;
  373 + }
  374 +
  375 + &_2 {
  376 + font-size: 16rpx;
  377 + position: absolute;
  378 + bottom: -10rpx;
  379 + left: 0;
  380 + }
  381 + }
  382 +
  383 + &_val {
  384 + font-size: 28rpx;
  385 +
  386 + &.p12 {
  387 + padding-right: 12rpx;
  388 + }
  389 + }
  390 + }
  391 +
  392 + .view-total {
  393 + padding-top: 20rpx;
  394 +
  395 + .head {
  396 + font-size: 32rpx;
  397 + font-weight: 600;
  398 + line-height: 50rpx;
  399 + color: rgba(0, 0, 0, 0.9);
  400 + padding-bottom: 16rpx;
  401 + margin-bottom: 24rpx;
  402 + ;
  403 + border-bottom: 1px dashed #E7E7E7;
  404 + }
  405 +
  406 + .row {
  407 + display: flex;
  408 + margin-bottom: 24rpx;
  409 + line-height: 32rpx;
  410 +
  411 + .label {
  412 + width: 180rpx;
  413 + margin-right: 14rpx;
  414 + color: rgba(0, 0, 0, 0.6);
  415 + font-size: 28rpx;
  416 + }
  417 +
  418 + .value {
  419 + flex: 1;
  420 + color: rgba(0, 0, 0, 0.9);
  421 + font-size: 28rpx;
  422 + white-space: pre-wrap;
  423 + word-break: break-all;
  424 + }
  425 + }
  426 + }
  427 +}
  428 +
  429 +.view-list {
  430 + padding: 26rpx 32rpx;
  431 + background: #ffffff;
  432 +
  433 + .card {
  434 + background: #f3f3f3;
  435 + border-radius: 16rpx;
  436 + padding: 32rpx 44rpx;
  437 + margin-bottom: 20rpx;
  438 +
  439 + &:last-child {
  440 + margin-bottom: 0;
  441 + }
  442 + }
  443 +
  444 + .row {
  445 + display: flex;
  446 + margin-bottom: 24rpx;
  447 + line-height: 32rpx;
  448 +
  449 + &.row-spec {
  450 + height: 60rpx;
  451 + align-items: center;
  452 + }
  453 + }
  454 +
  455 + .row:last-child {
  456 + margin-bottom: 0;
  457 + }
  458 +
  459 + .label {
  460 + width: 140rpx;
  461 + margin-right: 14rpx;
  462 + color: rgba(0, 0, 0, 0.6);
  463 + font-size: 28rpx;
  464 + }
  465 +
  466 + .value {
  467 + flex: 1;
  468 + color: rgba(0, 0, 0, 0.9);
  469 + font-size: 28rpx;
  470 + white-space: pre-wrap;
  471 + word-break: break-all;
  472 + }
  473 +
  474 + .value-spec {
  475 + height: 60rpx;
  476 + display: flex;
  477 + align-items: center;
  478 + color: #000000;
  479 +
  480 + &_box {
  481 + position: relative;
  482 + width: 60rpx;
  483 + height: 60rpx;
  484 +
  485 + &_1 {
  486 + font-size: 16rpx;
  487 + position: absolute;
  488 + top: 0;
  489 + left: 0;
  490 + }
  491 +
  492 + &_2 {
  493 + font-size: 16rpx;
  494 + position: absolute;
  495 + bottom: 0;
  496 + left: 0;
  497 + }
  498 + }
  499 +
  500 + &_val {
  501 + font-size: 28rpx;
  502 +
  503 + &.p12 {
  504 + padding-right: 12rpx;
  505 + }
  506 + }
  507 + }
  508 +
  509 + .view-total {
  510 + padding-top: 20rpx;
  511 +
  512 + .head {
  513 + font-size: 32rpx;
  514 + font-weight: 600;
  515 + line-height: 50rpx;
  516 + color: rgba(0, 0, 0, 0.9);
  517 + padding-bottom: 16rpx;
  518 + margin-bottom: 24rpx;
  519 + ;
  520 + border-bottom: 1px dashed #E7E7E7;
  521 + }
  522 +
  523 + .row {
  524 + display: flex;
  525 + margin-bottom: 24rpx;
  526 + line-height: 32rpx;
  527 +
  528 + .label {
  529 + width: 180rpx;
  530 + margin-right: 14rpx;
  531 + color: rgba(0, 0, 0, 0.6);
  532 + font-size: 28rpx;
  533 + }
  534 +
  535 + .value {
  536 + flex: 1;
  537 + color: rgba(0, 0, 0, 0.9);
  538 + font-size: 28rpx;
  539 + white-space: pre-wrap;
  540 + word-break: break-all;
  541 + }
  542 + }
  543 + }
  544 +}
  545 +</style>
  1 +<template>
  2 + <view class="page">
  3 + <scroll-view class="scroll" scroll-y>
  4 + <uni-list>
  5 + <uni-list-item class="select-item" :class="form.userId ? 'is-filled' : 'is-empty'" clickable
  6 + @click="openRelate('userId')" :rightText="form.userName || '请选择拜访人'" showArrow>
  7 + <template v-slot:body>
  8 + <view class="item-title"><text class="required">*</text><text>拜访人姓名</text></view>
  9 + </template>
  10 + </uni-list-item>
  11 +
  12 + <uni-list-item>
  13 + <template v-slot:body>
  14 + <view class="item-title"><text class="required">*</text><text>拜访时间</text></view>
  15 + </template>
  16 + <template v-slot:footer>
  17 + <uni-datetime-picker type="date" v-model="form.visitTime" />
  18 + </template>
  19 + </uni-list-item>
  20 +
  21 + <uni-list-item title="拜访内容">
  22 + <template v-slot:footer>
  23 + <uni-easyinput type="textarea" v-model="form.visitContent" placeholder="请输入拜访内容" :inputBorder="false" />
  24 + </template>
  25 + </uni-list-item>
  26 + </uni-list>
  27 + </scroll-view>
  28 +
  29 + <view class="footer">
  30 + <button class="btn submit" type="primary" @click="onSubmit">提交</button>
  31 + </view>
  32 +
  33 + <RelateSelectSheet :visible.sync="relate.visible" :title="relate.title" :source="relate.source"
  34 + :display-fields="relate.display" :multiple="relate.multiple" :row-key="relate.rowKey"
  35 + :selectedKeys.sync="relate.selectedKeys" :source-extra="{ source: 'CUSTOMER_DEVELOP' }"
  36 + @confirm="onRelateConfirm" />
  37 + </view>
  38 +</template>
  39 +
  40 +<script>
  41 +import RelateSelectSheet from '@/components/relate-select/index.vue'
  42 +import storage from '@/utils/storage'
  43 +import constant from '@/utils/constant'
  44 +import {
  45 + createVisitRecordApi
  46 +} from '@/api/devManage.js'
  47 +
  48 +export default {
  49 + name: 'DevManageVisitAdd',
  50 + components: { RelateSelectSheet },
  51 + data() {
  52 + return {
  53 + customerId: '',
  54 + form: {
  55 + userId: '',
  56 + userName: '',
  57 + visitTime: new Date().toISOString().substring(0, 10),
  58 + visitContent: ''
  59 + },
  60 + relate: { visible: false, title: '选择拜访人', source: '', display: [], multiple: false, rowKey: 'id', selectedKeys: [], fieldKey: '' }
  61 + }
  62 + },
  63 + created() {
  64 + const user = storage.get(constant.name)
  65 + const userId = storage.get(constant.id)
  66 + this.form.userName = user || ''
  67 + this.form.userId = userId || ''
  68 + },
  69 + onLoad(query) {
  70 + this.customerId = (query && query.id) || '';
  71 + },
  72 + methods: {
  73 + openRelate(fieldKey) {
  74 + let config = {}
  75 + if (fieldKey === 'userId') {
  76 + config = {
  77 + title: '拜访人',
  78 + source: 'user',
  79 + rowKey: 'id',
  80 + multiple: false,
  81 + display: [
  82 + { label: '姓名', field: 'name' },
  83 + { label: '编号', field: 'code' },
  84 + { label: '状态', field: 'available', format: v => (v ? '启用' : '停用') }
  85 + ]
  86 + }
  87 + }
  88 + const selectedKeys = this.form.userId ? [this.form.userId] : []
  89 + this.relate.title = config.title
  90 + this.relate.source = config.source
  91 + this.relate.display = config.display
  92 + this.relate.multiple = config.multiple
  93 + this.relate.rowKey = config.rowKey
  94 + this.relate.selectedKeys = selectedKeys
  95 + this.relate.fieldKey = fieldKey
  96 + this.$nextTick(() => { this.relate.visible = true })
  97 + },
  98 + onRelateConfirm({ items }) {
  99 + const first = (items && items.length > 0) ? items[0] : null
  100 + this.form.userId = (first && (first.id || first.userId)) || ''
  101 + this.form.userName = (first && (first.name || first.userName)) || ''
  102 + },
  103 + validateRequired() {
  104 + const checks = [
  105 + { key: 'userId', label: '拜访人姓名' },
  106 + { key: 'visitTime', label: '拜访时间' }
  107 + ]
  108 + for (const it of checks) {
  109 + const val = this.form[it.key]
  110 + if (val === undefined || val === null || String(val).trim() === '') {
  111 + uni.showToast({
  112 + title: `请先选择${it.label}`,
  113 + icon: 'none'
  114 + })
  115 + return false
  116 + }
  117 + }
  118 + return true
  119 + },
  120 + onSubmit() {
  121 + if (!this.validateRequired()) return
  122 + const payload = { ...this.form }
  123 + payload.customerId = this.customerId;
  124 + delete payload.userName;
  125 + console.log('visit_add_submit', payload)
  126 + createVisitRecordApi(payload).then(res => {
  127 + uni.showToast({
  128 + title: '提交成功',
  129 + icon: 'success'
  130 + })
  131 + setTimeout(() => { uni.redirectTo({ url: '/pages/dev_manage/index' }) }, 300)
  132 + }).catch(e => {
  133 + uni.showToast({
  134 + title: e.msg || '提交失败',
  135 + icon: 'none'
  136 + })
  137 + })
  138 + }
  139 + }
  140 +}
  141 +</script>
  142 +
  143 +<style lang="scss" scoped>
  144 +.page {
  145 + display: flex;
  146 + flex-direction: column;
  147 + height: 100%;
  148 +}
  149 +
  150 +.scroll {
  151 + flex: 1;
  152 + padding: 12rpx 0 160rpx;
  153 +}
  154 +
  155 +.footer {
  156 + position: fixed;
  157 + left: 0;
  158 + right: 0;
  159 + bottom: 0;
  160 + padding: 32rpx;
  161 + padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
  162 + background: #fff;
  163 + box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
  164 + z-index: 10;
  165 +
  166 + .btn {
  167 + height: 80rpx;
  168 + line-height: 80rpx;
  169 + border-radius: 12rpx;
  170 + font-size: 32rpx;
  171 + }
  172 +
  173 + .submit {
  174 + background: $theme-primary;
  175 + color: #fff;
  176 + }
  177 +}
  178 +
  179 +::v-deep .uni-list {
  180 + background: transparent;
  181 +
  182 + &-item {
  183 + &__extra-text {
  184 + font-size: 32rpx;
  185 + }
  186 +
  187 + &__content-title {
  188 + font-size: 32rpx;
  189 + color: rgba(0, 0, 0, 0.9);
  190 + }
  191 +
  192 + &__container {
  193 + padding: 32rpx;
  194 +
  195 + .uni-easyinput {
  196 + &__placeholder-class {
  197 + font-size: 32rpx;
  198 + color: rgba(0, 0, 0, 0.4);
  199 + }
  200 +
  201 + &__content {
  202 + border: none;
  203 +
  204 + &-input {
  205 + padding-left: 0 !important;
  206 + height: 48rpx;
  207 + line-height: 48rpx;
  208 + font-size: 32rpx;
  209 + }
  210 +
  211 + .content-clear-icon {
  212 + font-size: 44rpx !important;
  213 + }
  214 + }
  215 + }
  216 +
  217 + .item-title,
  218 + .uni-list-item__content {
  219 + flex: none;
  220 + min-height: 48rpx;
  221 + line-height: 48rpx;
  222 + font-size: 32rpx;
  223 + position: relative;
  224 + width: 210rpx;
  225 + margin-right: 32rpx;
  226 + color: rgba(0, 0, 0, 0.9);
  227 +
  228 + .required {
  229 + color: red;
  230 + position: absolute;
  231 + top: 50%;
  232 + transform: translateY(-50%);
  233 + left: -16rpx;
  234 + }
  235 + }
  236 +
  237 + }
  238 +
  239 + &.select-item {
  240 + &.is-empty {
  241 + .uni-list-item__extra-text {
  242 + color: rgba(0, 0, 0, 0.4) !important;
  243 + }
  244 + }
  245 +
  246 + &.is-filled {
  247 + .uni-list-item__extra-text {
  248 + color: rgba(0, 0, 0, 0.9) !important;
  249 + }
  250 + }
  251 + }
  252 +
  253 + &.mgb10 {
  254 + margin-bottom: 20rpx;
  255 + }
  256 + }
  257 +}
  258 +</style>