- 新增 contacts.vue: 搜索/来源筛选/列表卡(来源徽标)/编辑/转潜在客户/删除 - 新增 contact-edit.vue: 新增编辑复用, 姓名红星必填, 其余(选填) - leads.vue 顶部互链「我的人脉 ›」(导航合并第一步) - pages.json 注册两页; PAGE_KEY_MAP 补 PAGE_CARD_CONTACTS - card-platform.test.js 追加 4 测试(25/25)
230 lines
5.8 KiB
Vue
230 lines
5.8 KiB
Vue
<template>
|
|
<view class="contact-edit">
|
|
<view class="form-group">
|
|
<view class="group-title">{{ isEdit ? '编辑人脉' : '添加人脉' }}</view>
|
|
<view class="form-row">
|
|
<view class="row-label"><text class="req-star">*</text>姓名</view>
|
|
<input class="row-input" :value="form.name" placeholder="请输入姓名"
|
|
@input="e => form.name = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">手机</view>
|
|
<input class="row-input" type="number" :value="form.mobile" placeholder="手机号(选填)"
|
|
@input="e => form.mobile = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">公司</view>
|
|
<input class="row-input" :value="form.company" placeholder="公司名称(选填)"
|
|
@input="e => form.company = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">职位</view>
|
|
<input class="row-input" :value="form.job_title" placeholder="职位(选填)"
|
|
@input="e => form.job_title = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">微信号</view>
|
|
<input class="row-input" :value="form.wechat" placeholder="微信号(选填)"
|
|
@input="e => form.wechat = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">邮箱</view>
|
|
<input class="row-input" :value="form.email" placeholder="邮箱(选填)"
|
|
@input="e => form.email = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">网站</view>
|
|
<input class="row-input" :value="form.website" placeholder="个人主页 / 官网(选填)"
|
|
@input="e => form.website = e.detail.value" />
|
|
</view>
|
|
<view class="form-row">
|
|
<view class="row-label">地址</view>
|
|
<input class="row-input" :value="form.address" placeholder="地址(选填)"
|
|
@input="e => form.address = e.detail.value" />
|
|
</view>
|
|
<view class="form-row remark-row">
|
|
<view class="row-label">备注</view>
|
|
<textarea class="remark-input" :value="form.remark" placeholder="备注(选填)"
|
|
@input="e => form.remark = e.detail.value" />
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 保存 -->
|
|
<view class="save-bar">
|
|
<button class="save-btn" :disabled="saving" @tap="save">{{ saving ? '保存中…' : '保存' }}</button>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
// 与后端 Contact::EDITABLE_FIELDS 对齐(status 由列表归档操作管理, 编辑页不放)
|
|
const FIELDS = ['name', 'mobile', 'company', 'job_title', 'wechat', 'email', 'website', 'address', 'remark'];
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
id: 0,
|
|
isEdit: false,
|
|
form: {
|
|
name: '', mobile: '', company: '', job_title: '',
|
|
wechat: '', email: '', website: '', address: '', remark: ''
|
|
},
|
|
saving: false
|
|
};
|
|
},
|
|
onLoad(options) {
|
|
this.id = parseInt(options.id || 0, 10) || 0;
|
|
this.isEdit = this.id > 0;
|
|
if (this.isEdit) {
|
|
this.loadDetail();
|
|
}
|
|
},
|
|
methods: {
|
|
loadDetail() {
|
|
this.$api.sendRequest({
|
|
url: '/card/api/contact/info',
|
|
data: { id: this.id },
|
|
success: res => {
|
|
if (res.code == 0) {
|
|
const r = res.data || {};
|
|
FIELDS.forEach(k => {
|
|
if (r[k] !== undefined && r[k] !== null) {
|
|
this.form[k] = String(r[k]);
|
|
}
|
|
});
|
|
} else {
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: res.message || '人脉不存在',
|
|
showCancel: false,
|
|
success: () => this.backToList()
|
|
});
|
|
}
|
|
},
|
|
fail: () => {
|
|
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
|
|
}
|
|
});
|
|
},
|
|
save() {
|
|
if (this.saving) return;
|
|
if (!this.form.name.trim()) {
|
|
uni.showToast({ title: '请填写姓名', icon: 'none' });
|
|
return;
|
|
}
|
|
this.saving = true;
|
|
|
|
const data = { id: this.id, fields: {} };
|
|
FIELDS.forEach(k => { data.fields[k] = this.form[k]; });
|
|
|
|
this.$api.sendJson({
|
|
url: this.isEdit ? '/card/api/contact/update' : '/card/api/contact/add',
|
|
data: this.isEdit ? data : { fields: data.fields },
|
|
success: res => {
|
|
this.saving = false;
|
|
if (res.code == 0) {
|
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
|
setTimeout(() => this.backToList(), 600);
|
|
} else {
|
|
uni.showToast({ title: res.message || '保存失败', icon: 'none' });
|
|
}
|
|
},
|
|
fail: () => {
|
|
this.saving = false;
|
|
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
|
|
}
|
|
});
|
|
},
|
|
// 鸿蒙安全回列表: $util.redirectTo(禁裸 uni.switchTab/uni.navigateBack 兜底)
|
|
backToList() {
|
|
this.$util.redirectTo('/pages_tool/card/contacts');
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.contact-edit {
|
|
min-height: 100vh;
|
|
background-color: #f6f7f9;
|
|
padding: 24rpx 24rpx 60rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.form-group {
|
|
background-color: #ffffff;
|
|
border-radius: 16rpx;
|
|
margin-bottom: 24rpx;
|
|
overflow: hidden;
|
|
|
|
.group-title {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
padding: 24rpx 24rpx 8rpx;
|
|
}
|
|
|
|
.form-row {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 24rpx;
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.row-label {
|
|
width: 160rpx;
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* 必填红星(与 card/edit.vue 同款) */
|
|
.req-star {
|
|
color: #f5222d;
|
|
margin-right: 4rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.row-input {
|
|
flex: 1;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
.remark-row {
|
|
align-items: flex-start;
|
|
|
|
.remark-input {
|
|
flex: 1;
|
|
min-height: 120rpx;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 1.6;
|
|
}
|
|
}
|
|
}
|
|
|
|
.save-bar {
|
|
padding: 20rpx 0 0;
|
|
|
|
.save-btn {
|
|
height: 88rpx;
|
|
line-height: 88rpx;
|
|
background-color: var(--main-color, #0054a5);
|
|
color: #ffffff;
|
|
font-size: 30rpx;
|
|
border-radius: 44rpx;
|
|
|
|
&[disabled] {
|
|
opacity: 0.6;
|
|
color: #ffffff;
|
|
background-color: var(--main-color, #0054a5);
|
|
}
|
|
}
|
|
}
|
|
</style>
|