Преглед изворни кода

feat: 添加圆形和圆角矩形绘制功能;优化文本绘制方法,支持多样式文本显示;更新页面配置以支持新功能

EvilDragon пре 1 месец
родитељ
комит
1426653bfc

+ 3 - 0
package.json

@@ -9,5 +9,8 @@
   "license": "ISC",
   "dependencies": {
     "wot-design-uni": "1.3.13"
+  },
+  "resolutions": {
+    "bin-wrapper": "npm:bin-wrapper-china"
   }
 }

+ 0 - 3
packages/app/package.json

@@ -80,9 +80,6 @@
       "stylelint --fix"
     ]
   },
-  "resolutions": {
-    "bin-wrapper": "npm:bin-wrapper-china"
-  },
   "dependencies": {
     "@dcloudio/uni-app": "3.0.0-alpha-4020820240920001",
     "@dcloudio/uni-app-harmony": "3.0.0-alpha-4020820240920001",

+ 79 - 1
packages/app/src/core/utils/canvas.ts

@@ -24,6 +24,23 @@ export class Canvas {
     return (this.size.width / this.designSize.width) * designPx
   }
 
+  /**
+   * 绘制圆形
+   */
+  Circle(color, designX, designY, designR) {
+    this.context.save()
+    this.context.beginPath()
+    this.context.arc(
+      this.px(designX) + this.px(designR),
+      this.px(designY) + this.px(designR),
+      this.px(designR),
+      0,
+      2 * Math.PI,
+    )
+    this.context.setFillStyle(color)
+    this.context.fill()
+  }
+
   CircleImage(img, designX, designY, designR) {
     this.context.save()
     this.context.beginPath()
@@ -59,9 +76,70 @@ export class Canvas {
     this.context.drawImage(img, 0, 0, this.size.width, this.size.height)
   }
 
-  FillText(text, color, designFontSize, designX, designY) {
+  FillText(text, color, designFontSize, designX, designY, align = 'left') {
     this.context.setFillStyle(color)
     this.context.setFontSize(this.px(designFontSize))
+    if (align === 'center') {
+      const textWidth = this.context.measureText(text).width
+      designX = designX - textWidth / 2 / (this.size.width / this.designSize.width)
+    }
     this.context.fillText(text, this.px(designX), this.px(designY))
   }
+
+  /**
+   * 绘制圆角矩形
+   */
+  RoundRect(color, designX, designY, designW, designH, designR) {
+    this.context.save()
+    this.context.beginPath()
+    this.context.arc(
+      this.px(designX) + this.px(designR),
+      this.px(designY) + this.px(designR),
+      this.px(designR),
+      Math.PI,
+      Math.PI * 1.5,
+    )
+    this.context.lineTo(this.px(designX) + this.px(designW) - this.px(designR), this.px(designY))
+    this.context.arc(
+      this.px(designX) + this.px(designW) - this.px(designR),
+      this.px(designY) + this.px(designR),
+      this.px(designR),
+      Math.PI * 1.5,
+      Math.PI * 2,
+    )
+    this.context.lineTo(
+      this.px(designX) + this.px(designW),
+      this.px(designY) + this.px(designH) - this.px(designR),
+    )
+    this.context.arc(
+      this.px(designX) + this.px(designW) - this.px(designR),
+      this.px(designY) + this.px(designH) - this.px(designR),
+      this.px(designR),
+      0,
+      Math.PI * 0.5,
+    )
+    this.context.lineTo(this.px(designX) + this.px(designR), this.px(designY) + this.px(designH))
+    this.context.arc(
+      this.px(designX) + this.px(designR),
+      this.px(designY) + this.px(designH) - this.px(designR),
+      this.px(designR),
+      Math.PI * 0.5,
+      Math.PI,
+    )
+    this.context.setFillStyle(color)
+    this.context.fill()
+  }
+
+  /**
+   * 绘制多水平的多个不同样式的文本 例如:'文本1: 123, 文本2: 456'
+   */
+  FillTexts(texts, colors, fontSizes, designX, designY, designSpacing) {
+    let x = designX
+    for (let i = 0; i < texts.length; i++) {
+      this.context.setFillStyle(colors[i])
+      this.context.setFontSize(this.px(fontSizes[i]))
+      this.context.fillText(texts[i], this.px(x), this.px(designY))
+      x += designSpacing[i]
+    }
+  }
 }

+ 1 - 0
packages/app/src/pages/home/spread/product-detail/index.vue

@@ -59,6 +59,7 @@ const handleConfirm = async () => {
 }
 onLoad(async (query: { id: string; title: string; item: string }) => {
   id.value = query.id
+  item.value = query.item
   uni.setNavigationBarTitle({ title: query.title })
   await setData()
 })

+ 1 - 1
packages/app/src/pages/login/index.vue

@@ -36,7 +36,7 @@ const getTestCode = async ({ detail }) => {
 }
 const handleTestLogin = async () => {
   // console.log('');
-  const { data } = await testLogin({ mobile: mobile.value, password: 'aaa123456' })
+  const { data } = await testLogin({ mobile: mobile.value, password: '123456' })
   setUserInfo({
     token: data.accessToken,
     userId: data.userId,

+ 4 - 0
packages/merchant/.eslintrc.cjs

@@ -80,6 +80,10 @@ module.exports = {
     },
     'import/resolver': {
       typescript: {},
+      alias: {
+        map: [['@', './src']],
+        extensions: ['.ts', '.js', '.jsx', '.json', '.vue'],
+      },
     },
   },
   globals: {

+ 0 - 3
packages/merchant/package.json

@@ -80,9 +80,6 @@
       "stylelint --fix"
     ]
   },
-  "resolutions": {
-    "bin-wrapper": "npm:bin-wrapper-china"
-  },
   "dependencies": {
     "@dcloudio/uni-app": "3.0.0-alpha-4020820240920001",
     "@dcloudio/uni-app-harmony": "3.0.0-alpha-4020820240920001",

+ 8 - 0
packages/merchant/src/pages.json

@@ -176,6 +176,14 @@
       }
     },
     {
+      "path": "pages/mine/agent/invite/index",
+      "type": "page",
+      "style": {
+        "navigationBarTitleText": "邀请好友",
+        "navigationBarBackgroundColor": "#ffffff"
+      }
+    },
+    {
       "path": "pages/mine/agent/settings/index",
       "type": "page",
       "style": {

+ 115 - 0
packages/merchant/src/pages/mine/agent/invite/index.vue

@@ -0,0 +1,115 @@
+<route lang="json">
+{
+  "style": {
+    "navigationBarTitleText": "邀请好友",
+    "navigationBarBackgroundColor": "#ffffff"
+  }
+}
+</route>
+<script setup lang="ts">
+import { getBroker } from '../../../../core/libs/requests'
+import { useUserStore } from '@/store/index'
+import { Canvas } from '@designer-hub/app/src/core/utils/canvas'
+import { storeToRefs } from 'pinia'
+
+const currentInstance = getCurrentInstance()
+const userStore = useUserStore()
+const { userInfo } = storeToRefs(userStore)
+const { data, run: setData } = useRequest(() =>
+  getBroker({ brokerId: userInfo.value.userId!.toString() }),
+)
+
+onLoad(async () => {
+  await setData()
+  const [bg, title, contentBg, icon1, icon2, icon3, icon4, icon5, avatar] = await Promise.all(
+    [
+      'https://image.zhuchaohui.com/zhucaohui/9352daa033edc343fd6cc983978857dd77386b573380871a4b7f9e9f3617f183.png',
+      'https://image.zhuchaohui.com/zhucaohui/f1f13041769ecdf462aa2ccc246fb7566bea6fe83aaf73717ee959629cfe0f8f.svg',
+
+      'https://image.zhuchaohui.com/zhucaohui/08abd942d9f5635aa3cfd60376706bc948cdaf556417fb3396204f7cdec42e30.png',
+
+      'https://image.zhuchaohui.com/zhucaohui/fc22d1bee4e1737dc0d592a065f277bec4a790496faa292c869f781e9c67a700.svg',
+      'https://image.zhuchaohui.com/zhucaohui/85594fe5a8b12dc815b3ea062e826de086ed204f840931980cd1bf5417d8b814.svg',
+      'https://image.zhuchaohui.com/zhucaohui/7c3e518ff2dcd2d4d39001e3970c492195d518c7f0015c86c00b9ac5e788e4f4.svg',
+      'https://image.zhuchaohui.com/zhucaohui/11b8448cc06352f796a49fbbc67e1eacfa7f382cb2507d066cd32b6f88f164fe.svg',
+      'https://image.zhuchaohui.com/zhucaohui/d9dc32881076a752a7ab72701321538ff0e10fbc0482a3b4f9e95c1b8a132aec.svg',
+      data.value.headImgUrl || '',
+    ].map((it) => uni.getImageInfo({ src: it }).then(({ path }) => path)),
+  )
+
+  const ctx = uni.createCanvasContext('qrcode', currentInstance)
+  const { width, height } = await new Promise<any>((resolve) => {
+    uni
+      .createSelectorQuery()
+      .in(currentInstance)
+      .select('#qrcode')
+      .fields({ node: true, size: true }, (res) => {
+        resolve(res)
+      })
+      .exec()
+  })
+  const canvas = new Canvas(ctx, { width, height }, { width: 351 })
+  canvas.FillImage(bg)
+  canvas.RoundRect('#5379EC', 0, 0, 352, 607, 16)
+  canvas.Image(title, 27, 31, 297, 22.3)
+
+  canvas.Image(icon1, 28, 69, 15, 15)
+  canvas.Image(icon2, 143, 69, 13, 13)
+  canvas.Image(icon3, 248, 69, 13, 13)
+  canvas.Image(icon4, 30, 100, 12, 12)
+  canvas.Image(icon5, 141, 96, 16, 16)
+
+  canvas.FillText('国内外设计游学', '#ffffff', 10, 46, 80)
+  canvas.FillText('线上获客工具', '#ffffff', 10, 159, 80)
+  canvas.FillText('设计赋能项目', '#ffffff', 10, 262, 80)
+  canvas.FillText('丰富线下活动', '#ffffff', 10, 46, 109)
+  canvas.FillText('周边商品好礼', '#ffffff', 10, 159, 109)
+
+  // canvas.Circle('#D9D9D9', 136, 129, 41)
+
+  canvas.Image(contentBg, 17, 128, 319, 461)
+  canvas.CircleImage(avatar, 140, 133, 37)
+
+  canvas.FillText(data.value.brokerName, '#000000D9', 18, 149, 228, 'center')
+
+  canvas.FillTexts(
+    ['邀请码:', data.value.inviteCode],
+    ['14px PingFang SC', '18px PingFang SC'],
+    ['rgba(0,0,0,0.65)', 'rgba(0,0,0,0.85)'],
+    0,
+    0,
+    '',
+  )
+  // const textSegments = [
+  //   { text: '邀请码:', font: '14px PingFang SC', color: 'rgba(0,0,0,0.65)' },
+  //   { text: data.value.inviteCode || '', font: '18px PingFang SC', color: 'rgba(0,0,0,0.85)' },
+  // ]
+
+  // // Calculate total text width
+  // let totalWidth = 0
+  // textSegments.forEach((segment) => {
+  //   ctx.font = segment.font
+  //   totalWidth += ctx.measureText(segment.text).width
+  // })
+
+  // // Starting x position for centered text
+  // let startX = (width - totalWidth) / 2
+  // const y = 246 // Fixed vertical position
+
+  // // Draw each text segment
+  // textSegments.forEach((segment) => {
+  //   ctx.font = segment.font
+  //   ctx.fillStyle = segment.color
+
+  //   ctx.fillText(segment.text, startX, y)
+  //   startX += ctx.measureText(segment.text).width // Move x position for next segment
+  // })
+
+  ctx.draw && ctx.draw()
+})
+</script>
+<template>
+  <div class="aspect-[0.58/1]">
+    <canvas class="w-full h-full" id="qrcode" canvas-id="qrcode"></canvas>
+  </div>
+</template>

+ 4 - 1
packages/merchant/src/pages/mine/components/agent-mine.vue

@@ -22,6 +22,9 @@ const { data: followData, run: setFollowData } = useRequest(() => getFollowStati
 const toSettings = () => {
   uni.navigateTo({ url: '/pages/mine/agent/settings/index' })
 }
+const toInvite = () => {
+  uni.navigateTo({ url: '/pages/mine/agent/invite/index' })
+}
 onMounted(async () => {
   await setAgent()
   await Promise.all([setYearTarget(), setdesignerData(), setFollowData()])
@@ -62,7 +65,7 @@ onMounted(async () => {
             ID:{{ agent.inviteCode }}
           </div>
         </div>
-        <div>
+        <div class="flex flex-col items-center" @click.stop="toInvite">
           <div class="w-[29px] h-[29px] relative">
             <wd-img width="28" height="28" :src="qrCode"></wd-img>
           </div>

+ 1 - 0
packages/merchant/src/types/uni-pages.d.ts

@@ -19,6 +19,7 @@ interface NavigateToOptions {
        "/pages/agent/designer/archives/index" |
        "/pages/agent/designer/points_details/index" |
        "/pages/agent/tasks/detail/index" |
+       "/pages/mine/agent/invite/index" |
        "/pages/mine/agent/settings/index" |
        "/pages/agent/designer/archives/basic-info/index" |
        "/pages/mine/merchant/orders/detail/index";

+ 2 - 1
packages/merchant/tsconfig.json

@@ -15,7 +15,8 @@
     },
     "outDir": "dist",
     "lib": ["esnext", "dom"],
-    "types": ["@dcloudio/types", "@types/wechat-miniprogram", "wot-design-uni/global.d.ts"]
+    "types": ["@dcloudio/types", "@types/wechat-miniprogram", "wot-design-uni/global.d.ts"],
+    "strict": true
   },
   "vueCompilerOptions": {
     "target": 3,

Разлика између датотеке није приказан због своје велике величине
+ 500 - 2804
pnpm-lock.yaml


Неке датотеке нису приказане због велике количине промена