parent
							
								
									cfd454b989
								
							
						
					
					
						commit
						3fec9de1cf
					
				|  | @ -7,6 +7,8 @@ export interface FollowUpRecordVO { | ||||||
|   bizId: number // 数据编号
 |   bizId: number // 数据编号
 | ||||||
|   type: number // 跟进类型
 |   type: number // 跟进类型
 | ||||||
|   content: string // 跟进内容
 |   content: string // 跟进内容
 | ||||||
|  |   picUrls: string[] | ||||||
|  |   fileUrls: string[] | ||||||
|   nextTime: Date // 下次联系时间
 |   nextTime: Date // 下次联系时间
 | ||||||
|   businessIds: number[] // 关联的商机编号数组
 |   businessIds: number[] // 关联的商机编号数组
 | ||||||
|   contactIds: number[] // 关联的联系人编号数组
 |   contactIds: number[] // 关联的联系人编号数组
 | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
|             <Icon icon="ep:zoom-in" /> |             <Icon icon="ep:zoom-in" /> | ||||||
|             <span>查看</span> |             <span>查看</span> | ||||||
|           </div> |           </div> | ||||||
|           <div class="handle-icon" @click="handleRemove(file)" v-if="!disabled"> |           <div v-if="!disabled" class="handle-icon" @click="handleRemove(file)"> | ||||||
|             <Icon icon="ep:delete" /> |             <Icon icon="ep:delete" /> | ||||||
|             <span>删除</span> |             <span>删除</span> | ||||||
|           </div> |           </div> | ||||||
|  | @ -46,7 +46,6 @@ | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { PropType } from 'vue' |  | ||||||
| import type { UploadFile, UploadProps, UploadUserFile } from 'element-plus' | import type { UploadFile, UploadProps, UploadUserFile } from 'element-plus' | ||||||
| import { ElNotification } from 'element-plus' | import { ElNotification } from 'element-plus' | ||||||
| 
 | 
 | ||||||
|  | @ -70,10 +69,7 @@ type FileTypes = | ||||||
|   | 'image/x-icon' |   | 'image/x-icon' | ||||||
| 
 | 
 | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   modelValue: { |   modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired, | ||||||
|     type: Array as PropType<UploadUserFile[]>, |  | ||||||
|     required: true |  | ||||||
|   }, |  | ||||||
|   updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL), |   updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL), | ||||||
|   drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true) |   drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true) | ||||||
|   disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false) |   disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false) | ||||||
|  | @ -91,18 +87,8 @@ const uploadHeaders = ref({ | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| const fileList = ref<UploadUserFile[]>([]) | const fileList = ref<UploadUserFile[]>([]) | ||||||
| // fix: 改为动态监听赋值解决图片回显问题 | const uploadNumber = ref<number>(0) | ||||||
| watch( | const uploadList = ref<UploadUserFile[]>([]) | ||||||
|   () => props.modelValue, |  | ||||||
|   (data) => { |  | ||||||
|     if (!data) return |  | ||||||
|     fileList.value = data |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|     deep: true, |  | ||||||
|     immediate: true |  | ||||||
|   } |  | ||||||
| ) |  | ||||||
| /** | /** | ||||||
|  * @description 文件上传之前判断 |  * @description 文件上传之前判断 | ||||||
|  * @param rawFile 上传的文件 |  * @param rawFile 上传的文件 | ||||||
|  | @ -122,29 +108,61 @@ const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => { | ||||||
|       message: `上传图片大小不能超过 ${props.fileSize}M!`, |       message: `上传图片大小不能超过 ${props.fileSize}M!`, | ||||||
|       type: 'warning' |       type: 'warning' | ||||||
|     }) |     }) | ||||||
|  |   uploadNumber.value++ | ||||||
|   return imgType.includes(rawFile.type as FileTypes) && imgSize |   return imgType.includes(rawFile.type as FileTypes) && imgSize | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 图片上传成功 | // 图片上传成功 | ||||||
| interface UploadEmits { | interface UploadEmits { | ||||||
|   (e: 'update:modelValue', value: UploadUserFile[]): void |   (e: 'update:modelValue', value: string[]): void | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits<UploadEmits>() | const emit = defineEmits<UploadEmits>() | ||||||
| const uploadSuccess = (response, uploadFile: UploadFile) => { | const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => { | ||||||
|   if (!response) return |  | ||||||
|   // TODO 多图上传组件成功后只是把保存成功后的url替换掉组件选图时的文件路径,所以返回的fileList包含的是一个包含文件信息的对象列表 |  | ||||||
|   uploadFile.url = response.data |  | ||||||
|   emit('update:modelValue', fileList.value) |  | ||||||
|   message.success('上传成功') |   message.success('上传成功') | ||||||
|  |   // 删除自身 | ||||||
|  |   debugger | ||||||
|  |   const index = fileList.value.findIndex((item) => item.response?.data === res.data) | ||||||
|  |   fileList.value.splice(index, 1) | ||||||
|  |   uploadList.value.push({ name: res.data, url: res.data }) | ||||||
|  |   if (uploadList.value.length == uploadNumber.value) { | ||||||
|  |     fileList.value.push(...uploadList.value) | ||||||
|  |     uploadList.value = [] | ||||||
|  |     uploadNumber.value = 0 | ||||||
|  |     emitUpdateModelValue() | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // 监听模型绑定值变动 | ||||||
|  | watch( | ||||||
|  |   () => props.modelValue, | ||||||
|  |   (val: string | string[]) => { | ||||||
|  |     if (!val) { | ||||||
|  |       fileList.value = [] // fix:处理掉缓存,表单重置后上传组件的内容并没有重置 | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fileList.value = [] // 保障数据为空 | ||||||
|  |     fileList.value.push( | ||||||
|  |       ...(val as string[]).map((url) => ({ name: url.substring(url.lastIndexOf('/') + 1), url })) | ||||||
|  |     ) | ||||||
|  |   }, | ||||||
|  |   { immediate: true, deep: true } | ||||||
|  | ) | ||||||
|  | // 发送图片链接列表更新 | ||||||
|  | const emitUpdateModelValue = () => { | ||||||
|  |   let result: string[] = fileList.value.map((file) => file.url!) | ||||||
|  |   emit('update:modelValue', result) | ||||||
|  | } | ||||||
| // 删除图片 | // 删除图片 | ||||||
| const handleRemove = (uploadFile: UploadFile) => { | const handleRemove = (uploadFile: UploadFile) => { | ||||||
|   fileList.value = fileList.value.filter( |   fileList.value = fileList.value.filter( | ||||||
|     (item) => item.url !== uploadFile.url || item.name !== uploadFile.name |     (item) => item.url !== uploadFile.url || item.name !== uploadFile.name | ||||||
|   ) |   ) | ||||||
|   emit('update:modelValue', fileList.value) |   emit( | ||||||
|  |     'update:modelValue', | ||||||
|  |     fileList.value.map((file) => file.url!) | ||||||
|  |   ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 图片上传错误提示 | // 图片上传错误提示 | ||||||
|  |  | ||||||
|  | @ -15,9 +15,9 @@ | ||||||
|         <el-select v-model="queryParams.contactStatus" class="!w-240px" placeholder="状态" @change="handleQuery"> |         <el-select v-model="queryParams.contactStatus" class="!w-240px" placeholder="状态" @change="handleQuery"> | ||||||
|           <el-option |           <el-option | ||||||
|             v-for="(option, index) in CONTACT_STATUS" |             v-for="(option, index) in CONTACT_STATUS" | ||||||
|  |             :key="index" | ||||||
|             :label="option.label" |             :label="option.label" | ||||||
|             :value="option.value" |             :value="option.value" | ||||||
|             :key="index" |  | ||||||
|           /> |           /> | ||||||
|         </el-select> |         </el-select> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|  | @ -25,9 +25,9 @@ | ||||||
|         <el-select v-model="queryParams.sceneType" class="!w-240px" placeholder="归属" @change="handleQuery"> |         <el-select v-model="queryParams.sceneType" class="!w-240px" placeholder="归属" @change="handleQuery"> | ||||||
|           <el-option |           <el-option | ||||||
|             v-for="(option, index) in SCENE_TYPES" |             v-for="(option, index) in SCENE_TYPES" | ||||||
|  |             :key="index" | ||||||
|             :label="option.label" |             :label="option.label" | ||||||
|             :value="option.value" |             :value="option.value" | ||||||
|             :key="index" |  | ||||||
|           /> |           /> | ||||||
|         </el-select> |         </el-select> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|  | @ -74,7 +74,7 @@ | ||||||
|           <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" /> |           <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" /> | ||||||
|         </template> |         </template> | ||||||
|       </el-table-column> |       </el-table-column> | ||||||
|       <!-- TODO @puhui999:距进入公海天数 --> |       <el-table-column align="center" label="距进入公海天数" prop="poolDay" width="100px" /> | ||||||
|       <el-table-column |       <el-table-column | ||||||
|         :formatter="dateFormatter" |         :formatter="dateFormatter" | ||||||
|         align="center" |         align="center" | ||||||
|  | @ -110,7 +110,7 @@ | ||||||
|   </ContentWrap> |   </ContentWrap> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts" setup name="TodayCustomer"> | <script lang="ts" name="TodayCustomer" setup> | ||||||
| import { DICT_TYPE } from '@/utils/dict' | import { DICT_TYPE } from '@/utils/dict' | ||||||
| import { dateFormatter } from '@/utils/formatTime' | import { dateFormatter } from '@/utils/formatTime' | ||||||
| import * as BacklogApi from '@/api/crm/backlog' | import * as BacklogApi from '@/api/crm/backlog' | ||||||
|  |  | ||||||
|  | @ -34,49 +34,36 @@ | ||||||
|         <!-- TODO @puhui999:不搞富文本哈;然后加个附件、图片两个 form-item 哈 --> |         <!-- TODO @puhui999:不搞富文本哈;然后加个附件、图片两个 form-item 哈 --> | ||||||
|         <el-col :span="24"> |         <el-col :span="24"> | ||||||
|           <el-form-item label="跟进内容" prop="content"> |           <el-form-item label="跟进内容" prop="content"> | ||||||
|             <Editor v-model="formData.content" height="300px" /> |             <el-input v-model="formData.content" :rows="3" type="textarea" /> | ||||||
|  |           </el-form-item> | ||||||
|  |         </el-col> | ||||||
|  |         <el-col :span="24"> | ||||||
|  |           <el-form-item label="图片" prop="content"> | ||||||
|  |             <UploadImgs v-model="formData.picUrls" class="min-w-80px" /> | ||||||
|  |           </el-form-item> | ||||||
|  |         </el-col> | ||||||
|  |         <el-col :span="24"> | ||||||
|  |           <el-form-item label="附件" prop="content"> | ||||||
|  |             <UploadFile v-model="formData.fileUrls" class="min-w-80px" /> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|         </el-col> |         </el-col> | ||||||
|         <!-- TODO @puhui999:因为不考虑编辑的情况,是不是关联要是个弹窗选择哈? --> |  | ||||||
|         <el-col :span="24"> |         <el-col :span="24"> | ||||||
|           <el-form-item label="关联联系人" prop="contactIds"> |           <el-form-item label="关联联系人" prop="contactIds"> | ||||||
|             <el-select v-model="formData.contactIds" multiple placeholder="请选择"> |             <el-button @click="handleAddContact"> | ||||||
|               <el-option |               <Icon class="mr-5px" icon="ep:plus" /> | ||||||
|                 v-for="item in allContactList" |               添加联系人 | ||||||
|                 :key="item.id" |             </el-button> | ||||||
|                 :label="item.name" |  | ||||||
|                 :value="item.id" |  | ||||||
|               /> |  | ||||||
|             </el-select> |  | ||||||
|             <contact-list v-model:contactIds="formData.contactIds" /> |             <contact-list v-model:contactIds="formData.contactIds" /> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|           <!--          <el-form-item label="关联联系人" prop="contactIds">--> |  | ||||||
|           <!--            <el-button @click="handleAddContact">--> |  | ||||||
|           <!--              <Icon class="mr-5px" icon="ep:plus" />--> |  | ||||||
|           <!--              选择添加联系人--> |  | ||||||
|           <!--            </el-button>--> |  | ||||||
|           <!--            <contact-list v-model:contactIds="formData.contactIds" />--> |  | ||||||
|           <!--          </el-form-item>--> |  | ||||||
|         </el-col> |         </el-col> | ||||||
|         <el-col :span="24"> |         <el-col :span="24"> | ||||||
|           <el-form-item label="关联商机" prop="businessIds"> |           <el-form-item label="关联商机" prop="businessIds"> | ||||||
|             <el-select v-model="formData.businessIds" multiple placeholder="请选择"> |             <el-button @click="handleAddBusiness"> | ||||||
|               <el-option |               <Icon class="mr-5px" icon="ep:plus" /> | ||||||
|                 v-for="item in allBusinessList" |               添加商机 | ||||||
|                 :key="item.id" |             </el-button> | ||||||
|                 :label="item.name" |  | ||||||
|                 :value="item.id" |  | ||||||
|               /> |  | ||||||
|             </el-select> |  | ||||||
|             <business-list v-model:businessIds="formData.businessIds" /> |             <business-list v-model:businessIds="formData.businessIds" /> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|           <!--          <el-form-item label="关联商机" prop="businessIds">--> |  | ||||||
|           <!--            <el-button @click="handleAddBusiness">--> |  | ||||||
|           <!--              <Icon class="mr-5px" icon="ep:plus" />--> |  | ||||||
|           <!--              选择添加商机--> |  | ||||||
|           <!--            </el-button>--> |  | ||||||
|           <!--            <business-list v-model:businessIds="formData.businessIds" />--> |  | ||||||
|           <!--          </el-form-item>--> |  | ||||||
|         </el-col> |         </el-col> | ||||||
|       </el-row> |       </el-row> | ||||||
|     </el-form> |     </el-form> | ||||||
|  | @ -159,6 +146,8 @@ const submitForm = async () => { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const handleAddContact = () => {} | ||||||
|  | const handleAddBusiness = () => {} | ||||||
| /** 重置表单 */ | /** 重置表单 */ | ||||||
| const resetForm = () => { | const resetForm = () => { | ||||||
|   formRef.value?.resetFields() |   formRef.value?.resetFields() | ||||||
|  |  | ||||||
|  | @ -1,17 +1,17 @@ | ||||||
| <template> | <template> | ||||||
|   <Dialog title="添加虚拟评论" v-model="dialogVisible"> |   <Dialog v-model="dialogVisible" title="添加虚拟评论"> | ||||||
|     <el-form |     <el-form | ||||||
|       ref="formRef" |       ref="formRef" | ||||||
|  |       v-loading="formLoading" | ||||||
|       :model="formData" |       :model="formData" | ||||||
|       :rules="formRules" |       :rules="formRules" | ||||||
|       label-width="100px" |       label-width="100px" | ||||||
|       v-loading="formLoading" |  | ||||||
|     > |     > | ||||||
|       <el-form-item label="商品" prop="spuId"> |       <el-form-item label="商品" prop="spuId"> | ||||||
|         <SpuShowcase v-model="formData.spuId" :limit="1" /> |         <SpuShowcase v-model="formData.spuId" :limit="1" /> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|       <el-form-item label="商品规格" prop="skuId" v-if="formData.spuId"> |       <el-form-item v-if="formData.spuId" label="商品规格" prop="skuId"> | ||||||
|         <div @click="handleSelectSku" class="h-60px w-60px"> |         <div class="h-60px w-60px" @click="handleSelectSku"> | ||||||
|           <div v-if="skuData && skuData.picUrl"> |           <div v-if="skuData && skuData.picUrl"> | ||||||
|             <el-image :src="skuData.picUrl" /> |             <el-image :src="skuData.picUrl" /> | ||||||
|           </div> |           </div> | ||||||
|  | @ -27,7 +27,7 @@ | ||||||
|         <el-input v-model="formData.userNickname" placeholder="请输入用户名称" /> |         <el-input v-model="formData.userNickname" placeholder="请输入用户名称" /> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|       <el-form-item label="评论内容" prop="content"> |       <el-form-item label="评论内容" prop="content"> | ||||||
|         <el-input type="textarea" v-model="formData.content" /> |         <el-input v-model="formData.content" type="textarea" /> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|       <el-form-item label="描述星级" prop="descriptionScores"> |       <el-form-item label="描述星级" prop="descriptionScores"> | ||||||
|         <el-rate v-model="formData.descriptionScores" /> |         <el-rate v-model="formData.descriptionScores" /> | ||||||
|  | @ -40,11 +40,11 @@ | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|     </el-form> |     </el-form> | ||||||
|     <template #footer> |     <template #footer> | ||||||
|       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> |       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> | ||||||
|       <el-button @click="dialogVisible = false">取 消</el-button> |       <el-button @click="dialogVisible = false">取 消</el-button> | ||||||
|     </template> |     </template> | ||||||
|   </Dialog> |   </Dialog> | ||||||
|   <SkuTableSelect ref="skuTableSelectRef" @change="handleSkuChange" :spu-id="formData.spuId" /> |   <SkuTableSelect ref="skuTableSelectRef" :spu-id="formData.spuId" @change="handleSkuChange" /> | ||||||
| </template> | </template> | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import * as CommentApi from '@/api/mall/product/comment' | import * as CommentApi from '@/api/mall/product/comment' | ||||||
|  | @ -115,13 +115,8 @@ const submitForm = async () => { | ||||||
|   // 提交请求 |   // 提交请求 | ||||||
|   formLoading.value = true |   formLoading.value = true | ||||||
|   try { |   try { | ||||||
|     //处理评论图片 |  | ||||||
|     const picUrls = formData.value.picUrls.map((item) => { |  | ||||||
|       return item?.url ? item.url : item |  | ||||||
|     }) |  | ||||||
|     const data = { ...formData.value, picUrls } |  | ||||||
|     if (formType.value === 'create') { |     if (formType.value === 'create') { | ||||||
|       await CommentApi.createComment(data) |       await CommentApi.createComment(unref(formData.value) as any) | ||||||
|       message.success(t('common.createSuccess')) |       message.success(t('common.createSuccess')) | ||||||
|     } |     } | ||||||
|     dialogVisible.value = false |     dialogVisible.value = false | ||||||
|  |  | ||||||
|  | @ -1,16 +1,16 @@ | ||||||
| <!-- 商品发布 - 基础设置 --> | <!-- 商品发布 - 基础设置 --> | ||||||
| <template> | <template> | ||||||
|   <el-form ref="formRef" :model="formData" :rules="rules" label-width="120px" :disabled="isDetail"> |   <el-form ref="formRef" :disabled="isDetail" :model="formData" :rules="rules" label-width="120px"> | ||||||
|     <el-form-item label="商品名称" prop="name"> |     <el-form-item label="商品名称" prop="name"> | ||||||
|       <el-input |       <el-input | ||||||
|         v-model="formData.name" |         v-model="formData.name" | ||||||
|  |         :autosize="{ minRows: 2, maxRows: 2 }" | ||||||
|  |         :clearable="true" | ||||||
|  |         :show-word-limit="true" | ||||||
|  |         class="w-80!" | ||||||
|  |         maxlength="64" | ||||||
|         placeholder="请输入商品名称" |         placeholder="请输入商品名称" | ||||||
|         type="textarea" |         type="textarea" | ||||||
|         :autosize="{ minRows: 2, maxRows: 2 }" |  | ||||||
|         maxlength="64" |  | ||||||
|         :show-word-limit="true" |  | ||||||
|         :clearable="true" |  | ||||||
|         class="w-80!" |  | ||||||
|       /> |       /> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|     <el-form-item label="商品分类" prop="categoryId"> |     <el-form-item label="商品分类" prop="categoryId"> | ||||||
|  | @ -20,12 +20,12 @@ | ||||||
|         :props="defaultProps" |         :props="defaultProps" | ||||||
|         class="w-80" |         class="w-80" | ||||||
|         clearable |         clearable | ||||||
|         placeholder="请选择商品分类" |  | ||||||
|         filterable |         filterable | ||||||
|  |         placeholder="请选择商品分类" | ||||||
|       /> |       /> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|     <el-form-item label="商品品牌" prop="brandId"> |     <el-form-item label="商品品牌" prop="brandId"> | ||||||
|       <el-select v-model="formData.brandId" placeholder="请选择商品品牌" class="w-80"> |       <el-select v-model="formData.brandId" class="w-80" placeholder="请选择商品品牌"> | ||||||
|         <el-option |         <el-option | ||||||
|           v-for="item in brandList" |           v-for="item in brandList" | ||||||
|           :key="item.id" |           :key="item.id" | ||||||
|  | @ -35,25 +35,25 @@ | ||||||
|       </el-select> |       </el-select> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|     <el-form-item label="商品关键字" prop="keyword"> |     <el-form-item label="商品关键字" prop="keyword"> | ||||||
|       <el-input v-model="formData.keyword" placeholder="请输入商品关键字" class="w-80!" /> |       <el-input v-model="formData.keyword" class="w-80!" placeholder="请输入商品关键字" /> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|     <el-form-item label="商品简介" prop="introduction"> |     <el-form-item label="商品简介" prop="introduction"> | ||||||
|       <el-input |       <el-input | ||||||
|         v-model="formData.introduction" |         v-model="formData.introduction" | ||||||
|  |         :autosize="{ minRows: 2, maxRows: 2 }" | ||||||
|  |         :clearable="true" | ||||||
|  |         :show-word-limit="true" | ||||||
|  |         class="w-80!" | ||||||
|  |         maxlength="128" | ||||||
|         placeholder="请输入商品名称" |         placeholder="请输入商品名称" | ||||||
|         type="textarea" |         type="textarea" | ||||||
|         :autosize="{ minRows: 2, maxRows: 2 }" |  | ||||||
|         maxlength="128" |  | ||||||
|         :show-word-limit="true" |  | ||||||
|         :clearable="true" |  | ||||||
|         class="w-80!" |  | ||||||
|       /> |       /> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|     <el-form-item label="商品封面图" prop="picUrl"> |     <el-form-item label="商品封面图" prop="picUrl"> | ||||||
|       <UploadImg v-model="formData.picUrl" height="80px" :disabled="isDetail" /> |       <UploadImg v-model="formData.picUrl" :disabled="isDetail" height="80px" /> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|     <el-form-item label="商品轮播图" prop="sliderPicUrls"> |     <el-form-item label="商品轮播图" prop="sliderPicUrls"> | ||||||
|       <UploadImgs v-model:modelValue="formData.sliderPicUrls" :disabled="isDetail" /> |       <UploadImgs v-model="formData.sliderPicUrls" :disabled="isDetail" /> | ||||||
|     </el-form-item> |     </el-form-item> | ||||||
|   </el-form> |   </el-form> | ||||||
| </template> | </template> | ||||||
|  | @ -64,9 +64,9 @@ import { propTypes } from '@/utils/propTypes' | ||||||
| import { defaultProps, handleTree } from '@/utils/tree' | import { defaultProps, handleTree } from '@/utils/tree' | ||||||
| import type { Spu } from '@/api/mall/product/spu' | import type { Spu } from '@/api/mall/product/spu' | ||||||
| import * as ProductCategoryApi from '@/api/mall/product/category' | import * as ProductCategoryApi from '@/api/mall/product/category' | ||||||
|  | import { CategoryVO } from '@/api/mall/product/category' | ||||||
| import * as ProductBrandApi from '@/api/mall/product/brand' | import * as ProductBrandApi from '@/api/mall/product/brand' | ||||||
| import { BrandVO } from '@/api/mall/product/brand' | import { BrandVO } from '@/api/mall/product/brand' | ||||||
| import { CategoryVO } from '@/api/mall/product/category' |  | ||||||
| 
 | 
 | ||||||
| defineOptions({ name: 'ProductSpuInfoForm' }) | defineOptions({ name: 'ProductSpuInfoForm' }) | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|  | @ -107,10 +107,6 @@ watch( | ||||||
|       return |       return | ||||||
|     } |     } | ||||||
|     copyValueToTarget(formData, data) |     copyValueToTarget(formData, data) | ||||||
|     // TODO @puhui999:优化多文件上传,看看有没可能搞成返回 v-model 图片列表这种 |  | ||||||
|     formData.sliderPicUrls = data['sliderPicUrls']?.map((item) => ({ |  | ||||||
|       url: item |  | ||||||
|     })) |  | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     immediate: true |     immediate: true | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| <template> | <template> | ||||||
|   <Dialog :title="dialogTitle" v-model="dialogVisible"> |   <Dialog v-model="dialogVisible" :title="dialogTitle"> | ||||||
|     <el-form |     <el-form | ||||||
|       ref="formRef" |       ref="formRef" | ||||||
|  |       v-loading="formLoading" | ||||||
|       :model="formData" |       :model="formData" | ||||||
|       :rules="formRules" |       :rules="formRules" | ||||||
|       label-width="100px" |       label-width="100px" | ||||||
|       v-loading="formLoading" |  | ||||||
|     > |     > | ||||||
|       <el-form-item label="页面名称" prop="name"> |       <el-form-item label="页面名称" prop="name"> | ||||||
|         <el-input v-model="formData.name" placeholder="请输入页面名称" /> |         <el-input v-model="formData.name" placeholder="请输入页面名称" /> | ||||||
|  | @ -18,12 +18,12 @@ | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|     </el-form> |     </el-form> | ||||||
|     <template #footer> |     <template #footer> | ||||||
|       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> |       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> | ||||||
|       <el-button @click="dialogVisible = false">取 消</el-button> |       <el-button @click="dialogVisible = false">取 消</el-button> | ||||||
|     </template> |     </template> | ||||||
|   </Dialog> |   </Dialog> | ||||||
| </template> | </template> | ||||||
| <script setup lang="ts"> | <script lang="ts" setup> | ||||||
| import * as DiyPageApi from '@/api/mall/promotion/diy/page' | import * as DiyPageApi from '@/api/mall/promotion/diy/page' | ||||||
| 
 | 
 | ||||||
| /** 装修页面表单 */ | /** 装修页面表单 */ | ||||||
|  | @ -57,13 +57,7 @@ const open = async (type: string, id?: number) => { | ||||||
|   if (id) { |   if (id) { | ||||||
|     formLoading.value = true |     formLoading.value = true | ||||||
|     try { |     try { | ||||||
|       const diyPage = await DiyPageApi.getDiyPage(id) // 处理预览图 |       formData.value = await DiyPageApi.getDiyPage(id) | ||||||
|       if (diyPage?.previewPicUrls?.length > 0) { |  | ||||||
|         diyPage.previewPicUrls = diyPage.previewPicUrls.map((url: string) => { |  | ||||||
|           return { url } |  | ||||||
|         }) |  | ||||||
|       } |  | ||||||
|       formData.value = diyPage |  | ||||||
|     } finally { |     } finally { | ||||||
|       formLoading.value = false |       formLoading.value = false | ||||||
|     } |     } | ||||||
|  | @ -81,11 +75,7 @@ const submitForm = async () => { | ||||||
|   // 提交请求 |   // 提交请求 | ||||||
|   formLoading.value = true |   formLoading.value = true | ||||||
|   try { |   try { | ||||||
|     // 处理预览图 |     const data = formData.value as unknown as DiyPageApi.DiyPageVO | ||||||
|     const previewPicUrls = formData.value.previewPicUrls.map((item) => { |  | ||||||
|       return item['url'] ? item['url'] : item |  | ||||||
|     }) |  | ||||||
|     const data = { ...formData.value, previewPicUrls } as unknown as DiyPageApi.DiyPageVO |  | ||||||
|     if (formType.value === 'create') { |     if (formType.value === 'create') { | ||||||
|       await DiyPageApi.createDiyPage(data) |       await DiyPageApi.createDiyPage(data) | ||||||
|       message.success(t('common.createSuccess')) |       message.success(t('common.createSuccess')) | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| <template> | <template> | ||||||
|   <Dialog :title="dialogTitle" v-model="dialogVisible"> |   <Dialog v-model="dialogVisible" :title="dialogTitle"> | ||||||
|     <el-form |     <el-form | ||||||
|       ref="formRef" |       ref="formRef" | ||||||
|  |       v-loading="formLoading" | ||||||
|       :model="formData" |       :model="formData" | ||||||
|       :rules="formRules" |       :rules="formRules" | ||||||
|       label-width="100px" |       label-width="100px" | ||||||
|       v-loading="formLoading" |  | ||||||
|     > |     > | ||||||
|       <el-form-item label="模板名称" prop="name"> |       <el-form-item label="模板名称" prop="name"> | ||||||
|         <el-input v-model="formData.name" placeholder="请输入模板名称" /> |         <el-input v-model="formData.name" placeholder="请输入模板名称" /> | ||||||
|  | @ -18,12 +18,12 @@ | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|     </el-form> |     </el-form> | ||||||
|     <template #footer> |     <template #footer> | ||||||
|       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> |       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> | ||||||
|       <el-button @click="dialogVisible = false">取 消</el-button> |       <el-button @click="dialogVisible = false">取 消</el-button> | ||||||
|     </template> |     </template> | ||||||
|   </Dialog> |   </Dialog> | ||||||
| </template> | </template> | ||||||
| <script setup lang="ts"> | <script lang="ts" setup> | ||||||
| import * as DiyTemplateApi from '@/api/mall/promotion/diy/template' | import * as DiyTemplateApi from '@/api/mall/promotion/diy/template' | ||||||
| 
 | 
 | ||||||
| /** 装修模板表单 */ | /** 装修模板表单 */ | ||||||
|  | @ -57,14 +57,7 @@ const open = async (type: string, id?: number) => { | ||||||
|   if (id) { |   if (id) { | ||||||
|     formLoading.value = true |     formLoading.value = true | ||||||
|     try { |     try { | ||||||
|       const diyTemplate = await DiyTemplateApi.getDiyTemplate(id) |       formData.value = await DiyTemplateApi.getDiyTemplate(id) | ||||||
|       // 处理预览图 |  | ||||||
|       if (diyTemplate?.previewPicUrls?.length > 0) { |  | ||||||
|         diyTemplate.previewPicUrls = diyTemplate.previewPicUrls.map((url: string) => { |  | ||||||
|           return { url } |  | ||||||
|         }) |  | ||||||
|       } |  | ||||||
|       formData.value = diyTemplate |  | ||||||
|     } finally { |     } finally { | ||||||
|       formLoading.value = false |       formLoading.value = false | ||||||
|     } |     } | ||||||
|  | @ -82,11 +75,7 @@ const submitForm = async () => { | ||||||
|   // 提交请求 |   // 提交请求 | ||||||
|   formLoading.value = true |   formLoading.value = true | ||||||
|   try { |   try { | ||||||
|     // 处理预览图 |     const data = formData.value as unknown as DiyTemplateApi.DiyTemplateVO | ||||||
|     const previewPicUrls = formData.value.previewPicUrls.map((item) => { |  | ||||||
|       return item['url'] ? item['url'] : item |  | ||||||
|     }) |  | ||||||
|     const data = { ...formData.value, previewPicUrls } as unknown as DiyTemplateApi.DiyTemplateVO |  | ||||||
|     if (formType.value === 'create') { |     if (formType.value === 'create') { | ||||||
|       await DiyTemplateApi.createDiyTemplate(data) |       await DiyTemplateApi.createDiyTemplate(data) | ||||||
|       message.success(t('common.createSuccess')) |       message.success(t('common.createSuccess')) | ||||||
|  |  | ||||||
|  | @ -2,12 +2,12 @@ | ||||||
|   <ContentWrap> |   <ContentWrap> | ||||||
|     <el-form |     <el-form | ||||||
|       ref="formRef" |       ref="formRef" | ||||||
|  |       v-loading="formLoading" | ||||||
|       :model="formData" |       :model="formData" | ||||||
|       :rules="formRules" |       :rules="formRules" | ||||||
|       label-width="120px" |       label-width="120px" | ||||||
|       v-loading="formLoading" |  | ||||||
|     > |     > | ||||||
|       <el-form-item label="hideId" v-show="false"> |       <el-form-item v-show="false" label="hideId"> | ||||||
|         <el-input v-model="formData.id" /> |         <el-input v-model="formData.id" /> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|       <el-tabs> |       <el-tabs> | ||||||
|  | @ -16,9 +16,9 @@ | ||||||
|           <el-form-item label="退款理由" prop="afterSaleRefundReasons"> |           <el-form-item label="退款理由" prop="afterSaleRefundReasons"> | ||||||
|             <el-select |             <el-select | ||||||
|               v-model="formData.afterSaleRefundReasons" |               v-model="formData.afterSaleRefundReasons" | ||||||
|  |               allow-create | ||||||
|               filterable |               filterable | ||||||
|               multiple |               multiple | ||||||
|               allow-create |  | ||||||
|               placeholder="请直接输入退款理由" |               placeholder="请直接输入退款理由" | ||||||
|             > |             > | ||||||
|               <el-option |               <el-option | ||||||
|  | @ -50,15 +50,15 @@ | ||||||
|         <el-tab-pane label="配送"> |         <el-tab-pane label="配送"> | ||||||
|           <el-form-item label="启用包邮" prop="deliveryExpressFreeEnabled"> |           <el-form-item label="启用包邮" prop="deliveryExpressFreeEnabled"> | ||||||
|             <el-switch v-model="formData.deliveryExpressFreeEnabled" style="user-select: none" /> |             <el-switch v-model="formData.deliveryExpressFreeEnabled" style="user-select: none" /> | ||||||
|             <el-text class="w-full" size="small" type="info"> 商城是否启用全场包邮 </el-text> |             <el-text class="w-full" size="small" type="info"> 商城是否启用全场包邮</el-text> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|           <el-form-item label="满额包邮" prop="deliveryExpressFreePrice"> |           <el-form-item label="满额包邮" prop="deliveryExpressFreePrice"> | ||||||
|             <el-input-number |             <el-input-number | ||||||
|               v-model="formData.deliveryExpressFreePrice" |               v-model="formData.deliveryExpressFreePrice" | ||||||
|               placeholder="请输入满额包邮" |  | ||||||
|               class="!w-xs" |  | ||||||
|               :precision="2" |  | ||||||
|               :min="0" |               :min="0" | ||||||
|  |               :precision="2" | ||||||
|  |               class="!w-xs" | ||||||
|  |               placeholder="请输入满额包邮" | ||||||
|             /> |             /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               商城商品满多少金额即可包邮,单位:元 |               商城商品满多少金额即可包邮,单位:元 | ||||||
|  | @ -72,7 +72,7 @@ | ||||||
|         <el-tab-pane label="分销"> |         <el-tab-pane label="分销"> | ||||||
|           <el-form-item label="分佣启用" prop="brokerageEnabled"> |           <el-form-item label="分佣启用" prop="brokerageEnabled"> | ||||||
|             <el-switch v-model="formData.brokerageEnabled" style="user-select: none" /> |             <el-switch v-model="formData.brokerageEnabled" style="user-select: none" /> | ||||||
|             <el-text class="w-full" size="small" type="info"> 商城是否开启分销模式 </el-text> |             <el-text class="w-full" size="small" type="info"> 商城是否开启分销模式</el-text> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|           <el-form-item label="分佣模式" prop="brokerageEnabledCondition"> |           <el-form-item label="分佣模式" prop="brokerageEnabledCondition"> | ||||||
|             <el-radio-group v-model="formData.brokerageEnabledCondition"> |             <el-radio-group v-model="formData.brokerageEnabledCondition"> | ||||||
|  | @ -109,7 +109,7 @@ | ||||||
|             </el-text> |             </el-text> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|           <el-form-item label="分销海报图"> |           <el-form-item label="分销海报图"> | ||||||
|             <UploadImgs v-model="formData.brokeragePosterUrls" width="75px" height="125px" /> |             <UploadImgs v-model="formData.brokeragePosterUrls" height="125px" width="75px" /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               个人中心分销海报图片,建议尺寸 600x1000 |               个人中心分销海报图片,建议尺寸 600x1000 | ||||||
|             </el-text> |             </el-text> | ||||||
|  | @ -117,10 +117,10 @@ | ||||||
|           <el-form-item label="一级返佣比例" prop="brokerageFirstPercent"> |           <el-form-item label="一级返佣比例" prop="brokerageFirstPercent"> | ||||||
|             <el-input-number |             <el-input-number | ||||||
|               v-model="formData.brokerageFirstPercent" |               v-model="formData.brokerageFirstPercent" | ||||||
|               placeholder="请输入一级返佣比例" |  | ||||||
|               class="!w-xs" |  | ||||||
|               :min="0" |  | ||||||
|               :max="100" |               :max="100" | ||||||
|  |               :min="0" | ||||||
|  |               class="!w-xs" | ||||||
|  |               placeholder="请输入一级返佣比例" | ||||||
|             /> |             /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               订单交易成功后给推广人返佣的百分比 |               订单交易成功后给推广人返佣的百分比 | ||||||
|  | @ -129,10 +129,10 @@ | ||||||
|           <el-form-item label="二级返佣比例" prop="brokerageSecondPercent"> |           <el-form-item label="二级返佣比例" prop="brokerageSecondPercent"> | ||||||
|             <el-input-number |             <el-input-number | ||||||
|               v-model="formData.brokerageSecondPercent" |               v-model="formData.brokerageSecondPercent" | ||||||
|               placeholder="请输入二级返佣比例" |  | ||||||
|               class="!w-xs" |  | ||||||
|               :min="0" |  | ||||||
|               :max="100" |               :max="100" | ||||||
|  |               :min="0" | ||||||
|  |               class="!w-xs" | ||||||
|  |               placeholder="请输入二级返佣比例" | ||||||
|             /> |             /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               订单交易成功后给推广人的推荐人返佣的百分比 |               订单交易成功后给推广人的推荐人返佣的百分比 | ||||||
|  | @ -141,9 +141,9 @@ | ||||||
|           <el-form-item label="佣金冻结天数" prop="brokerageFrozenDays"> |           <el-form-item label="佣金冻结天数" prop="brokerageFrozenDays"> | ||||||
|             <el-input-number |             <el-input-number | ||||||
|               v-model="formData.brokerageFrozenDays" |               v-model="formData.brokerageFrozenDays" | ||||||
|               placeholder="请输入佣金冻结天数" |  | ||||||
|               class="!w-xs" |  | ||||||
|               :min="0" |               :min="0" | ||||||
|  |               class="!w-xs" | ||||||
|  |               placeholder="请输入佣金冻结天数" | ||||||
|             /> |             /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               防止用户退款,佣金被提现了,所以需要设置佣金冻结时间,单位:天 |               防止用户退款,佣金被提现了,所以需要设置佣金冻结时间,单位:天 | ||||||
|  | @ -152,10 +152,10 @@ | ||||||
|           <el-form-item label="提现最低金额" prop="brokerageWithdrawMinPrice"> |           <el-form-item label="提现最低金额" prop="brokerageWithdrawMinPrice"> | ||||||
|             <el-input-number |             <el-input-number | ||||||
|               v-model="formData.brokerageWithdrawMinPrice" |               v-model="formData.brokerageWithdrawMinPrice" | ||||||
|               placeholder="请输入提现最低金额" |  | ||||||
|               class="!w-xs" |  | ||||||
|               :precision="2" |  | ||||||
|               :min="0" |               :min="0" | ||||||
|  |               :precision="2" | ||||||
|  |               class="!w-xs" | ||||||
|  |               placeholder="请输入提现最低金额" | ||||||
|             /> |             /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               用户提现最低金额限制,单位:元 |               用户提现最低金额限制,单位:元 | ||||||
|  | @ -164,10 +164,10 @@ | ||||||
|           <el-form-item label="提现手续费" prop="brokerageWithdrawFeePercent"> |           <el-form-item label="提现手续费" prop="brokerageWithdrawFeePercent"> | ||||||
|             <el-input-number |             <el-input-number | ||||||
|               v-model="formData.brokerageWithdrawFeePercent" |               v-model="formData.brokerageWithdrawFeePercent" | ||||||
|               placeholder="请输入提现手续费" |  | ||||||
|               class="!w-xs" |  | ||||||
|               :min="0" |  | ||||||
|               :max="100" |               :max="100" | ||||||
|  |               :min="0" | ||||||
|  |               class="!w-xs" | ||||||
|  |               placeholder="请输入提现手续费" | ||||||
|             /> |             /> | ||||||
|             <el-text class="w-full" size="small" type="info"> |             <el-text class="w-full" size="small" type="info"> | ||||||
|               提现手续费百分比,范围 0-100,0 为无提现手续费。例:设置 10,即收取 10% 手续费,提现 |               提现手续费百分比,范围 0-100,0 为无提现手续费。例:设置 10,即收取 10% 手续费,提现 | ||||||
|  | @ -184,21 +184,22 @@ | ||||||
|                 {{ dict.label }} |                 {{ dict.label }} | ||||||
|               </el-checkbox> |               </el-checkbox> | ||||||
|             </el-checkbox-group> |             </el-checkbox-group> | ||||||
|             <el-text class="w-full" size="small" type="info"> 商城开通提现的付款方式 </el-text> |             <el-text class="w-full" size="small" type="info"> 商城开通提现的付款方式</el-text> | ||||||
|           </el-form-item> |           </el-form-item> | ||||||
|         </el-tab-pane> |         </el-tab-pane> | ||||||
|       </el-tabs> |       </el-tabs> | ||||||
|       <!-- 保存 --> |       <!-- 保存 --> | ||||||
|       <el-form-item> |       <el-form-item> | ||||||
|         <el-button type="primary" @click="submitForm" :loading="formLoading"> 保存 </el-button> |         <el-button :loading="formLoading" type="primary" @click="submitForm"> 保存</el-button> | ||||||
|       </el-form-item> |       </el-form-item> | ||||||
|     </el-form> |     </el-form> | ||||||
|   </ContentWrap> |   </ContentWrap> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup lang="ts"> | <script lang="ts" setup> | ||||||
| import * as ConfigApi from '@/api/mall/trade/config' | import * as ConfigApi from '@/api/mall/trade/config' | ||||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||||
|  | import { cloneDeep } from 'lodash-es' | ||||||
| 
 | 
 | ||||||
| defineOptions({ name: 'TradeConfig' }) | defineOptions({ name: 'TradeConfig' }) | ||||||
| 
 | 
 | ||||||
|  | @ -253,12 +254,7 @@ const submitForm = async () => { | ||||||
|   // 提交请求 |   // 提交请求 | ||||||
|   formLoading.value = true |   formLoading.value = true | ||||||
|   try { |   try { | ||||||
|     const data = { |     const data = cloneDeep(unref(formData.value)) as unknown as ConfigApi.ConfigVO | ||||||
|       ...formData.value |  | ||||||
|     } as unknown as ConfigApi.ConfigVO |  | ||||||
|     data.brokeragePosterUrls = formData.value.brokeragePosterUrls.map((item: any) => { |  | ||||||
|       return item?.url ? item.url : item |  | ||||||
|     }) |  | ||||||
|     // 金额放大 |     // 金额放大 | ||||||
|     data.deliveryExpressFreePrice = data.deliveryExpressFreePrice * 100 |     data.deliveryExpressFreePrice = data.deliveryExpressFreePrice * 100 | ||||||
|     data.brokerageWithdrawMinPrice = data.brokerageWithdrawMinPrice * 100 |     data.brokerageWithdrawMinPrice = data.brokerageWithdrawMinPrice * 100 | ||||||
|  | @ -275,7 +271,6 @@ const getConfig = async () => { | ||||||
|   try { |   try { | ||||||
|     const data = await ConfigApi.getTradeConfig() |     const data = await ConfigApi.getTradeConfig() | ||||||
|     if (data != null) { |     if (data != null) { | ||||||
|       data.brokeragePosterUrls = data.brokeragePosterUrls.map((url) => ({ url })) |  | ||||||
|       formData.value = data |       formData.value = data | ||||||
|       // 金额缩小 |       // 金额缩小 | ||||||
|       formData.value.deliveryExpressFreePrice = data.deliveryExpressFreePrice / 100 |       formData.value.deliveryExpressFreePrice = data.deliveryExpressFreePrice / 100 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 puhui999
						puhui999