Enhance profile editing and sharing functionality

- Added a new feature for sharing profile cards, including special handling for forwarding to friends and displaying a canvas cover with user information.
- Updated the mini program's profile-edit page to generate a shareable card with a structured layout, including user avatar, nickname, and additional information.
- Improved the documentation to reflect the new sharing capabilities and updated the last modified date for relevant entries.
This commit is contained in:
Alex-larget
2026-03-16 17:18:49 +08:00
parent 219ae3b843
commit 9210b931c4
19 changed files with 948 additions and 338 deletions

View File

@@ -104,30 +104,28 @@ Page({
goBack() { getApp().goBackOrToHome() },
// 生成分享名片封面图(头像+昵称5:4 比例
// 生成分享名片封面图(参考:头像+昵称右,分隔线,四栏信息 5:4
async generateShareCard() {
const { avatar, nickname } = this.data
const { avatar, nickname, region, mbti, industry, position } = this.data
const userId = app.globalData.userInfo?.id
if (!userId) return
try {
const ctx = wx.createCanvasContext('shareCardCanvas', this)
const w = 500
const h = 400
// 背景渐变Soul 深色风格)
const pad = 32
// 背景(深灰卡片感)
const grd = ctx.createLinearGradient(0, 0, w, h)
grd.addColorStop(0, '#0F172A')
grd.addColorStop(0.5, '#050B14')
grd.addColorStop(0, '#1E293B')
grd.addColorStop(1, '#0F172A')
ctx.setFillStyle(grd)
ctx.fillRect(0, 0, w, h)
// 顶部装饰条
ctx.setFillStyle('#5EEAD4')
ctx.fillRect(0, 0, w, 4)
// 头像:居中偏上,圆形 120px
const avatarSize = 120
const avatarX = (w - avatarSize) / 2
const avatarY = 80
// 顶部区域:左头像 + 右昵称
const avatarSize = 100
const avatarX = pad + 10
const avatarY = 50
const avatarRadius = avatarSize / 2
const rightStart = avatarX + avatarSize + 28
const drawAvatar = () => new Promise((resolve) => {
if (avatar && avatar.startsWith('http')) {
wx.downloadFile({
@@ -156,22 +154,61 @@ Page({
}
})
await drawAvatar()
// 头像外圈描边
ctx.setStrokeStyle('#5EEAD4')
ctx.setLineWidth(3)
ctx.setStrokeStyle('rgba(94,234,212,0.5)')
ctx.setLineWidth(2)
ctx.beginPath()
ctx.arc(avatarX + avatarRadius, avatarY + avatarRadius, avatarRadius, 0, Math.PI * 2)
ctx.stroke()
// 昵称
// 右侧:昵称 + 个人名片
const displayName = (nickname || '').trim() || '创业者'
ctx.setFillStyle('#ffffff')
ctx.setFontSize(24)
ctx.setTextAlign('center')
ctx.fillText(displayName, w / 2, avatarY + avatarSize + 50)
// 副标题
ctx.setFillStyle('rgba(94,234,212,0.9)')
ctx.setFontSize(14)
ctx.fillText('Soul创业派对 · 名片', w / 2, avatarY + avatarSize + 78)
ctx.setFontSize(26)
ctx.setTextAlign('left')
ctx.fillText(displayName, rightStart, avatarY + 36)
ctx.setFillStyle('#94A3B8')
ctx.setFontSize(13)
ctx.fillText('个人名片', rightStart, avatarY + 62)
// 分隔线
const divY = 168
ctx.setStrokeStyle('rgba(255,255,255,0.08)')
ctx.setLineWidth(1)
ctx.beginPath()
ctx.moveTo(pad, divY)
ctx.lineTo(w - pad, divY)
ctx.stroke()
// 底部四栏:地区 | MBTI行业 | 职位
const labelGray = '#64748B'
const valueWhite = '#F1F5F9'
const rowH = 52
const colW = (w - pad * 2) / 2
const truncate = (text, maxW) => {
if (!text) return ''
ctx.setFontSize(15)
let m = ctx.measureText(text)
if (m.width <= maxW) return text
for (let i = text.length - 1; i > 0; i--) {
const t = text.slice(0, i) + '…'
if (ctx.measureText(t).width <= maxW) return t
}
return text[0] + '…'
}
const maxValW = colW - 16
const items = [
{ label: '地区', value: truncate((region || '').trim() || '未填写', maxValW), x: pad },
{ label: 'MBTI', value: (mbti || '').trim() || '未填写', x: pad + colW },
{ label: '行业', value: truncate((industry || '').trim() || '未填写', maxValW), x: pad },
{ label: '职位', value: truncate((position || '').trim() || '未填写', maxValW), x: pad + colW },
]
items.forEach((item, i) => {
const row = Math.floor(i / 2)
const baseY = divY + 36 + row * rowH
ctx.setFillStyle(labelGray)
ctx.setFontSize(12)
ctx.fillText(item.label, item.x, baseY - 8)
ctx.setFillStyle(valueWhite)
ctx.setFontSize(15)
ctx.fillText(item.value, item.x, baseY + 14)
})
ctx.draw(true, () => {
wx.canvasToTempFilePath({
canvasId: 'shareCardCanvas',
@@ -188,14 +225,14 @@ Page({
},
drawAvatarPlaceholder(ctx, x, y, size, nickname) {
ctx.setFillStyle('rgba(94,234,212,0.25)')
ctx.setFillStyle('rgba(94,234,212,0.2)')
ctx.beginPath()
ctx.arc(x + size / 2, y + size / 2, size / 2, 0, Math.PI * 2)
ctx.fill()
ctx.setFillStyle('#5EEAD4')
ctx.setFontSize(size * 0.45)
ctx.setFontSize(size * 0.42)
ctx.setTextAlign('center')
ctx.fillText((nickname || '?')[0], x + size / 2, y + size / 2 + size * 0.15)
ctx.fillText((nickname || '?')[0], x + size / 2, y + size / 2 + size * 0.14)
},
onShareAppMessage() {