소스 검색

```
feat(workflow): 实现工作流购买功能并优化国际化

- 添加工作流购买逻辑,包括余额检查和支付流程
- 新增 purchase API 接口调用
- 实现 confirmBuy 工具函数处理购买确认
- 更新下载工作流功能,集成购买验证流程

refactor(editor): 移除 BlockNoteEditor 调试日志

- 删除 onUpdateModelValue 回调中的 console.log
- 移除 BlockNoteEditorDialog 中的调试输出
- 清理 BlockNoteReact 组件的调试信息

i18n(common): 增加通用国际化词汇

- 添加 'fileAddressNotExist' 文件地址不存在提示
- 新增 'balanceNotEnough' 余额不足提示
- 添加 'use' 使用、'workflowPreview' 工作流预览等词汇
- 增加 'Detail' 详情、'free' 免费、'currentPrice' 当前价格

fix(fileUploader): 更新下载文件函数参数

- 修改 downloadFile 函数接收对象参数
- 添加国际化支持参数传递
- 修复文件下载功能的参数传递方式

style(workflowDetail): 优化工作流详情页面UI

- 使用国际化

zhangningning 1 개월 전
부모
커밋
8a926f435b

+ 1 - 1
.env.development

@@ -1,6 +1,6 @@
 # 乔功
 VITE_API_BASE_URL=http://192.168.100.134:8080/api
 # 高运甲
-VITE_API_BASE_URL=http://192.168.100.89:8080/api
+# VITE_API_BASE_URL=http://192.168.100.89:8080/api
 
 

+ 0 - 1
src/components/BlockNoteEditor.vue

@@ -32,7 +32,6 @@ const emit = defineEmits(['update:modelValue','getHtml']);
 const editorProps = ref({
   modelValue: props.modelValue,
   onUpdateModelValue: (value,html) => {
-    console.log('onUpdateModelValue', value,html);
     emit('update:modelValue', value);
     emit('getHtml', html);
   },

+ 0 - 1
src/components/BlockNoteEditorDialog.vue

@@ -91,7 +91,6 @@ const openDialog = (item) => {
   }else{
     title.value = t('common.add')
   }
-  console.log(editorContent.value)
 };
 
 defineExpose({

+ 3 - 1
src/components/FileUploader.vue

@@ -163,6 +163,8 @@
 import { ref, computed, watch } from 'vue'
 import DGTMessage from '@/utils/message'
 import { downloadFile } from '@/utils/util'
+import { useI18n } from 'vue-i18n' 
+const { t } = useI18n() 
 // import { 
 //   UploadFilled, 
 //   ZoomIn, 
@@ -430,7 +432,7 @@ const handlePreview = (file,index) => {
   if (isTextFile(file)) {
     if (file.url) {
       //浏览器下载
-      downloadFile(file.url, file.name)
+      downloadFile({url:file.url, fileName: file.name,t})
 
       // fetch(file.url)
       //   .then(response => response.text())

+ 0 - 3
src/components/react-components/BlockNoteReact.jsx

@@ -56,14 +56,11 @@ const BlockNoteReact = ({ modelValue, onUpdateModelValue, editable = true, curre
       formData.append('file', file);
       formData.append('directory', 'note');
       const response = await uploadFile(formData);
-      console.log('上传响应:', response);
-      // response.url = "http://jcxxpt.oss-cn-beijing.aliyuncs.com/id_card/2025/12/26/MFE1Qdqi9tXdc0cb704ec71877b97f0f0bde3a1bbb72_20251226111105A001.jpg";
       return response.url; // 返回图片 URL
     },
     // placeholder: "请输入内容(支持块级编辑、格式设置)"
   });
   editor.onMount(() => {
-    console.log('BlockNote 编辑器已挂载(React 版)', editor);
   });
 
 

+ 7 - 0
src/locales/en.js

@@ -84,6 +84,13 @@ export default {
     total: 'Total',
     demandCount: 'Demand Count',
     downloadWorkflow: 'Download Workflow',
+    fileAddressNotExist: 'File Address Not Exist',
+    balanceNotEnough: 'Your balance is not enough, whether to go to recharge?',
+    use:"Use",
+    workflowPreview:"Workflow Preview",
+    Detail:"Detail",
+    free:"Free",
+    currentPrice:"Current Price",
   },
   login: {
     smsLogin: 'SMS Login',

+ 7 - 0
src/locales/zh-CN.js

@@ -88,6 +88,13 @@ export default {
     total: '共',
     demandCount: '条需求',
     downloadWorkflow: '下载工作流',
+    fileAddressNotExist: '文件地址不存在',
+    balanceNotEnough: '您的余额不足,是否前往充值?',
+    use:"使用",
+    workflowPreview:"工作流预览",
+    Detail:"详情",
+    free:"免费",
+    currentPrice:"当前价格",
   },
   login: {
     smsLogin: '短信登录',

+ 40 - 15
src/pages/WorkflowDetail.vue

@@ -16,7 +16,7 @@
             </div>
             <div class="gap5">
               <img :src="shiyongIcon" alt="员工" style="width: 16px; height: 16px;">
-              <span class="font_size14">{{ruleForm.downCount ?? ''}} 使用</span>
+              <span class="font_size14">{{ruleForm.downCount ?? ''}} {{t('common.use')}}</span>
             </div>
             <div class="gap5">
               <img :src="yunIcon" alt="员工" style="width: 16px; height: 16px;">
@@ -34,10 +34,10 @@
         <div class="padding16 bg_color_fff border_radius_10 mt10">
           <div class="gap10">
             <div class="line_vertical"></div>
-            <div class="font_size20 bold">工作流预览</div>
+            <div class="font_size20 bold">{{$t('common.workflowPreview')}}</div>
           </div>
           <div class="mt20">
-            <img :src="item || ''" alt="工作流预览" v-for="(item, index) in coverImage" :key="index"
+            <img :src="item || ''" alt="" v-for="(item, index) in coverImage" :key="index"
             style="width: 100%; height: auto;" />
           </div>
         </div>
@@ -45,7 +45,7 @@
         <div class="padding16 bg_color_fff border_radius_10 mt10">
           <div class="gap10">
             <div class="line_vertical"></div>
-            <div class="font_size20 bold">详情</div>
+            <div class="font_size20 bold">{{$t('common.Detail')}}</div>
           </div>
           <BlockNoteEditor v-model="editorContent" :editable="false" class="mt20"/>
         </div>
@@ -56,13 +56,13 @@
           <div class="padding16 bg_color_fff border_radius_16 box_shadow_card">
             <div class="flex-center-between">
               <div class="flex-column">
-                <div class="font_size16">当前价格</div>
+                <div class="font_size16">{{$t('common.currentPrice')}}</div>
                 <div class="color_price">
                   <span class="font_size32">{{ruleForm.workflowPrice || 0}}</span> 
-                  <span>{{$t('common.mibi')}}</span>
+                  <span>{{$t('common.baomibi')}}</span>
                 </div>
               </div>
-              <el-button type="success" plain size="mini" v-if="ruleForm.workflowPrice === 0">免费</el-button>
+              <el-button type="success" plain size="mini" v-if="ruleForm.workflowPrice === 0">{{$t('common.free')}}</el-button>
             </div>
             <div class="mt20">
               <el-button type="primary" class="font_size16" size="large" style="width: 100%;">
@@ -80,13 +80,13 @@
           <!-- 工作流作者 -->
           <div class="padding16 bg_color_fff border_radius_16 box_shadow_card mt20">
             <div class="flex-center-between">
-              <div class="flex-between flex_1">
-                <el-avatar :size="50" :src=" ruleForm.userAvatar || appStore.avatarDefault " />
+              <div class="flex-center-between flex_1">
+                <el-avatar :size="50" :src=" ruleForm.userAvatar || appStore.avatarDefault"/>
                 <div class="ml10 flex_1">
                   <div class="font_size18 bold">{{ruleForm.nickName || ''}}</div>
-                  <div class="gap5 mt5">
+                  <!-- <div class="gap5 mt5">
                     <el-tag type="primary" v-for="item in 5" :key="item" >技能标签</el-tag>
-                  </div>
+                  </div> -->
                 </div>
               </div>
               <div>
@@ -147,12 +147,16 @@ import yiguanzhuIcon from '@/assets/imgs/yiguanzhu.png'
 import geshiIcon from '@/assets/imgs/geshi.png'
 import neicunIcon from '@/assets/imgs/neicun.png'
 import banbenIcon from '@/assets/imgs/banben.png'
-import { downloadFile } from '@/utils/util'
+import { downloadFile, confirmBuy } from '@/utils/util'
 
 import { getPublishDetail } from '@/api/publish.js'
+import { purchase } from '@/api/common.js'
 
 import BlockNoteEditor from '@/components/BlockNoteEditor.vue';
-import { useRoute } from 'vue-router'
+import { useI18n } from 'vue-i18n' 
+const { t } = useI18n() 
+import { useRouter, useRoute } from 'vue-router'
+const router = useRouter()
 const route = useRoute()
 import { useAppStore } from '@/pinia/appStore'
 const appStore = useAppStore()
@@ -179,7 +183,6 @@ const ruleForm = ref({
 
 onMounted(() => {
   getPublishDetail({id:publishId.value}).then(res => {
-    console.log(res)
     ruleForm.value = res.data || {};
     nextTick(() => {
       if(ruleForm.value.coverImage){
@@ -195,7 +198,29 @@ onMounted(() => {
 });
 // 下载工作流
 const downloadWorkflow = () => {
-  downloadFile(ruleForm.value.workflowFile, ruleForm.value.workflowTitle + '.json');
+  purchase({
+    buyType: 1,
+    publishId: publishId.value,
+  }).then(res => {
+    if(res.code === 200){
+      if(res.data?.buyFlag == 1){
+        if(res.data?.contentUrl){
+          downloadFile({url:res.data?.contentUrl,t});
+        }
+      }else{
+        confirmBuy({
+          callback:downloadWorkflow,
+          appStore,
+          router,
+          price:ruleForm.value.workflowPrice,
+          t,
+          productId:publishId.value,
+          orderType:'workflow_purchase',
+          payMethod:'BMI'
+        })
+      }
+    }
+  })
 };
 </script>
 

+ 1 - 1
src/pages/workflowTrade/workflowTrade.vue

@@ -110,7 +110,7 @@
               <div class="gap10">
                 <el-avatar :size="32" :src="appStore.avatar" />
                 <div class="font_size16 bold">{{item.nickName}}</div>
-                <div class="font_size14 gray mt2">{{item.createTime}} 发布</div>
+                <div class="font_size14 gray mt2">{{item.createTime}} {{$t('common.publish')}}</div>
               </div>
               <el-button type="primary" size="large" @click="submitSignUp({questId: item.questId,questUserId: item.questUserId},t)">
                 <img :src="zaixianbaomingIcon" alt="" class="mr10" style="width: 16px; height: 16px;">

+ 3 - 3
src/utils/util.js

@@ -2,9 +2,9 @@ import DGTMessage from '@/utils/message'
 import { signUp } from '@/api/apply.js'
 import { ElMessageBox } from 'element-plus'
 import { createOrder } from '@/api/order.js'
-export function downloadFile(url, fileName) {
+export function downloadFile({url, fileName='download',t}) {
   if (!url) {
-    DGTMessage.error('文件地址不存在');
+    DGTMessage.error(t('common.fileAddressNotExist'));
     return;
   }
   const link = document.createElement('a');
@@ -63,7 +63,7 @@ export function confirmBuy({
 }){
   const balance = appStore.userInfo?.[type] || 0;
   if(balance < price ){
-    ElMessageBox.confirm('您的余额不足,是否前往充值?', t('common.tip'), {
+    ElMessageBox.confirm(t('common.balanceNotEnough'), t('common.tip'), {
       confirmButtonText: t('common.confirm'),
       cancelButtonText: t('common.cancel'),
       type: 'warning'