Browse Source

新增产品配置

大大的豆芽 1 week ago
parent
commit
3253e99d0d
45 changed files with 760 additions and 351 deletions
  1. 124 0
      .idea/uiDesigner.xml
  2. 4 0
      admin-ui/src/assets/styles/ruoyi.scss
  3. 2 2
      admin-ui/src/components/pagesHeader/index.vue
  4. 300 163
      admin-ui/src/views/admin/product/productCenter.vue
  5. 3 3
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigTabController.java
  6. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDataGroupController.java
  7. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataGroupInfoService.java
  8. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/AlertControllerF.java
  9. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/CashControllerF.java
  10. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/CategoryControllerF.java
  11. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/ChatsC2CControllerF.java
  12. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/ChatsC2SControllerF.java
  13. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/CommentControllerF.java
  14. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/CouponControllerF.java
  15. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/CouponUserControllerF.java
  16. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/HelpControllerF.java
  17. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/MessageControllerF.java
  18. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/OrdersControllerF.java
  19. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/PageLayoutControllerF.java
  20. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/PayCallbackControllerF.java
  21. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/ProductCityControllerF.java
  22. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/ProductControllerF.java
  23. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/SearchControllerF.java
  24. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/ShopControllerF.java
  25. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/SpreadControllerF.java
  26. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/StatisticControllerF.java
  27. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserAddressControllerF.java
  28. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserBrowseControllerF.java
  29. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserControllerF.java
  30. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserLoginControllerF.java
  31. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserMoneyControllerF.java
  32. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserVipControllerF.java
  33. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserVisitorControllerF.java
  34. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/UserWorkerControllerF.java
  35. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/VipCategoryControllerF.java
  36. 1 1
      znyun-mod-primary/src/main/java/com/znyun/commons/api/VipVantageControllerF.java
  37. 13 5
      znyun-mod-primary/src/main/java/com/znyun/commons/controller/ProductControllerA.java
  38. 0 22
      znyun-mod-primary/src/main/java/com/znyun/commons/dao/ProductItemDao.java
  39. 16 0
      znyun-mod-primary/src/main/java/com/znyun/commons/domain/Product.java
  40. 0 72
      znyun-mod-primary/src/main/java/com/znyun/commons/domain/ProductItem.java
  41. 22 0
      znyun-mod-primary/src/main/java/com/znyun/commons/request/ProductRequest.java
  42. 15 1
      znyun-mod-primary/src/main/java/com/znyun/commons/response/ProductResponse.java
  43. 25 0
      znyun-mod-primary/src/main/java/com/znyun/commons/service/ProductService.java
  44. 163 11
      znyun-mod-primary/src/main/java/com/znyun/commons/service/impl/ProductServiceImpl.java
  45. 41 40
      znyun-mod-primary/src/main/java/com/znyun/utils/AttachmentUtil.java

+ 124 - 0
.idea/uiDesigner.xml

@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>

+ 4 - 0
admin-ui/src/assets/styles/ruoyi.scss

@@ -138,6 +138,10 @@
    color: inherit;
 }
 
+.el-message-box {
+   width: 750px;
+}
+
 .el-message-box__status + .el-message-box__message {
    word-break: break-word;
 }

+ 2 - 2
admin-ui/src/components/pagesHeader/index.vue

@@ -1,10 +1,10 @@
 <template>
   <el-card shadow="never" class="box-card">
     <div class="acea-row row-middle">
-      <div class="font-sm after-line" @click="goBack">
+      <!-- <div class="font-sm after-line" @click="goBack">
         <span class="el-icon-arrow-left"></span>
         <span class="pl10">返回</span>
-      </div>
+      </div> -->
       <span class="ht_title ml10">{{ title }}</span>
     </div>
   </el-card>

+ 300 - 163
admin-ui/src/views/admin/product/productCenter.vue

@@ -66,24 +66,6 @@
 
       <el-table-column prop="shopShortName" label="所属店铺" width="120" show-overflow-tooltip />
 
-      <el-table-column prop="oldPrice" label="原价" width="100">
-        <template slot-scope="{ row }">
-          <span>¥ {{ row.oldPrice.toFixed(2) }}</span>
-        </template>
-      </el-table-column>
-
-      <el-table-column prop="price" label="优惠价" width="100">
-        <template slot-scope="{ row }">
-          <span>¥ {{ row.price.toFixed(2) }}</span>
-        </template>
-      </el-table-column>
-
-      <el-table-column prop="memberPrice" label="会员价" width="100">
-        <template slot-scope="{ row }">
-          <span>¥ {{ row.memberPrice.toFixed(2) }}</span>
-        </template>
-      </el-table-column>
-
       <el-table-column prop="unit" label="单位" width="100">
         <template slot-scope="{ row }">
           <span>{{ row.unitNum + row.unit }}</span>
@@ -119,103 +101,58 @@
         <!-- 基础信息 -->
         <el-tab-pane label="基础信息" name="basic">
           <el-form :model="dialogForm" label-width="100px" class="dialog-form">
+            
             <el-row :gutter="20">
               <el-col :span="12">
-                <el-form-item label="服务名称" prop="name">
-                  <el-input v-model="dialogForm.name" placeholder="请输入服务名称" />
-                </el-form-item>
-              </el-col>
-              <el-col :span="12">
-                <el-form-item label="服务品类" prop="cateIds">
-                  <el-cascader v-model="dialogForm.cateIds" :options="categoryList" :props="categoryProps" :show-all-levels="false"
-                    placeholder="请选择服务品类" clearable style="width: 100%" />
-                </el-form-item>
-              </el-col>
-            </el-row>
-
-            <!-- <el-row :gutter="20">
-              <el-col :span="12">
-                <el-form-item label="服务模式" prop="serviceMode">
-                  <el-checkbox-group v-model="serviceModeList" @change="onChangeServiceModeCbx">
-                    <el-checkbox v-for="(item,index) in serviceModes" :key="index" :label="item">
-                      {{item}}
-                    </el-checkbox>
-                  </el-checkbox-group>
+                <el-form-item label="封面图" prop="image">
+                  <upload-image v-model="dialogForm.image" :mode="'attachment'" :boxSize="{width: '100px', height: '100px'}" :multiple="false" />
                 </el-form-item>
               </el-col>
               <el-col :span="12">
-                <el-form-item label="发布人" prop="userId">
-                  <el-input v-model="userName" placeholder="请选择发布人" @focus="showUsersDialog" readonly />
-                </el-form-item>
-              </el-col>
-            </el-row> -->
-
-            <el-row :gutter="20">
-              <el-col :span="24">
-                <el-form-item label="服务描述" prop="describes">
-                  <el-input v-model="dialogForm.describes" type="textarea" :rows="3" placeholder="请输入服务描述" />
+                <el-form-item label="详情图" prop="detailsImage">
+                  <upload-image v-model="detailsImageList" :mode="'attachment'" :boxSize="{width: '100px', height: '100px'}" :multiple="true" />
                 </el-form-item>
               </el-col>
             </el-row>
