chore:接口

This commit is contained in:
2026-10-13 10:38:08 +08:00
parent 8c5ed50f7a
commit 15b0d2a18a
11 changed files with 114 additions and 102 deletions

View File

@@ -69,20 +69,22 @@ export default {
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) {
saving: false,
fromAdmin: false
};
},
onLoad(options) {
this.id = parseInt(options.id || 0, 10) || 0;
this.isEdit = this.id > 0;
// from=admin: 商家端人脉管理页复用本编辑页, 保存后回商家端(缺省回员工端)
this.fromAdmin = options.from === 'admin';
if (this.isEdit) {
this.loadDetail();
}
},
}
},
methods: {
loadDetail() {
this.$api.sendRequest({
url: '/card/api/contact/info',
this.$cardApi.contactInfo({
data: { id: this.id },
success: res => {
if (res.code == 0) {
@@ -117,27 +119,32 @@ export default {
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' });
const onOk = 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' });
}
});
};
const onFail = () => {
this.saving = false;
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
};
// add/update 都走 JSON body:fields 为嵌套对象,跨端序列化零歧义
if (this.isEdit) {
this.$cardApi.contactUpdate({ data: data, success: onOk, fail: onFail });
} else {
this.$cardApi.contactAdd({ data: { fields: data.fields }, success: onOk, fail: onFail });
}
},
// 鸿蒙安全回列表: $util.redirectTo(禁裸 uni.switchTab/uni.navigateBack 兜底)
// 商家端(from=admin)回商家端人脉管理, 员工端回「我的人脉」
backToList() {
this.$util.redirectTo('/pages_tool/card/contacts');
const target = this.fromAdmin ? '/pages_tool/card/admin/contacts' : '/pages_tool/card/contacts';
this.$util.redirectTo(target);
}
}
};

View File

@@ -128,8 +128,7 @@ export default {
if (this.keyword.trim() !== '') {
data.keyword = this.keyword.trim();
}
this.$api.sendRequest({
url: '/card/api/contact/lists',
this.$cardApi.contactLists({
data: data,
success: res => {
if (res.code == 0) {
@@ -163,8 +162,7 @@ export default {
},
doConvert(item) {
uni.showLoading({ title: '转换中…', mask: true });
this.$api.sendRequest({
url: '/card/api/contact/toLead',
this.$cardApi.contactToLead({
data: { id: item.id },
success: res => {
uni.hideLoading();
@@ -192,8 +190,7 @@ export default {
});
},
doDelete(item) {
this.$api.sendRequest({
url: '/card/api/contact/delete',
this.$cardApi.contactDelete({
data: { id: item.id },
success: res => {
if (res.code == 0) {

View File

@@ -105,8 +105,8 @@ export default {
push('网站', r.website);
push('地址', [r.country, r.province, r.city, r.address].filter(Boolean).join(' '));
push('邮编', r.postal_code);
push('Telegram', r.telegram);
push('Messenger', r.messenger);
// Telegram / Messenger 已于 2026-10-13 软下线为独立标量:
// 旧值由后端自动合并进 socials_list, 此处不再单独渲染(避免重复行)
// 附加手机号(mobiles_list, 后端 CardRichFields 解码) → 可拨打
(r.mobiles_list || []).forEach((m, i) => {
@@ -170,8 +170,7 @@ export default {
return;
}
this.isLoading = true;
this.$api.sendRequest({
url: '/card/api/card/detail',
this.$cardApi.cardDetail({
data: { card_id: this.cardId },
success: res => {
this.isLoading = false;

View File

@@ -66,16 +66,7 @@
<input class="row-input" :value="form.wechat" placeholder="微信号(选填)"
@input="e => form.wechat = e.detail.value" />
</view>
<view class="form-row">
<view class="row-label">Telegram</view>
<input class="row-input" :value="form.telegram" placeholder="Telegram 账号(选填)"
@input="e => form.telegram = e.detail.value" />
</view>
<view class="form-row">
<view class="row-label">Messenger</view>
<input class="row-input" :value="form.messenger" placeholder="Messenger 账号(选填)"
@input="e => form.messenger = e.detail.value" />
</view>
<!-- Telegram / Messenger 已于 2026-10-13 软下线为独立字段, 统一在下方「社交媒体账号」添加 -->
</view>
<!-- 社交媒体账号 -->
@@ -93,7 +84,7 @@
<view class="form-row" v-if="socials.length < MAX_SOCIALS">
<text class="dyn-add" @tap="addSocial">+ 添加社交媒体(最多{{ MAX_SOCIALS }}个)</text>
</view>
<view class="group-tip" v-if="socials.length === 0">还没有社交媒体账号,添加后可展示在名片上</view>
<view class="group-tip" v-if="socials.length === 0">还没有社交媒体账号;Telegram / Messenger 也已并入此处添加</view>
</view>
<!-- 自定义字段 -->
@@ -159,37 +150,22 @@
</template>
<script>
// 与后端 BusinessCardFieldNormalizer 输出对齐的标量字段(含 2026-10 补的 bio)。
// 富化字段(mobiles/socials/custom_fields)由页面动态行单独收集,
// 后端 Card::update 的 richFieldSaves 仅对显式携带的键做 CardRichFields 清洗。
const FIELDS = [
'name', 'company', 'job_title', 'avatar',
'mobile', 'phone', 'email', 'website', 'wechat', 'telegram', 'messenger',
'country', 'province', 'city', 'address', 'postal_code',
'bio'
];
// 社交媒体类型: 必须与后端 CardRichFields::SOCIAL_TYPES 白名单保持一致(增减需两边同步)
const SOCIAL_TYPES = [
{ key: 'alipay', label: '支付宝' },
{ key: 'douyin', label: '抖音' },
{ key: 'wxvideo', label: '视频号' },
{ key: 'xiaohongshu', label: '小红书' },
{ key: 'weibo', label: '微博' },
{ key: 'kuaishou', label: '快手' },
{ key: 'bilibili', label: '哔哩哔哩' },
{ key: 'qq', label: 'QQ' },
{ key: 'linkedin', label: 'LinkedIn' },
{ key: 'facebook', label: 'Facebook' },
{ key: 'instagram', label: 'Instagram' },
{ key: 'x', label: 'X' },
{ key: 'other', label: '其他' }
];
/**
* 与后端 BusinessCardFieldNormalizer 输出对齐的标量字段(含 2026-10 补的 bio)。
* ⚠️ 2026-10-13: telegram / messenger 软下线为独立标量(传了也被后端忽略),
* 统一走下方社交媒体动态行; 旧数据读取时已由后端合并进 socials_list。
* 富化字段(mobiles/socials/custom_fields)由页面动态行单独收集,
* 后端 Card::update 的 richFieldSaves 仅对显式携带的键做 CardRichFields 清洗。
*
* SOCIAL_TYPES / CARD_FIELDS / RICH_FIELD_LIMITS 统一从收口层导入,
* 与后端白名单单点同步(见 common/js/card-api.js)。
*/
import { SOCIAL_TYPES, CARD_FIELDS, RICH_FIELD_LIMITS } from '@/common/js/card-api.js';
// 上限与后端 CardRichFields::MAX_* 一致
const MAX_MOBILES = 5;
const MAX_SOCIALS = 10;
const MAX_CUSTOM = 10;
const MAX_MOBILES = RICH_FIELD_LIMITS.MAX_MOBILES;
const MAX_SOCIALS = RICH_FIELD_LIMITS.MAX_SOCIALS;
const MAX_CUSTOM = RICH_FIELD_LIMITS.MAX_CUSTOM;
export default {
data() {
@@ -197,7 +173,7 @@ export default {
cardId: '',
form: {
name: '', company: '', job_title: '', avatar: '',
mobile: '', phone: '', email: '', website: '', wechat: '', telegram: '', messenger: '',
mobile: '', phone: '', email: '', website: '', wechat: '',
country: '', province: '', city: '', address: '', postal_code: '',
bio: ''
},
@@ -223,14 +199,13 @@ export default {
return;
}
this.isLoading = true;
this.$api.sendRequest({
url: '/card/api/card/detail',
this.$cardApi.cardDetail({
data: { card_id: this.cardId },
success: res => {
this.isLoading = false;
if (res.code == 0) {
const r = (res.data && res.data.relation) || {};
FIELDS.forEach(k => {
CARD_FIELDS.forEach(k => {
if (r[k] !== undefined && r[k] !== null) {
this.form[k] = String(r[k]);
}
@@ -369,7 +344,7 @@ export default {
// 富化字段始终显式携带(空数组=清空), 后端 richFieldSaves 只对携带的键清洗落库。
// 走 sendJson(JSON body): 嵌套数组序列化跨端零歧义, TP6 原生解析
const fields = {};
FIELDS.forEach(k => { fields[k] = this.form[k]; });
CARD_FIELDS.forEach(k => { fields[k] = this.form[k]; });
fields.mobiles = this.mobiles.map(v => String(v || '').trim());
fields.socials = this.socials.map(s => ({ type: s.type, value: String(s.value || '').trim() }));
fields.custom_fields = this.customFields.map(c => ({
@@ -377,8 +352,7 @@ export default {
value: String(c.value || '').trim()
}));
this.$api.sendJson({
url: '/card/api/card/update',
this.$cardApi.cardUpdate({
data: {
card_id: this.cardId,
fields: fields

View File

@@ -100,8 +100,7 @@ export default {
if (this.status !== '') {
data.status = this.status;
}
this.$api.sendRequest({
url: '/card/api/lead/lists',
this.$cardApi.leadLists({
data: data,
success: res => {
if (res.code == 0) {
@@ -134,8 +133,7 @@ export default {
});
},
doSetStatus(item, index, status) {
this.$api.sendRequest({
url: '/card/api/lead/setStatus',
this.$cardApi.leadSetStatus({
data: { id: item.id, status: status },
success: res => {
if (res.code == 0) {

View File

@@ -87,8 +87,7 @@ export default {
},
loadPage(pageNo, done) {
this.isLoading = true;
this.$api.sendRequest({
url: '/card/api/card/lists',
this.$cardApi.cardLists({
data: {
page: pageNo,
page_size: this.pageSize,
@@ -142,8 +141,7 @@ export default {
},
doClaim(cardId) {
uni.showLoading({ title: '认领中…' });
this.$api.sendRequest({
url: '/card/api/card/claim',
this.$cardApi.cardClaim({
data: { card_id: cardId },
success: res => {
uni.hideLoading();