-
+            
             <el-row :gutter="20">
               <el-col :span="12">
-                <el-form-item label="预约价格" prop="appointmentPrice">
-                  <el-input-number v-model="dialogForm.appointmentPrice" :precision="2" :step="0.1" :min="0" style="width: 100%" />
-                </el-form-item>
-              </el-col>
-            </el-row>
-
-            <el-row :gutter="20">
-              <el-col :span="8">
-                <el-form-item label="最低时间" prop="minNum">
-                  <el-input-number v-model="dialogForm.minNum" :min="1" style="width: 100%" />
-                </el-form-item>
-              </el-col>
-              <el-col :span="8">
-                <el-form-item label="单位" prop="unit">
-                  <el-radio-group v-model="dialogForm.unit">
-                    <el-radio label="小时">小时</el-radio>
-                    <el-radio label="分钟">分钟</el-radio>
-                  </el-radio-group>
+                <el-form-item label="服务名称" prop="name">
+                  <el-input v-model="dialogForm.name" placeholder="请输入服务名称" />
                 </el-form-item>
               </el-col>
-              <el-col :span="8">
-                <el-form-item label="单位数量" prop="unitNum">
-                  <el-input-number v-model="dialogForm.unitNum" :min="10" style="width: 100%" />
+              <el-col :span="12">
+                <el-form-item label="服务品类" prop="cateIds">
+                  <el-cascader v-model="dialogForm.cateIds" :options="categoryList" :props="categoryProps" :show-all-levels="false"
+                    placeholder="请选择服务品类" clearable style="width: 100%" />
                 </el-form-item>
               </el-col>
             </el-row>
 
             <el-row :gutter="20">
               <el-col :span="24">
-                <el-form-item label="服务地区" prop="region">
-                  <el-cascader style="width: 100%" size="large" :options="regionData" v-model="storeAddress" :placeholder="storeAddre"
-                    @change="handleAddressChange" />
+                <el-form-item label="服务保障" prop="serviceProjects">
+                  <el-select v-model="dialogForm.serviceProjects" multiple placeholder="请选择服务保障" style="width: 100%">
+                    <el-option
+                      v-for="item in serviceProject"
+                      :key="item.id"
+                      :label="item.name"
+                      :value="item.id">
+                    </el-option>
+                  </el-select>
                 </el-form-item>
               </el-col>
             </el-row>
 
             <el-row :gutter="20">
               <el-col :span="24">
-                <el-form-item label="详细地址" prop="detailsAddress">
-                  <el-input v-model="dialogForm.detailsAddress" placeholder="请输入详细地址" @keydown.enter.native="setLocation" clearable />
+                <el-form-item label="服务描述" prop="describes">
+                  <el-input v-model="dialogForm.describes" type="textarea" :rows="3" placeholder="请输入服务描述" />
                 </el-form-item>
               </el-col>
             </el-row>
 
-            <el-row :gutter="20">
-              <el-col :span="12">
-                <el-form-item label="封面图" prop="image">
-                  <upload-image v-model="dialogForm.image" :mode="'attachment'" :boxSize="{width: '100px', height: '100px'}" :multiple="false" />
-                </el-form-item>
-              </el-col>
-              <el-col :span="12">
-                <el-form-item label="详情图" prop="detailsImage">
-                  <upload-image v-model="detailsImageList" :mode="'attachment'" :boxSize="{width: '100px', height: '100px'}" :multiple="true" />
-                </el-form-item>
-              </el-col>
-            </el-row>
+            
           </el-form>
         </el-tab-pane>
 
@@ -236,8 +173,7 @@
               </el-table-column>
               <el-table-column prop="salePrice" label="价格" width="120">
                 <template slot-scope="scope">
-                  <span v-if="scope.row.priceType === 1">¥{{ scope.row.salePrice }}</span>
-                  <span v-else>待定</span>
+                  <span>¥{{ scope.row.salePrice }}</span> 
                 </template>
               </el-table-column>
               <el-table-column prop="oldPrice" label="原价" width="120">
@@ -259,7 +195,7 @@
         <!-- 表单配置 -->
         <el-tab-pane label="表单配置" name="form">
           <div class="form-config-container">
-            <el-button type="primary" size="small" @click="addField">添加字段</el-button>
+            <el-button type="primary" size="small" @click="addField" style="margin-bottom: 10px;">添加字段</el-button>
             <el-form ref="formConfigForm" :model="formConfig" label-width="100px">
               <div v-for="(field, index) in formConfig.fields" :key="index" class="field-item">
                 <el-row :gutter="20">
@@ -275,8 +211,18 @@
                       <el-select v-model="field.type" placeholder="请选择字段类型" style="width: 100%" @change="handleFieldTypeChange(field)">
                         <el-option label="文本" value="text" />
                         <el-option label="数字" value="number" />
-                        <el-option label="选择" value="select" />
+                        <el-option label="下拉" value="select" />
                         <el-option label="多选" value="checkbox" />
+                        <el-option label="图片" value="upload" />
+                      </el-select>
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="6">
+                    <el-form-item :label="'是否必填'" :prop="'fields.' + index + '.required'"
+                      :rules="[{ required: true, message: '请选择是否必填', trigger: 'change' }]">
+                      <el-select v-model="field.required" placeholder="请选择是否必填" style="width: 100%" @change="handleFieldTypeChange(field)">
+                        <el-option label="是" :value="true" />
+                        <el-option label="否" :value="false" />
                       </el-select>
                     </el-form-item>
                   </el-col>
@@ -285,7 +231,7 @@
                       <el-input v-model="field.placeholder" placeholder="请输入提示文字" />
                     </el-form-item>
                   </el-col>
-                  <el-col :span="6">
+                  <el-col :span="24">
                     <el-form-item :label="'选项内容'" v-if="field.type === 'select' || field.type === 'checkbox'" :prop="'fields.' + index + '.options'"
                       :rules="[{ required: true, message: '请输入选项内容', trigger: 'blur' }]">
                       <el-input type="textarea" v-model="field.options" placeholder="请输入选项内容,多个选项用逗号分隔" :rows="3" />
@@ -300,14 +246,45 @@
           </div>
         </el-tab-pane>
 
+        <!-- 收费标准 -->
+        <el-tab-pane label="收费标准" name="cost">
+          <div class="cost-container">
+            <div class="cost-header">
+              <el-button type="primary" size="small" @click="addCostStandard">添加收费标准</el-button>
+            </div>
+            <el-table :data="costStandardList" border style="width: 100%">
+              <el-table-column prop="name" label="标准名称" width="180" />
+              <el-table-column prop="price" label="价格" width="120">
+                <template slot-scope="scope">
+                  <span>¥{{ scope.row.price }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column prop="remark" label="备注" show-overflow-tooltip />
+              <el-table-column label="操作" width="150">
+                <template slot-scope="scope">
+                  <el-button size="mini" @click="handleEditCostStandard(scope.row)">编辑</el-button>
+                  <el-button size="mini" type="danger" @click="handleDeleteCostStandard(scope.row)">删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+
+            <el-form :model="dialogForm" style="margin-top: 10px;">
+              <el-form-item label="收费标准说明" class="cost-form-item">
+                <WangEditor
+                  style="width: 100%"
+                  :height="300"
+                  :value="costContent"
+                  @input="getCostContent"
+                />
+              </el-form-item>
+            </el-form>
+          </div>
+        </el-tab-pane>
+
         <!-- 详情 -->
         <el-tab-pane label="详情" name="detail">
           <div class="detail-container">
             <el-form :model="dialogForm" label-width="100px">
-              <el-form-item label="服务详情">
-                <WangEditor style="width: 100%" :height="500" :value="content" @input="getEditorContent" />
-              </el-form-item>
-
               <el-form-item label="优惠券">
                 <div class="coupon-container">
                   <el-tag v-for="(tag, index) in dialogForm.coupons" :key="index" class="mr10 mb10" :closable="true" @close="handleCloseCoupon(tag)">
@@ -319,9 +296,14 @@
                   </el-button>
                 </div>
               </el-form-item>
+              <el-form-item label="服务详情">
+                <WangEditor style="width: 100%" :height="500" :value="content" @input="getEditorContent" />
+              </el-form-item>
             </el-form>
           </div>
         </el-tab-pane>
+
+        
       </el-tabs>
 
       <div slot="footer" class="dialog-footer">
@@ -343,8 +325,9 @@
             <el-radio :label="2">动态价格</el-radio>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="价格" prop="salePrice" v-if="specForm.priceType === 1">
+        <el-form-item label="价格" prop="salePrice">
           <el-input-number v-model="specForm.salePrice" :precision="2" :step="0.1" />
+          <div>如果是动态价格,则此处为首付款</div>
         </el-form-item>
         <el-form-item label="原价" prop="oldPrice" v-if="specForm.priceType === 1">
           <el-input-number v-model="specForm.oldPrice" :precision="2" :step="0.1" />
@@ -419,6 +402,45 @@
         :page-sizes="[5, 10, 20, 30, 40]" @pagination="getUserList" />
     </el-dialog>
 
+    <!-- 收费标准编辑弹窗 -->
+    <el-dialog
+      :title="costStandardDialogTitle"
+      :visible.sync="costStandardDialogVisible"
+      width="500px"
+    >
+      <el-form
+        :model="costStandardForm"
+        :rules="costStandardRules"
+        ref="costStandardForm"
+        label-width="100px"
+      >
+        <el-form-item label="标准名称" prop="name">
+          <el-input v-model="costStandardForm.name" />
+        </el-form-item>
+        <el-form-item label="价格" prop="price">
+          <el-input-number
+            v-model="costStandardForm.price"
+            :precision="2"
+            :step="0.1"
+            :min="0"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <el-input
+            type="textarea"
+            v-model="costStandardForm.remark"
+            :rows="3"
+            placeholder="请输入备注信息"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="costStandardDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submitCostStandardForm">确 定</el-button>
+      </div>
+    </el-dialog>
+
     <pagination v-show="tableData.total" :total="tableData.total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
       @pagination="getList" />
   </div>
@@ -461,6 +483,7 @@ export default {
       },
       categoryValue: '',
       categoryList: [],
+      serviceProject: [],
       categoryProps: {
         children: 'children',
         label: 'name',
@@ -508,7 +531,10 @@ export default {
         detailsAddress: '',
         describes: '',
         couponIds: [],
-        coupons: []
+        coupons: [],
+        costStandards: [],
+        costContent: '',
+        serviceProjects: []
       },
       userName: '',
       longitude: '',
@@ -565,12 +591,30 @@ export default {
       formConfig: {
         fields: []
       },
-      content: ''
+      content: '',
+      costStandardList: [],
+      costContent: '',
+      costStandardDialogVisible: false,
+      costStandardDialogTitle: '添加收费标准',
+      costStandardForm: {
+        name: '',
+        price: 0,
+        remark: ''
+      },
+      costStandardRules: {
+        name: [
+          { required: true, message: '请输入标准名称', trigger: 'blur' }
+        ],
+        price: [
+          { required: true, message: '请输入价格', trigger: 'blur' }
+        ]
+      }
     }
   },
   mounted() {
     this.getCategoryList()
     this.getList()
+    this.getServiceProject()
   },
   methods: {
     // 原有的方法保持不变
@@ -588,6 +632,17 @@ export default {
       this.multiple = !selection.length
       this.single = selection.length !== 1
     },
+    getServiceProject(){
+      this.request({
+        url: '/system/group/data/selectByKey?key=service_guarantee',
+        method: 'get'
+      }).then(res => {
+        if (res.code === 200) {
+          this.serviceProject = res.data
+        }
+      }).catch(() => {
+      })
+    },
     getList() {
       this.loading = true
       this.request({
@@ -687,25 +742,43 @@ export default {
         this.dialogForm[k] = rows[k]
       }
       this.content = rows.content
-      this.userName = rows.userName
-      if (this.dialogForm.detailsImage !== '' && this.dialogForm.detailsImage != null) {
-        this.detailsImageList = this.dialogForm.detailsImage.split(',')
+      this.costContent = rows.costContent || ''
+      this.costStandardList = rows.costStandards || []
+      
+      // 处理服务保障数据
+      if (rows.serviceProjects) {
+        this.dialogForm.serviceProjects = rows.serviceProjects.split(',').map(id => parseInt(id))
+      } else {
+        this.dialogForm.serviceProjects = []
       }
-      this.dialogForm.cateIds = rows.cateId.split(',')
-      this.serviceModeList = this.dialogForm.serviceMode.split(',')
-      this.storeAddress = []
-      this.storeAddre = ''
-      if (!this.isEmpty(this.dialogForm.province)) {
-        this.storeAddre += this.dialogForm.province
-        this.storeAddre += '/'
+      
+      // 处理规格数据
+      if (rows.specs) {
+        try {
+          this.specList = JSON.parse(rows.specs)
+        } catch (e) {
+          this.specList = []
+        }
+      } else {
+        this.specList = []
       }
-      if (!this.isEmpty(this.dialogForm.city)) {
-        this.storeAddre += this.dialogForm.city
-        this.storeAddre += '/'
+      
+      // 处理表单配置
+      if (rows.formConfig) {
+        try {
+          const formConfig = JSON.parse(rows.formConfig)
+          this.formConfig.fields = formConfig
+        } catch (e) {
+          this.formConfig.fields = []
+        }
+      } else {
+        this.formConfig.fields = []
       }
-      if (!this.isEmpty(this.dialogForm.district)) {
-        this.storeAddre += this.dialogForm.district
+      
+      if (this.dialogForm.detailsImage !== '' && this.dialogForm.detailsImage != null) {
+        this.detailsImageList = this.dialogForm.detailsImage.split(',')
       }
+      this.dialogForm.cateIds = rows.cateId.split(',')
       this.dialogTitle = '编辑服务'
       this.dialogVisible = true
       this.dialogEditVisible = true
@@ -725,18 +798,36 @@ export default {
         this.dialogForm.detailsImage = this.detailsImageList.toString()
         this.dialogForm.cateId = this.dialogForm.cateIds.join(',')
         this.dialogForm.content = this.content
-
-        // 添加表单配置
-        if (this.activeTab === 'form') {
-          this.handleFormConfig().then(formConfig => {
+        this.dialogForm.costContent = this.costContent
+        this.dialogForm.costStandards = this.costStandardList
+        
+        // 处理服务保障数据
+        this.dialogForm.serviceProjects = this.dialogForm.serviceProjects.join(',')
+        
+        // 添加规格数据
+        this.dialogForm.specs = this.specList
+
+        // 处理表单配置
+        this.$refs.formConfigForm.validate(valid => {
+          if (valid) {
+            const formConfig = this.formConfig.fields.map(field => {
+              const config = {
+                name: field.name,
+                type: field.type,
+                placeholder: field.placeholder,
+                required: field.required,
+                options: field.options
+              }
+              return config
+            })
             this.dialogForm.formConfig = formConfig
+            
+            // 提交请求
             this.submitRequest(url)
-          }).catch(error => {
-            this.$message.error(error.message || '表单验证失败')
-          })
-        } else {
-          this.submitRequest(url)
-        }
+          } else {
+            this.$message.error('表单配置验证失败')
+          }
+        })
       }
     },
     submitRequest(url) {
@@ -755,50 +846,17 @@ export default {
       })
     },
     validateForm() {
-      if (this.dialogForm.cateIds.length === 0) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请选择服务分类' })
-        return false
-      }
-      if (this.isEmpty(this.dialogForm.serviceMode)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请选择服务模式' })
-        return false
-      }
+
+
       if (this.isEmpty(this.dialogForm.image)) {
         this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请上传服务封面图' })
         return false
       }
-      if (this.isEmpty(this.dialogForm.userId)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请选择发布人' })
-        return false
-      }
+
       if (this.isEmpty(this.dialogForm.name)) {
         this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请输入服务名称' })
         return false
       }
-      if (this.isEmpty(this.dialogForm.oldPrice)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请输入发布价格' })
-        return false
-      }
-      if (this.isEmpty(this.dialogForm.price)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请输入接单价格' })
-        return false
-      }
-      if (this.isEmpty(this.dialogForm.memberPrice)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请输入会员价格' })
-        return false
-      }
-      if (this.isEmpty(this.dialogForm.minNum)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请输入最低服务时间' })
-        return false
-      }
-      if (this.isEmpty(this.dialogForm.unitNum)) {
-        this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请输入单位数量' })
-        return false
-      }
-      if (this.isEmpty(this.dialogForm.city)) {
-        // this.$notify({ title: '提示', duration: 1800, type: 'warning', message: '请选择服务地区' })
-        // return false
-      }
       return true
     },
     hideDialog() {
@@ -1027,7 +1085,7 @@ export default {
       this.dialogForm.coupons = [];
       this.dialogForm.couponIds = [];
       this.request({
-        url: '/api/admin/coupon/product/list',
+        url: '/api/admin/product/info',
         method: 'get',
         params: { productId: productId }
       }).then(res => {
@@ -1187,7 +1245,6 @@ export default {
                 placeholder: field.placeholder,
                 required: field.required
               }
-
               if (field.type === 'select' || field.type === 'checkbox') {
                 config.options = field.options.split(',').map(opt => opt.trim()).filter(opt => opt)
               }
@@ -1223,6 +1280,56 @@ export default {
         3: '已拒绝'
       }
       return statusMap[status] || '未知'
+    },
+    // 收费标准相关方法
+    addCostStandard() {
+      this.costStandardDialogTitle = '添加收费标准'
+      this.costStandardForm = {
+        name: '',
+        price: 0,
+        remark: ''
+      }
+      this.costStandardDialogVisible = true
+    },
+
+    handleEditCostStandard(row) {
+      this.costStandardDialogTitle = '编辑收费标准'
+      this.costStandardForm = { ...row }
+      this.costStandardDialogVisible = true
+    },
+
+    handleDeleteCostStandard(row) {
+      this.$confirm('确认删除该收费标准?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        const index = this.costStandardList.findIndex(item => item === row)
+        if (index > -1) {
+          this.costStandardList.splice(index, 1)
+        }
+      })
+    },
+
+    submitCostStandardForm() {
+      this.$refs.costStandardForm.validate((valid) => {
+        if (valid) {
+          if (this.costStandardDialogTitle === '添加收费标准') {
+            this.costStandardList.push({ ...this.costStandardForm })
+          } else {
+            const index = this.costStandardList.findIndex(item => item.name === this.costStandardForm.name)
+            if (index > -1) {
+              this.costStandardList.splice(index, 1, { ...this.costStandardForm })
+            }
+          }
+          this.costStandardDialogVisible = false
+        }
+      })
+    },
+
+    getCostContent(content) {
+      this.costContent = content
+      this.dialogForm.costContent = content
     }
   },
 
@@ -1231,7 +1338,7 @@ export default {
 
 <style>
 .customWidth {
-  width: 80% !important;
+  width: 85% !important;
 }
 
 .dialog-form {
@@ -1285,6 +1392,36 @@ export default {
   height: 500px !important;
 }
 
+::v-deep .w-e-toolbar {
+  border-bottom: 1px solid #dcdfe6;
+}
+
+.cost-container {
+  padding: 20px;
+}
+
+.cost-header {
+  margin-bottom: 20px;
+}
+
+.cost-form-item {
+  display: flex;
+  flex-direction: column;
+}
+
+.cost-form-item .el-form-item__label {
+  text-align: left;
+  margin-bottom: 10px;
+}
+
+.cost-form-item .el-form-item__content {
+  margin-left: 0 !important;
+}
+
+::v-deep .w-e-text-container {
+  height: 300px !important;
+}
+
 ::v-deep .w-e-toolbar {
   border-bottom: 1px solid #dcdfe6;
 }

+ 3 - 3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigTabController.java

@@ -248,7 +248,7 @@ public class SysConfigTabController extends BaseController {
         map.put("status", true);
         map.put("method", "POST");
         map.put("info", "");
-        map.put("action", "/mapi/system/configTab/saveForm/" + tabId);
+        map.put("action", "/system/configTab/saveForm/" + tabId);
         List<DataGroupRules> rulesList = new ArrayList<>();
         DataGroupRules info = DataGroupRules.create("input", "info", "配置名称", null, null);
         DataGroupRules menuName = DataGroupRules.create("input", "menu_name", "字段变量", "例如:site_url", null);
@@ -358,7 +358,7 @@ public class SysConfigTabController extends BaseController {
         map.put("status", true);
         map.put("method", "POST");
         map.put("info", "");
-        map.put("action", "/mapi/system/configTab/editForm/" + id);
+        map.put("action", "/system/configTab/editForm/" + id);
         List<DataGroupRules> rulesList = new ArrayList<>();
         DataGroupRules info = DataGroupRules.create("input", "info", "配置名称", null, sysConfigRecord.getInfo());
         DataGroupRules menuName = DataGroupRules.create("input", "menu_name", "字段变量", "例如:site_url", sysConfigRecord.getMenuName());
@@ -483,7 +483,7 @@ public class SysConfigTabController extends BaseController {
         Map map = new HashMap();
         map.put("method", "POST");
         map.put("info", "");
-        map.put("action", "/mapi/system/configTab/save_basics/" + tabId);
+        map.put("action", "/system/configTab/save_basics/" + tabId);
         map.put("rules", rulesList);
         return success(map);
     }

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDataGroupController.java

@@ -297,7 +297,7 @@ public class SysDataGroupController extends BaseController {
         map.put("status", true);
         map.put("method", "POST");
         map.put("info", "");
-        map.put("action", "/mapi/system/group/data/saveForm");
+        map.put("action", "/system/group/data/saveForm");
         List<DataGroupRules> rulesList = new ArrayList<>();
         DataGroupRules status = DataGroupRules.createStatusHeader(1);
         DataGroupRules sort = DataGroupRules.createSortHeader(1);
@@ -327,7 +327,7 @@ public class SysDataGroupController extends BaseController {
         map.put("status", true);
         map.put("method", "POST");
         map.put("info", "");
-        map.put("action", "/mapi/system/group/data/updateForm/" + id);
+        map.put("action", "/system/group/data/updateForm/" + id);
         JSONObject jsonObject = JSONUtil.parseObj(sysDataGroupInfo.getValue());
         List<DataGroupRules> rulesList = new ArrayList<>();
         DataGroupRules status = DataGroupRules.createStatusHeader(sysDataGroupInfo.getStatus());

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataGroupInfoService.java

@@ -2,6 +2,7 @@ package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.system.domain.SysDataGroupInfo;
+import org.apache.poi.ss.formula.functions.T;
 
 import java.util.List;
 
@@ -63,7 +64,6 @@ public interface ISysDataGroupInfoService extends IService<SysDataGroupInfo> {
      */
     public int deleteSysDataGroupInfoById(Integer id);
 
-
     /**
      * 修改组合数据详情状态
      *

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/AlertControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/AlertControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/CashControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/CashControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/CategoryControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/CategoryControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.page.TableDataInfo;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/ChatsC2CControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/ChatsC2CControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/ChatsC2SControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/ChatsC2SControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/CommentControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/CommentControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/CouponControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/CouponControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import io.swagger.annotations.Api;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/CouponUserControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/CouponUserControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/HelpControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/HelpControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/MessageControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/MessageControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/OrdersControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/OrdersControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/PageLayoutControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/PageLayoutControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.page.TableDataInfo;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/PayCallbackControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/PayCallbackControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import io.swagger.annotations.Api;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/ProductCityControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/ProductCityControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/ProductControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/ProductControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/SearchControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/SearchControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/ShopControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/ShopControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/SpreadControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/SpreadControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.znyun.utils.SenInfoCheckUtil;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/StatisticControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/StatisticControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserAddressControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserAddressControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserBrowseControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserBrowseControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserLoginControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserLoginControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserMoneyControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserMoneyControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserVipControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserVipControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserVisitorControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserVisitorControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/UserWorkerControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/UserWorkerControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/VipCategoryControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/VipCategoryControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.page.TableDataInfo;

+ 1 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/controller/VipVantageControllerF.java → znyun-mod-primary/src/main/java/com/znyun/commons/api/VipVantageControllerF.java

@@ -1,4 +1,4 @@
-package com.znyun.commons.controller;
+package com.znyun.commons.api;
 
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.page.TableDataInfo;

+ 13 - 5
znyun-mod-primary/src/main/java/com/znyun/commons/controller/ProductControllerA.java

@@ -4,6 +4,7 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.ResResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.znyun.commons.request.ProductRequest;
+import com.znyun.commons.response.ProductResponse;
 import com.znyun.commons.service.ProductService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -53,33 +54,40 @@ public class ProductControllerA extends BaseController {
         return toDataTable(productService.listBy(shopId, city, category, serviceMode, userId, userName, status, shopName, like, categorySub));
     }
 
+    @ApiOperation("按照指定条件查询")
+    @RequestMapping(value = "/info", method = RequestMethod.GET)
+    public ResResult listBy(@RequestParam @ApiParam("产品id") Integer productId) {
+        ProductResponse productResponse = productService.getInfoById(productId);
+        return ResResult.success(productResponse);
+    }
+
     @ApiOperation("修改状态")
     @RequestMapping(value = "/changeStatus", method = RequestMethod.POST)
-    public ResResult changeStatus(@RequestParam(required = true) @ApiParam("服务ID") Integer id){
+    public ResResult changeStatus(@RequestParam(required = true) @ApiParam("服务ID") Integer id) {
         return toResult(productService.changeStatus(id));
     }
 
     @ApiOperation("修改首页是否推荐")
     @RequestMapping(value = "/changeRecommend", method = RequestMethod.POST)
-    public ResResult changeRecommend(@RequestParam(required = true) @ApiParam("服务ID") Integer id){
+    public ResResult changeRecommend(@RequestParam(required = true) @ApiParam("服务ID") Integer id) {
         return toResult(productService.changeRecommend(id));
     }
 
     @ApiOperation("编辑服务信息")
     @RequestMapping(value = "/update", method = RequestMethod.POST)
-    public ResResult update(@RequestBody ProductRequest request){
+    public ResResult update(@RequestBody ProductRequest request) {
         return toResult(productService.updateBy(request));
     }
 
     @ApiOperation("删除服务信息")
     @RequestMapping(value = "/delete", method = RequestMethod.POST)
-    public ResResult delete(@RequestParam(required = true) @ApiParam("服务ID") Integer id){
+    public ResResult delete(@RequestParam(required = true) @ApiParam("服务ID") Integer id) {
         return toResult(productService.removeById(id));
     }
 
     @ApiOperation("假删除服务信息")
     @RequestMapping(value = "/fDelete", method = RequestMethod.POST)
-    public ResResult fDelete(@RequestParam(required = true) @ApiParam("服务ID") Integer id){
+    public ResResult fDelete(@RequestParam(required = true) @ApiParam("服务ID") Integer id) {
         return toResult(productService.fakeDelete(id));
     }
 

+ 0 - 22
znyun-mod-primary/src/main/java/com/znyun/commons/dao/ProductItemDao.java

@@ -1,22 +0,0 @@
-package com.znyun.commons.dao;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.znyun.commons.domain.Product;
-import com.znyun.commons.domain.ProductItem;
-import com.znyun.commons.response.ProductResponse;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * ----------------------------------------------------------------------
- * | Copyright (c) 2019~2022 智能云科技 znyun.net.cn All rights reserved. |
- * | 面向系统:节省您的时间,拓展您的空间                                     |
- * | License     :开源仅供学习,正式版源码购买后方可授权商用                  |
- * | Author      :智能云团队 <2701596751@qq.com>                         |
- * ----------------------------------------------------------------------
- */
-public interface ProductItemDao extends BaseMapper<ProductItem> {
-
-}

+ 16 - 0
znyun-mod-primary/src/main/java/com/znyun/commons/domain/Product.java

@@ -15,6 +15,7 @@ import lombok.experimental.Accessors;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 /**
  * ----------------------------------------------------------------------
@@ -91,6 +92,16 @@ public class Product implements Serializable {
     /** 数据组字段以及类型(json数据) */
     private String productFields;
 
+    /**
+     * 服务保障数组,多个用逗号隔开
+     */
+    @ApiModelProperty(value = "服务保障")
+    private String serviceProjects;
+
+    @ApiModelProperty(value = "服务保障名称列表")
+    @TableField(exist = false)
+    private List<String> serviceProjectNames;
+
     @ApiModelProperty(value = "状态 0:进行中 1:待审核 2:已下架 3:拒绝")
     @TableField("status")
     protected Integer status;
@@ -139,6 +150,11 @@ public class Product implements Serializable {
     @TableField("audit_content")
     protected String auditContent;
 
+
+    @ApiModelProperty(value = "收费标准内容")
+    @TableField("cost_content")
+    protected String costContent;
+
     @ApiModelProperty(value = "单位")
     @TableField("unit")
     protected String unit;

+ 0 - 72
znyun-mod-primary/src/main/java/com/znyun/commons/domain/ProductItem.java

@@ -1,72 +0,0 @@
-package com.znyun.commons.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.experimental.Accessors;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * ----------------------------------------------------------------------
- * | Copyright (c) 2019~2022 智能云科技 znyun.net.cn All rights reserved. |
- * | 面向系统:节省您的时间,拓展您的空间                                     |
- * | License     :开源仅供学习,正式版源码购买后方可授权商用                  |
- * | Author      :智能云团队 <2701596751@qq.com>                         |
- * ----------------------------------------------------------------------
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-@Accessors(chain = true)
-@TableName("zny_product_item")
-@ApiModel(value="ProductItem对象", description="ProductItem表")
-public class ProductItem implements Serializable {
-
-    protected static final long serialVersionUID = 1L;
-
-    @ApiModelProperty(value = "zny_product表ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    protected Integer id;
-
-    @ApiModelProperty(value = "商品id")
-    @TableField("product_id")
-    protected Integer productId;
-
-    @ApiModelProperty(value = "产品子项名称")
-    @TableField("name")
-    protected String itemName;
-
-    @ApiModelProperty(value = "价格模式 1:固定价格 2:动态价格")
-    @TableField("price_type")
-    protected Integer priceType;
-
-    @ApiModelProperty(value = "产品价格")
-    @TableField("sale_price")
-    protected BigDecimal salePrice;
-
-    @ApiModelProperty(value = "原价")
-    @TableField("old_price")
-    protected BigDecimal oldPrice;
-
-    @ApiModelProperty(value = "状态 0:下架 1:上架")
-    @TableField("status")
-    protected Integer status;
-
-    @ApiModelProperty(value = "更新时间")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @TableField("update_time")
-    protected Date updateTime;
-
-    @ApiModelProperty(value = "创建时间")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @TableField("create_time")
-    protected Date createTime;
-}

+ 22 - 0
znyun-mod-primary/src/main/java/com/znyun/commons/request/ProductRequest.java

@@ -1,5 +1,9 @@
 package com.znyun.commons.request;
 
+import com.znyun.commons.domain.ProductCostStandard;
+import com.znyun.commons.domain.ProductField;
+import com.znyun.commons.domain.ProductItem;
+import com.znyun.commons.domain.ServiceProject;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.ToString;
@@ -109,4 +113,22 @@ public class ProductRequest implements Serializable {
 
     @ApiModelProperty(value = "优惠券id集合")
     private List<Integer> couponIds;
+
+    @ApiModelProperty(value = "规格列表")
+    private List<ProductItem> specs;
+
+    @ApiModelProperty(value = "表单配置")
+    private List<ProductField> formConfig;
+
+    @ApiModelProperty(value = "收费标准列表")
+    private List<ProductCostStandard> costStandards;
+
+    @ApiModelProperty(value = "收费标准说明")
+    private String costContent;
+
+    @ApiModelProperty(value = "服务保障")
+    private String serviceProjects;
+
+    @ApiModelProperty(value = "服务保障名称列表")
+    private List<ServiceProject> serviceProjectList;
 }

+ 15 - 1
znyun-mod-primary/src/main/java/com/znyun/commons/response/ProductResponse.java

@@ -1,10 +1,12 @@
 package com.znyun.commons.response;
 
-import com.znyun.commons.domain.Product;
+import com.znyun.commons.domain.*;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * ----------------------------------------------------------------------
@@ -27,4 +29,16 @@ public class ProductResponse extends Product implements Serializable {
     private String shopShortName;
 
     private String category;
+
+    @ApiModelProperty(value = "规格列表")
+    private List<ProductItem> specs;
+
+    @ApiModelProperty(value = "表单配置")
+    private List<ProductField> formConfig;
+
+    @ApiModelProperty(value = "收费标准列表")
+    private List<ProductCostStandard> costStandards;
+
+    @ApiModelProperty(value = "服务保障名称列表")
+    private List<ServiceProject> serviceProjectList;
 }

+ 25 - 0
znyun-mod-primary/src/main/java/com/znyun/commons/service/ProductService.java

@@ -186,4 +186,29 @@ public interface ProductService extends IService<Product> {
      * @return
      */
     Integer getValidNum();
+
+    /**
+     * 根据ID获取产品信息(包含规格、表单配置、收费标准等)
+     */
+    Product getById(Integer id);
+
+    /**
+     * 根据ID获取产品信息(包含规格、表单配置、收费标准等)
+     */
+    ProductResponse getInfoById(Integer id);
+
+    /**
+     * 删除产品
+     */
+    boolean removeBy(Integer id);
+
+    /**
+     * 获取产品列表
+     */
+    List<ProductRequest> listBy(ProductRequest dataRequest);
+
+    /**
+     * 获取产品总数
+     */
+    long countBy(ProductRequest dataRequest);
 }

+ 163 - 11
znyun-mod-primary/src/main/java/com/znyun/commons/service/impl/ProductServiceImpl.java

@@ -4,11 +4,14 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.system.domain.SysDataGroupInfo;
+import com.ruoyi.system.service.ISysDataGroupInfoService;
 import com.znyun.common.constants.Constants;
 import com.znyun.common.constants.MessageConstants;
 import com.znyun.common.constants.ProductConstants;
@@ -31,6 +34,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import com.alibaba.fastjson.JSON;
+import org.springframework.beans.factory.annotation.Autowired;
+
 /**
  * ----------------------------------------------------------------------
  * | Copyright (c) 2019~2022 智能云科技 znyun.net.cn All rights reserved. |
@@ -64,6 +70,12 @@ public class ProductServiceImpl extends ServiceImpl<ProductDao, Product> impleme
 
     private AttachmentUtil attachmentUtil;
 
+    private ProductItemService productItemService;
+    private ProductFieldService productFieldService;
+    private ProductCostStandardService productCostStandardService;
+
+    private ISysDataGroupInfoService sysDataGroupInfoService;
+
     /**
      * 产品Simple列表
      *
@@ -145,7 +157,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductDao, Product> impleme
     public List<Product> listByIds(List<Integer> productIds) {
         LambdaQueryWrapper<Product> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.in(Product::getId, productIds);
-        queryWrapper.eq(Product::getIsDel,false);
+        queryWrapper.eq(Product::getIsDel, false);
         return list(queryWrapper);
     }
 
@@ -306,22 +318,65 @@ public class ProductServiceImpl extends ServiceImpl<ProductDao, Product> impleme
         product.setImage(attachmentUtil.clearPrefix(product.getImage()));
         product.setSliderImage(attachmentUtil.clearPrefix(product.getSliderImage()));
         product.setDetailsImage(attachmentUtil.clearPrefix(product.getDetailsImage()));
+        if (CollUtil.isNotEmpty(dataRequest.getFormConfig())) {
+            product.setProductFields(JSON.toJSONString(dataRequest.getFormConfig()));
+        }
 
-        if(StrUtil.isNotBlank(dataRequest.getCateId())) {
+        if (StrUtil.isNotBlank(dataRequest.getCateId())) {
             List<Integer> cateIds = ZnyunUtil.stringToArray(dataRequest.getCateId());
             List<Category> categories = categoryService.listByIds(cateIds);
             List<String> cateNames = categories.stream().map(Category::getName).distinct().collect(Collectors.toList());
             product.setCategoryDefSub(String.join(",", cateNames));
             product.setCategoryDef(product.getCategoryDefSub());
-
-            /*List<Category> categories2 = categoryService.listParentByIds(cateIds);
-            List<String> cateNames2 = categories2.stream().map(Category::getName).distinct().collect(Collectors.toList());
-            product.setCategoryDef(String.join(",", cateNames2));*/
         }
 
         Boolean execute = transactionTemplate.execute(e -> {
+            // 更新产品基本信息
             updateById(product);
 
+            // 处理规格
+            if (CollUtil.isNotEmpty(dataRequest.getSpecs())) {
+                // 删除原有规格
+                productItemService.removeByProductId(product.getId());
+                // 保存新规格
+                List<ProductItem> specs = dataRequest.getSpecs().stream()
+                        .map(spec -> {
+                            spec.setProductId(product.getId());
+                            return spec;
+                        })
+                        .collect(Collectors.toList());
+                productItemService.saveBatch(specs);
+            }
+
+            // 处理表单配置
+//            if (CollUtil.isNotEmpty(dataRequest.getFormConfig())) {
+//                // 删除原有表单配置
+//                productFieldService.removeByProductId(product.getId());
+//                // 保存新表单配置
+//                List<ProductField> fields = dataRequest.getFormConfig().stream()
+//                    .map(field -> {
+//                        field.setProductId(product.getId());
+//                        return field;
+//                    })
+//                    .collect(Collectors.toList());
+//                productFieldService.saveBatch(fields);
+//            }
+
+            // 处理收费标准
+            if (CollUtil.isNotEmpty(dataRequest.getCostStandards())) {
+                // 删除原有收费标准
+                productCostStandardService.removeByProductId(product.getId());
+                // 保存新收费标准
+                List<ProductCostStandard> standards = dataRequest.getCostStandards().stream()
+                        .map(standard -> {
+                            standard.setProductId(product.getId());
+                            return standard;
+                        })
+                        .collect(Collectors.toList());
+                productCostStandardService.saveBatch(standards);
+            }
+
+            // 处理优惠券
             if (CollUtil.isNotEmpty(dataRequest.getCouponIds())) {
                 couponProductService.deleteByProductId(dataRequest.getId());
                 List<CouponProduct> couponList = new ArrayList<>();
@@ -361,26 +416,60 @@ public class ProductServiceImpl extends ServiceImpl<ProductDao, Product> impleme
         product.setImage(attachmentUtil.clearPrefix(product.getImage()));
         product.setSliderImage(attachmentUtil.clearPrefix(product.getSliderImage()));
         product.setDetailsImage(attachmentUtil.clearPrefix(product.getDetailsImage()));
+        if (CollUtil.isNotEmpty(dataRequest.getFormConfig())) {
+            product.setProductFields(JSON.toJSONString(dataRequest.getFormConfig()));
+        }
 
         if (ObjectUtil.isEmpty(product.getStatus())) {
             product.setStatus(ProductConstants.STATUS_APPROVE);
         }
 
-        if(StrUtil.isNotBlank(dataRequest.getCateId())) {
+        if (StrUtil.isNotBlank(dataRequest.getCateId())) {
             List<Integer> cateIds = ZnyunUtil.stringToArray(dataRequest.getCateId());
             List<Category> categories = categoryService.listByIds(cateIds);
             List<String> cateNames = categories.stream().map(Category::getName).distinct().collect(Collectors.toList());
             product.setCategoryDefSub(String.join(",", cateNames));
             product.setCategoryDef(product.getCategoryDefSub());
-
-            /*List<Category> categories2 = categoryService.listParentByIds(cateIds);
-            List<String> cateNames2 = categories2.stream().map(Category::getName).distinct().collect(Collectors.toList());
-            product.setCategoryDef(String.join(",", cateNames2));*/
         }
 
         Boolean execute = transactionTemplate.execute(e -> {
+            // 保存产品基本信息
             save(product);
 
+            // 处理规格
+            if (CollUtil.isNotEmpty(dataRequest.getSpecs())) {
+                List<ProductItem> specs = dataRequest.getSpecs().stream()
+                        .map(spec -> {
+                            spec.setProductId(product.getId());
+                            return spec;
+                        })
+                        .collect(Collectors.toList());
+                productItemService.saveBatch(specs);
+            }
+
+            // 处理表单配置
+//            if (CollUtil.isNotEmpty(dataRequest.getFormConfig())) {
+//                List<ProductField> fields = dataRequest.getFormConfig().stream()
+//                    .map(field -> {
+//                        field.setProductId(product.getId());
+//                        return field;
+//                    })
+//                    .collect(Collectors.toList());
+//                productFieldService.saveBatch(fields);
+//            }
+
+            // 处理收费标准
+            if (CollUtil.isNotEmpty(dataRequest.getCostStandards())) {
+                List<ProductCostStandard> standards = dataRequest.getCostStandards().stream()
+                        .map(standard -> {
+                            standard.setProductId(product.getId());
+                            return standard;
+                        })
+                        .collect(Collectors.toList());
+                productCostStandardService.saveBatch(standards);
+            }
+
+            // 处理优惠券
             if (CollUtil.isNotEmpty(dataRequest.getCouponIds())) {
                 List<CouponProduct> couponList = new ArrayList<>();
                 for (Integer couponId : dataRequest.getCouponIds()) {
@@ -389,6 +478,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductDao, Product> impleme
                 }
                 couponProductService.saveBatch(couponList);
             }
+
             return Boolean.TRUE;
         });
 
@@ -450,4 +540,66 @@ public class ProductServiceImpl extends ServiceImpl<ProductDao, Product> impleme
                 .eq(Product::getIsDel, Boolean.FALSE);
         return count(queryWrapper);
     }
+
+    @Override
+    public ProductResponse getInfoById(Integer id) {
+        // 获取产品基本信息
+        Product product = super.getById(id);
+        if (product == null) {
+            return null;
+        }
+
+        // 转换为请求对象
+        ProductResponse request = new ProductResponse();
+        BeanUtils.copyProperties(product, request);
+
+        // 获取规格信息
+        LambdaQueryWrapper<ProductItem> itemWrapper = new LambdaQueryWrapper<>();
+        itemWrapper.eq(ProductItem::getProductId, id);
+        List<ProductItem> specs = productItemService.list(itemWrapper);
+        request.setSpecs(specs);
+
+        // 获取表单配置
+        if (StringUtils.isNotEmpty(product.getProductFields())) {
+            request.setFormConfig(JSON.parseArray(product.getProductFields(), ProductField.class));
+        }
+
+        // 获取收费标准
+        List<ProductCostStandard> costStandards = productCostStandardService.getByProductId(id.toString());
+        request.setCostStandards(costStandards);
+
+        // 获取服务保障名称
+        if (StringUtils.isNotEmpty(product.getServiceProjects())) {
+            String[] projectIds = product.getServiceProjects().split(",");
+            List<ServiceProject> projectNames = new ArrayList<>();
+            List<SysDataGroupInfo> infoList = sysDataGroupInfoService.listByIds(CollUtil.toList(projectIds));
+            infoList.stream().forEach(info -> {
+                ServiceProject serviceProject = JSONUtil.toBean(info.getValue(), ServiceProject.class);
+                projectNames.add(serviceProject);
+            });
+            request.setServiceProjectList(projectNames);
+        }
+        return request;
+    }
+
+    @Override
+    public Product getById(Integer id) {
+        Product product = super.getById(id);
+        return product;
+    }
+
+    @Override
+    public boolean removeBy(Integer id) {
+        return false;
+    }
+
+    @Override
+    public List<ProductRequest> listBy(ProductRequest dataRequest) {
+        return null;
+    }
+
+    @Override
+    public long countBy(ProductRequest dataRequest) {
+        return 0;
+    }
 }

+ 41 - 40
znyun-mod-primary/src/main/java/com/znyun/utils/AttachmentUtil.java

@@ -53,22 +53,23 @@ public class AttachmentUtil {
     }
 
     public String prefixImage(String path, Boolean isSocket) {
-        String resultPath = "";
-        String uploadRoot = com.ruoyi.common.constant.Constants.ZNYUN_FILE_UPLOAD;
-
-        Integer uploadTypeValue = Integer.parseInt(systemConfigService.findByType(ConfigConstants.UPLOAD_TYPE).getValue());
-        if (uploadTypeValue == Constants.UPLOAD_TYPE_LOCAL && Constants.ENV_DEV.equals(EnvConfig.getActive())) {
-            String contextPath = SpringUtils.getRequiredProperty("server.servlet.context-path");
-            if (contextPath == null || contextPath.equals("/")) {
-                resultPath = path.replace(uploadRoot + "/", getCdnUrl() + "/" + uploadRoot + "/");
-            } else {
-                resultPath = path.replace(uploadRoot + "/", getCdnUrl() + contextPath + "/" + uploadRoot + "/");
-            }
-        } else {
-            resultPath = path.replace(uploadRoot + "/", getCdnUrl() + "/" + uploadRoot + "/");
-        }
-
-        return resultPath.replace("/http", "http");
+//        String resultPath = "";
+//        String uploadRoot = com.ruoyi.common.constant.Constants.ZNYUN_FILE_UPLOAD;
+//
+//        Integer uploadTypeValue = Integer.parseInt(systemConfigService.findByType(ConfigConstants.UPLOAD_TYPE).getValue());
+//        if (uploadTypeValue == Constants.UPLOAD_TYPE_LOCAL && Constants.ENV_DEV.equals(EnvConfig.getActive())) {
+//            String contextPath = SpringUtils.getRequiredProperty("server.servlet.context-path");
+//            if (contextPath == null || contextPath.equals("/")) {
+//                resultPath = path.replace(uploadRoot + "/", getCdnUrl() + "/" + uploadRoot + "/");
+//            } else {
+//                resultPath = path.replace(uploadRoot + "/", getCdnUrl() + contextPath + "/" + uploadRoot + "/");
+//            }
+//        } else {
+//            resultPath = path.replace(uploadRoot + "/", getCdnUrl() + "/" + uploadRoot + "/");
+//        }
+//
+//        return resultPath.replace("/http", "http");
+        return path;
     }
 
     /**
@@ -78,18 +79,18 @@ public class AttachmentUtil {
      * @return String
      */
     public String clearPrefix(String path) {
-        if (StringUtils.isBlank(path)) {
-            return path;
-        }
-
-        String contextPath = ServletUtils.getRequest().getContextPath();
-        if(contextPath != null && !contextPath.equals("/")) {
-            path = path.replace(contextPath, "");
-        }
-
-        if (path.contains(getCdnUrl() + "/")) {
-            return path.replace(getCdnUrl() + "/", "");
-        }
+//        if (StringUtils.isBlank(path)) {
+//            return path;
+//        }
+//
+//        String contextPath = ServletUtils.getRequest().getContextPath();
+//        if(contextPath != null && !contextPath.equals("/")) {
+//            path = path.replace(contextPath, "");
+//        }
+//
+//        if (path.contains(getCdnUrl() + "/")) {
+//            return path.replace(getCdnUrl() + "/", "");
+//        }
         return path;
     }
 
@@ -100,18 +101,18 @@ public class AttachmentUtil {
      * @return
      */
     public String clearPrefix(String path, Boolean isSocket) {
-        if (StringUtils.isBlank(path)) {
-            return path;
-        }
-
-        String contextPath = SpringUtils.getRequiredProperty("server.servlet.context-path");
-        if(contextPath != null && !contextPath.equals("/")) {
-            path = path.replace(contextPath, "");
-        }
-
-        if (path.contains(getCdnUrl() + "/")) {
-            return path.replace(getCdnUrl() + "/", "");
-        }
+//        if (StringUtils.isBlank(path)) {
+//            return path;
+//        }
+//
+//        String contextPath = SpringUtils.getRequiredProperty("server.servlet.context-path");
+//        if(contextPath != null && !contextPath.equals("/")) {
+//            path = path.replace(contextPath, "");
+//        }
+//
+//        if (path.contains(getCdnUrl() + "/")) {
+//            return path.replace(getCdnUrl() + "/", "");
+//        }
         return path;
     }