2025-03-21 10:15:35 +08:00
< template >
< a -spin :spinning ="confirmLoading" >
2025-08-27 08:53:30 +08:00
< div v -show = " ! isEditMedia "
2025-08-25 14:56:19 +08:00
style = "padding-top: 14px;padding-left: 14px;padding-right: 14px; background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);margin-bottom: 14px;" >
< JFormContainer :disabled ="disabled" >
< template # detail >
< a -form ref = "formRef" :labelCol ="labelCol" :wrapperCol ="wrapperCol" :colon ="false"
name = "ConfigService2DirectiveForm" style = "padding: 0px 0px;" >
< a -row v-show ="!isEditMedia" >
< a -col :span ="8" >
< a -form -item label = "分类标签" v -bind = " validateInfos.instructionTagId "
id = "ConfigServiceDirectiveForm-instructionTagId" name = "instructionTagId" >
< j -dict -select -tag v -model :value ="formData.instructionTagId" :orgCode ="mainOrgCode"
: dictCode = "`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder = "请选择分类标签" allowClear @ upDictCode = "upInstructionDictCode" disabled / >
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="8" >
< a -form -item label = "服务类别" v -bind = " validateInfos.categoryId " id = "ConfigServiceDirectiveForm-categoryId"
name = "categoryId" >
< j -dict -select -tag type = "list" v -model :value ="formData.categoryId" disabled :orgCode ="mainOrgCode"
: dictCode = "categoryDictCode" placeholder = "请选择服务类别" allow - clear @ upDictCode = "upCategoryDictCode" / >
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="8" >
< a -form -item label = "服务类型" v -bind = " validateInfos.typeId " id = "ConfigServiceDirectiveForm-typeId"
name = "typeId" >
< j -dict -select -tag type = "list" v -model :value ="formData.typeId" :dictCode ="typeDictCode"
: orgCode = "mainOrgCode" disabled placeholder = "请选择服务类型" allowClear @ upDictCode = "upTypeDictCode" / >
< / a - f o r m - i t e m >
< / a - c o l >
< / a - r o w >
< / a - f o r m >
< / template >
< / JFormContainer >
< / div >
< div style = "padding: 14px;background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);" >
2025-08-27 08:53:30 +08:00
< JFormContainer >
2025-08-11 17:04:01 +08:00
< template # detail >
< a -form ref = "formRef" class = "antd-modal-form" :labelCol ="labelCol" :wrapperCol ="wrapperCol" :colon ="false"
name = "ConfigService2DirectiveForm" style = "padding: 20px 0px;" >
< a -row v-show ="!isEditMedia" >
2025-08-25 14:56:19 +08:00
<!-- < a -col :span ="12" v-show ="false" >
2025-08-11 17:04:01 +08:00
< a -form -item label = "分类标签" v -bind = " validateInfos.instructionTagId "
id = "ConfigServiceDirectiveForm-instructionTagId" name = "instructionTagId" >
< j -dict -select -tag v -model :value ="formData.instructionTagId" :orgCode ="mainOrgCode"
: dictCode = "`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder = "请选择分类标签" allowClear @ upDictCode = "upInstructionDictCode" : disabled = "!!formData.id" / >
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="12" v-show ="false" >
< a -form -item label = "服务类别" v -bind = " validateInfos.categoryId " id = "ConfigServiceDirectiveForm-categoryId"
name = "categoryId" >
< j -dict -select -tag type = "list" v -model :value ="formData.categoryId" :disabled ="!!formData.id"
: orgCode = "mainOrgCode" : dictCode = "categoryDictCode" placeholder = "请选择服务类别" allow - clear
@ upDictCode = "upCategoryDictCode" / >
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="12" v-show ="false" >
< a -form -item label = "服务类型" v -bind = " validateInfos.typeId " id = "ConfigServiceDirectiveForm-typeId"
name = "typeId" >
< j -dict -select -tag type = "list" v -model :value ="formData.typeId" :dictCode ="typeDictCode"
: orgCode = "mainOrgCode" : disabled = "!!formData.id" placeholder = "请选择服务类型" allowClear
@ upDictCode = "upTypeDictCode" / >
< / a - f o r m - i t e m >
2025-08-25 14:56:19 +08:00
< / a - c o l > - - >
2025-08-11 17:04:01 +08:00
< a -col :span ="12" >
< a -form -item label = "服务指令名称" v -bind = " validateInfos.directiveName "
id = "ConfigServiceDirectiveForm-directiveName" name = "directiveName" >
< a -input v -model :value ="formData.directiveName" placeholder = "请输入服务指令名称" allow -clear :maxlength ="20"
: showCount = "true" : disabled = "!!formData.id" > < / a - i n p u t >
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="12" >
< a -form -item label = "收费价格(元)" v -bind = " validateInfos.tollPrice " id = "ConfigServiceDirectiveForm-tollPrice"
name = "tollPrice" >
< a -input -number v -model :value ="formData.tollPrice" placeholder = "请输入收费价格" style = "width: 100%" :min ="0"
2025-08-26 09:07:44 +08:00
: max = "99999.99" : precision = "2" @ keydown = "onPriceKeydown" : disabled = "disabled" / >
2025-08-11 17:04:01 +08:00
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="12" >
2025-08-15 14:20:51 +08:00
< a -form -item label = "周期类型" v -bind = " validateInfos.cycleType " id = "ConfigServiceDirectiveForm-cycleType"
name = "cycleType" >
< j -dict -select -tag type = "list" v -model :value ="formData.cycleType" dictCode = "period_type"
placeholder = "请选择周期类型" allowClear @ upDictCode = "upCycleTypeDictCode" : disabled = "!!formData.id" / >
2025-08-11 17:04:01 +08:00
< / a - f o r m - i t e m >
< / a - c o l >
< a -col :span ="12" >
< a -form -item label = "提成价格(元)" v -bind = " validateInfos.comPrice " id = "ConfigServiceDirectiveForm-comPrice"
name = "comPrice" >
< a -input -number v -model :value ="formData.comPrice" placeholder = "请输入提成价格" style = "width: 100%" :min ="0"
2025-08-26 09:07:44 +08:00
: max = "99999.99" : precision = "2" @ keydown = "onPriceKeydown" : disabled = "disabled" / >
2025-08-11 17:04:01 +08:00
< / a - f o r m - i t e m >
< / a - c o l >
2025-08-15 14:20:51 +08:00
< a -col :span ="12" >
< a -form -item label = "是否启用" v -bind = " validateInfos.izEnabled " id = "ConfigServiceDirectiveForm-izEnabled"
name = "izEnabled" >
< j -dict -select -tag type = 'radio' v -model :value ="formData.izEnabled" dictCode = "iz_enabled"
2025-08-27 08:53:30 +08:00
placeholder = "请选择是否启用" allowClear : disabled = "disabled" / >
2025-08-15 14:20:51 +08:00
< / a - f o r m - i t e m >
< / a - c o l >
2025-08-11 17:04:01 +08:00
< a -col :span ="12" >
< a -form -item label = "服务时长" v -bind = " validateInfos.serviceDuration "
id = "ConfigServiceDirectiveForm-serviceDuration" name = "serviceDuration" >
< a -input -number v -model :value ="formData.serviceDuration" :min ="5" :max ="55" :step ="5" addon -after = " 分钟 "
2025-08-26 09:07:44 +08:00
placeholder = "请输入服务时长(分钟)" allow - clear @ keydown = "onDurationKeydown" : disabled = "disabled" / >
2025-08-11 17:04:01 +08:00
< / a - f o r m - i t e m >
< / a - c o l >
< / a - r o w >
2025-08-25 14:56:19 +08:00
< a -row style = "padding: 20px;" >
< a -col :span ="6" >
< DirectiveRadioCom :directiveMediaBtnValue ="directiveMediaBtnValue" @change ="mediaBtnChanged" >
< / DirectiveRadioCom >
2025-08-11 17:04:01 +08:00
< / a - c o l >
< / a - r o w >
2025-08-25 14:56:19 +08:00
< a -row style = "padding: 0px 20px;" >
< a -col :span ="24" v-show ="directiveMediaBtnValue == 0" >
2025-09-02 11:15:23 +08:00
< JImageUploadtz v -if = " opeType = = ' dmlook ' "
2025-10-10 09:47:30 +08:00
: value = "!!formData.previewFile ? formData.previewFile : defaultPrePic" maxCount = "1"
2025-08-28 16:03:57 +08:00
: disabled = "disabled || !isMain" / >
2025-10-09 14:49:30 +08:00
< JImageUploadtz v -else v -model :value ="formData.previewFile" maxCount = "1" :toOpe ="true"
: bizPath = "formComputedData.mediaFileSavePath" : disabled = "disabled || !isMain" / >
2025-08-11 17:04:01 +08:00
< / a - c o l >
2025-08-25 14:56:19 +08:00
< a -col :span ="24" v-show ="directiveMediaBtnValue == 1" >
2025-09-02 11:15:23 +08:00
< JImageUploadtz v -if = " opeType = = ' dmlook ' "
2025-10-10 09:47:30 +08:00
: value = "!!formData.previewFileSmall ? formData.previewFileSmall : defaultPreSmallPic"
2025-08-28 16:03:57 +08:00
maxCount = "1" : disabled = "disabled || !isMain" / >
2025-10-09 14:49:30 +08:00
< JImageUploadtz v -else v -model :value ="formData.previewFileSmall" maxCount = "1" :toOpe ="true"
: bizPath = "formComputedData.mediaFileSavePath" : disabled = "disabled || !isMain" / >
2025-08-11 17:04:01 +08:00
< / a - c o l >
2025-08-25 14:56:19 +08:00
< a -col :span ="24" v-show ="directiveMediaBtnValue == 2" >
2025-10-10 09:47:30 +08:00
< JUploadMP3 v -if = " opeType = = ' dmlook ' " : value = " formData.mp3File" maxCount = "1"
2025-08-28 16:03:57 +08:00
: disabled = "disabled || !isMain" / >
2025-10-09 14:49:30 +08:00
< JUploadMP3 v -else v -model :value ="formData.mp3File" :toOpe ="true"
: bizPath = "formComputedData.mediaFileSavePath" maxCount = "1" : disabled = "disabled || !isMain" / >
2025-08-11 17:04:01 +08:00
< / a - c o l >
2025-08-25 14:56:19 +08:00
< a -col :span ="24" v-show ="directiveMediaBtnValue == 3" >
2025-10-10 09:47:30 +08:00
< JUploadMP4 v -if = " opeType = = ' dmlook ' " : value = " formData.mp4File" maxCount = "1"
2025-08-28 16:03:57 +08:00
fileType = "mp4" : disabled = "disabled || !isMain" / >
2025-10-09 14:49:30 +08:00
< JUploadMP4 v -else v -model :value ="formData.mp4File" :toOpe ="true"
: bizPath = "formComputedData.mediaFileSavePath" maxCount = "1" fileType = "mp4"
2025-08-27 08:53:30 +08:00
: disabled = "disabled || !isMain" / >
2025-08-11 17:04:01 +08:00
< / a - c o l >
2025-08-25 14:56:19 +08:00
< a -col :span ="24" v-show ="directiveMediaBtnValue == 4" >
2025-09-02 11:15:23 +08:00
< JImageUploadtz v -if = " opeType = = ' dmlook ' "
2025-10-10 09:47:30 +08:00
: value = "!!formData.immediateFile ? formData.immediateFile : defaultImmediatePic"
2025-08-28 16:03:57 +08:00
maxCount = "1" : disabled = "disabled || !isMain" / >
2025-10-09 14:49:30 +08:00
< JImageUploadtz v -else v -model :value ="formData.immediateFile" :toOpe ="true"
: bizPath = "formComputedData.mediaFileSavePath" maxCount = "1" : disabled = "disabled || !isMain" / >
2025-08-11 17:04:01 +08:00
< / a - c o l >
2025-09-28 13:41:29 +08:00
< a -col :span ="24" v-show ="directiveMediaBtnValue == 5" >
< JImageUploadtz v -if = " opeType = = ' dmlook ' "
2025-10-10 09:47:30 +08:00
: value = "!!formData.immediateFileFocus ? formData.immediateFileFocus : defaultImmediatePic"
2025-09-28 13:41:29 +08:00
maxCount = "1" : disabled = "disabled || !isMain" / >
2025-10-09 14:49:30 +08:00
< JImageUploadtz v -else v -model :value ="formData.immediateFileFocus" :toOpe ="true"
: bizPath = "formComputedData.mediaFileSavePath" maxCount = "1" : disabled = "disabled || !isMain" / >
2025-09-28 13:41:29 +08:00
< / a - c o l >
2025-08-11 17:04:01 +08:00
< / a - r o w >
2025-08-25 14:56:19 +08:00
< a -row style = "padding: 20px;" >
< a -col :span ="2" >
< div class = "description-container" >
< a -button @click ="toggleDescription" > 服务指令描述 < / a -button >
< div v-show ="showDescription" class="description-box" >
< div class = "box-header" >
< span class = "title" > 服务指令描述 < / span >
< span class = "collapse-icon" @click ="toggleDescription" >
< DownOutlined style = "margin-right: 3px;" / > 收起
< / span >
< / div >
< div >
< a -textarea v -model :value ="formData.serviceContent" placeholder = "请输入服务指令描述" :maxlength ="200"
2025-08-27 08:53:30 +08:00
: rows = "3" : autosize = "{ minRows: 3 }" : showCount = "true"
: disabled = "disabled || (!isMain && !!formData.id)" / >
2025-08-25 14:56:19 +08:00
< / div >
< / div >
< / div >
2025-08-11 17:04:01 +08:00
< / a - c o l >
< / a - r o w >
< / a - f o r m >
< / template >
< / JFormContainer >
< / div >
2025-03-21 10:15:35 +08:00
< / a - s p i n >
< / template >
< script lang = "ts" setup >
import { ref , reactive , defineExpose , nextTick , defineProps , computed , onMounted , watch } from 'vue' ;
import { defHttp } from '/@/utils/http/axios' ;
import { useMessage } from '/@/hooks/web/useMessage' ;
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue' ;
import { JCheckbox } from '/@/components/Form' ;
2025-08-26 09:07:44 +08:00
import JUploadMP3 from '../../../../components/Form/src/jeecg/components/JUpload/JUploadMP3.vue' ;
import JUploadMP4 from '../../../../components/Form/src/jeecg/components/JUpload/JUploadMP4.vue' ;
import JImageUploadtz from '/@/components/Form/src/jeecg/components/JImageUploadtz.vue' ;
2025-04-01 09:35:36 +08:00
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue' ;
2025-03-21 10:15:35 +08:00
import { getValueType } from '/@/utils' ;
2025-07-23 08:39:10 +08:00
import { saveOrUpdate , syncMediaForBiz , syncMediaForAllBiz } from '../ConfigServiceDirective.api' ;
2025-03-21 10:15:35 +08:00
import { Form } from 'ant-design-vue' ;
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue' ;
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils' ;
2025-08-07 16:24:07 +08:00
import { env } from 'process' ;
2025-08-11 17:04:01 +08:00
import DirectiveRadioCom from './DirectiveRadioCom.vue'
import { QuestionCircleOutlined } from '@ant-design/icons-vue' ;
import { DownOutlined } from '@ant-design/icons-vue' ;
2025-08-27 08:53:30 +08:00
import { uploadUrl } from '/@/api/common/api' ;
2025-04-01 09:35:36 +08:00
2025-10-09 14:49:30 +08:00
const opeMediaAddress = import . meta . env . VITE _OPE _MEDIA _ADDRESS
2025-08-11 17:04:01 +08:00
const showDescription = ref ( false ) ;
// 切换悬浮容器的显示状态
const toggleDescription = ( ) => {
showDescription . value = ! showDescription . value ;
} ;
2025-09-02 11:15:23 +08:00
const defaultPrePic = import . meta . env . VITE _DEFAULT _DIRECTIVE _PRE _PIC
const defaultPreSmallPic = import . meta . env . VITE _DEFAULT _DIRECTIVE _PRESMALL _PIC
const defaultImmediatePic = import . meta . env . VITE _DEFAULT _DIRECTIVE _IM _PIC
2025-08-11 17:04:01 +08:00
const fileList = ref ( [ ] )
2025-08-06 16:01:50 +08:00
const onPriceKeydown = ( e : KeyboardEvent ) => {
const key = e . key ;
// 放行控制键
if ( [ 'Backspace' , 'Delete' , 'ArrowLeft' , 'ArrowRight' , 'Tab' ] . includes ( key ) ) return ;
// 只能输数字和点
if ( ! /[\d.]/ . test ( key ) ) {
e . preventDefault ( ) ;
return ;
}
const input = e . target as HTMLInputElement ;
const { value , selectionStart : s , selectionEnd : t } = input ;
const next = value . slice ( 0 , s ! ) + key + value . slice ( t ! ) ;
// 整数最多5位, 小数最多2位
if ( ! /^\d{0,5}(?:\.\d{0,2})?$/ . test ( next ) ) {
e . preventDefault ( ) ;
}
} ;
2025-08-11 17:04:01 +08:00
const onDurationKeydown = ( e : KeyboardEvent ) => {
const key = e . key ;
// 放行控制键
if ( [ 'Backspace' , 'Delete' , 'ArrowLeft' , 'ArrowRight' , 'Tab' ] . includes ( key ) ) return ;
// 只能输数字和点
if ( ! /[\d.]/ . test ( key ) ) {
e . preventDefault ( ) ;
return ;
}
const input = e . target as HTMLInputElement ;
const { value , selectionStart : s , selectionEnd : t } = input ;
const next = value . slice ( 0 , s ! ) + key + value . slice ( t ! ) ;
// 整数最多5位, 小数最多2位
if ( ! /^\d{0,2}$/ . test ( next ) ) {
e . preventDefault ( ) ;
}
} ;
2025-03-21 10:15:35 +08:00
const props = defineProps ( {
formDisabled : { type : Boolean , default : false } ,
formData : { type : Object , default : ( ) => ( { } ) } ,
2025-05-27 14:14:07 +08:00
formBpm : { type : Boolean , default : true } ,
2025-08-04 14:48:44 +08:00
mainOrgCode : '' ,
2025-08-07 16:24:07 +08:00
mediaApiAddress : '' , //指令资源请求地址
2025-08-08 09:33:27 +08:00
opeType : 'look' ,
2025-08-27 08:53:30 +08:00
isMain : false , //是否主指令库
2025-03-21 10:15:35 +08:00
} ) ;
2025-08-11 17:04:01 +08:00
const checkMp3 = ( file ) => {
const isPDF = file . type === 'application/mp3' || file . name . endsWith ( '.mp3' ) ;
if ( ! isPDF ) {
createMessage . error ( '只能上传 mp3 文件!' ) ;
return false ; // 阻止上传
}
return true ;
} ;
const checkMp4 = ( file ) => {
const isPDF = file . type === 'application/mp4' || file . name . endsWith ( '.mp4' ) ;
if ( ! isPDF ) {
2025-08-15 14:20:51 +08:00
createMessage . error ( '只能上传 mp4 文件!' ) ;
2025-08-11 17:04:01 +08:00
return false ; // 阻止上传
}
return true ;
} ;
2025-08-06 16:01:50 +08:00
const bodyTagDictCode = ref ( ` nu_config_body_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc ` )
const emotionTagDictCode = ref ( ` nu_config_emotion_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc ` )
2025-03-21 10:15:35 +08:00
const formRef = ref ( ) ;
const useForm = Form . useForm ;
const emit = defineEmits ( [ 'register' , 'ok' ] ) ;
const formData = reactive < Record < string , any > > ( {
id : '' ,
categoryId : '' ,
typeId : '' ,
instructionTagId : '' ,
directiveName : '' ,
tollPrice : 0 ,
comPrice : 0 ,
izReimbursement : '0' ,
izPreferential : '0' ,
chargingFrequency : '' ,
cycleType : '' ,
sort : 99 ,
serviceContent : '' ,
serviceDuration : '5' ,
2025-07-16 08:34:10 +08:00
status : '' ,
izEnabled : '0' ,
2025-03-21 10:15:35 +08:00
createBy : '' ,
createTime : '' ,
updateBy : '' ,
updateTime : '' ,
mp3File : '' ,
mp4File : '' ,
2025-09-02 11:15:23 +08:00
previewFile : defaultPrePic ,
previewFileSmall : defaultPreSmallPic ,
immediateFile : defaultImmediatePic ,
2025-09-28 13:41:29 +08:00
immediateFileFocus : defaultImmediatePic ,
2025-03-21 10:15:35 +08:00
} ) ;
const { createMessage } = useMessage ( ) ;
2025-08-15 14:20:51 +08:00
const labelCol = ref < any > ( { xs : { span : 24 } , sm : { span : 4 } } ) ;
2025-08-11 17:04:01 +08:00
const wrapperCol = ref < any > ( { xs : { span : 24 } , sm : { span : 19 } } ) ;
2025-03-21 10:15:35 +08:00
const confirmLoading = ref < boolean > ( false ) ;
2025-07-15 08:39:29 +08:00
const isEditMedia = ref ( false )
2025-07-16 08:34:10 +08:00
const instructionTagName = ref ( '' )
const categoryName = ref ( '' )
const typeName = ref ( '' )
const cycleTypeName = ref ( '' )
2025-08-08 09:33:27 +08:00
const orgMediaPathAddress = ref ( '' ) //对应机构媒体资源静态访问路径
2025-03-21 10:15:35 +08:00
//表单验证
const validatorRules = reactive ( {
categoryId : [ { required : true , message : '请选择服务类别!' } , ] ,
typeId : [ { required : true , message : '请选择服务类型!' } , ] ,
instructionTagId : [ { required : true , message : '请选择分类标签!' } , ] ,
directiveName : [ { required : true , message : '请输入服务指令名称!' } , ] ,
tollPrice : [ { required : true , message : '请输入收费价格!' } , { pattern : /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/ , message : '请输入正确的金额!' } , ] ,
comPrice : [ { required : false } , { pattern : /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/ , message : '请输入正确的金额!' } , ] ,
2025-08-25 14:56:19 +08:00
// izReimbursement: [{ required: true, message: '请选择是否参与医保报销!' },],
// izPreferential: [{ required: true, message: '请选择是否参与机构优惠!' },],
2025-03-21 10:15:35 +08:00
// chargingFrequency: [{ required: true, message: '请选择收费频次!' },],
cycleType : [ { required : true , message : '请选择周期类型!' } , ] ,
// sort: [{ required: true, message: '请输入排序!' }, { pattern: /^\d+$/, message: '请输入正整数!' },],
serviceDuration : [
{ required : true , message : '请输入服务时长(分钟)!' } ,
{ pattern : /^\d+$/ , message : '请输入正整数!' } ,
{
validator : ( _ , value ) => {
if ( value % 5 !== 0 ) {
return Promise . reject ( '请输入5的倍数!' ) ;
}
return Promise . resolve ( ) ;
} ,
} ,
{
validator : ( _ , value ) => {
if ( value < 5 || value > 55 ) {
return Promise . reject ( '请输入5到55之间的值!' ) ;
}
return Promise . resolve ( ) ;
} ,
} ,
] ,
izEnabled : [ { required : true , message : '请选择是否启用!' } , ] ,
} ) ;
2025-08-06 16:01:50 +08:00
2025-03-21 10:15:35 +08:00
const { resetFields , validate , validateInfos } = useForm ( formData , validatorRules , { immediate : false } ) ;
// 表单禁用
const disabled = computed ( ( ) => {
if ( props . formBpm === true ) {
if ( props . formData . disabled === false ) {
return false ;
} else {
return true ;
}
}
return props . formDisabled ;
} ) ;
2025-07-15 08:39:29 +08:00
const categoryDictCode = ref ( '' )
2025-03-21 10:15:35 +08:00
const typeDictCode = ref ( '' )
2025-07-15 08:39:29 +08:00
// 计算属性:是否可以上传预览图片
const canUploadPreviewImage = computed ( ( ) => {
return formData . instructionTagId &&
formData . categoryId &&
2025-10-09 14:49:30 +08:00
formData . typeId
// &&
// formData.directiveName &&
// formData.cycleType;
2025-07-15 08:39:29 +08:00
} ) ;
//分类标签名称
const instructionComDictCode = ref ( [ ] )
function upInstructionDictCode ( v _ ) {
instructionComDictCode . value = v _
}
//服务类别名称
const categoryComDictCode = ref ( [ ] )
function upCategoryDictCode ( v _ ) {
categoryComDictCode . value = v _
}
//服务类型名称
const typeComDictCode = ref ( [ ] )
function upTypeDictCode ( v _ ) {
typeComDictCode . value = v _
}
//周期类型名称
const cycleTypeComDictCode = ref ( [ ] )
function upCycleTypeDictCode ( v _ ) {
cycleTypeComDictCode . value = v _
}
2025-07-16 08:34:10 +08:00
//体型标签名称
const upBodyTagsComDictCode = ref ( [ ] )
function upBodyTagsDictCode ( v _ ) {
upBodyTagsComDictCode . value = v _
}
//情绪标签名称
const upEmotionTagsComDictCode = ref ( [ ] )
function upEmotionTagsDictCode ( v _ ) {
upEmotionTagsComDictCode . value = v _
}
2025-07-15 08:39:29 +08:00
2025-07-16 08:34:10 +08:00
watch ( [ instructionComDictCode , categoryComDictCode , typeComDictCode , cycleTypeComDictCode , upBodyTagsComDictCode , upEmotionTagsComDictCode ] , ( ) => {
// 当这些字典数据变化时,强制重新计算 formComputedData
2025-07-15 08:39:29 +08:00
} , { deep : true } ) ;
2025-07-16 08:34:10 +08:00
const bodyTagsObj = ref ( [ ] )
const emotionTagsObj = ref ( [ ] )
const formComputedData = computed ( ( ) => {
if ( ! canUploadPreviewImage . value ) return { } ;
2025-07-15 08:39:29 +08:00
// 获取各个字段的字典值
2025-07-16 08:34:10 +08:00
const instructionName = instructionComDictCode . value . find ( d => d . value == formData . instructionTagId ) ? . label || '' ;
2025-10-09 14:49:30 +08:00
console . log ( "🌊 ~ instructionName:" , instructionName )
2025-07-16 08:34:10 +08:00
const categoryName = categoryComDictCode . value . find ( d => d . value == formData . categoryId ) ? . label || '' ;
2025-10-09 14:49:30 +08:00
console . log ( "🌊 ~ categoryName:" , categoryName )
2025-07-16 08:34:10 +08:00
const typeName = typeComDictCode . value . find ( d => d . value == formData . typeId ) ? . label || '' ;
2025-10-09 14:49:30 +08:00
console . log ( "🌊 ~ typeName:" , typeName )
2025-07-16 08:34:10 +08:00
const cycleTypeName = cycleTypeComDictCode . value . find ( d => d . value == formData . cycleType ) ? . label || '' ;
2025-07-15 08:39:29 +08:00
2025-07-16 08:34:10 +08:00
// 处理标签
const processTags = ( tags , dict ) => {
if ( ! tags ) return [ ] ;
return tags . split ( ',' )
. map ( id => dict . find ( d => d . value === id ) )
. filter ( Boolean )
. map ( item => ( { id : item . value , label : item . label } ) ) ;
} ;
return {
2025-10-09 14:49:30 +08:00
// mediaFileSavePath: `directive/${instructionName}/${categoryName}/${typeName}/${cycleTypeName}/${formData.directiveName}`,
mediaFileSavePath : ` directive/ ${ instructionName } / ${ categoryName } / ${ typeName } ` ,
2025-07-16 08:34:10 +08:00
instructionName ,
categoryName ,
typeName ,
cycleTypeName ,
bodyTagsObj : JSON . stringify ( processTags ( formData . bodyTags , upBodyTagsComDictCode . value ) ) ,
emotionTagsObj : JSON . stringify ( processTags ( formData . emotionTags , upEmotionTagsComDictCode . value ) )
} ;
2025-07-15 08:39:29 +08:00
} ) ;
2025-03-21 10:15:35 +08:00
2025-07-15 08:39:29 +08:00
watch (
( ) => formData . instructionTagId ,
( newInstructionTagId ) => {
2025-07-28 10:25:47 +08:00
if ( needWatch . value ) {
2025-07-15 08:39:29 +08:00
formData . categoryId = ''
formData . typeId = ''
2025-08-25 14:56:19 +08:00
// formData.cycleType = ''
2025-07-28 10:25:47 +08:00
}
if ( ! newInstructionTagId ) {
2025-07-15 08:39:29 +08:00
categoryDictCode . value = 'nu_config_service_category,category_name,id,1=2' ;
} else {
2025-08-07 16:24:07 +08:00
categoryDictCode . value = ` nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 and instruction_id = ' ${ newInstructionTagId } ' order by sort asc ` ;
2025-07-15 08:39:29 +08:00
}
}
) ;
2025-03-21 10:15:35 +08:00
watch (
( ) => formData . categoryId ,
( newCategoryId ) => {
2025-07-28 10:25:47 +08:00
if ( needWatch . value ) {
2025-07-15 08:39:29 +08:00
formData . typeId = ''
2025-08-25 14:56:19 +08:00
// formData.cycleType = ''
2025-07-28 10:25:47 +08:00
}
if ( ! newCategoryId ) {
2025-08-07 16:24:07 +08:00
typeDictCode . value = 'nu_config_service_type,type_name,id,1=2' ;
2025-03-21 10:15:35 +08:00
} else {
2025-08-07 16:24:07 +08:00
typeDictCode . value = ` nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = ' ${ newCategoryId } ' order by sort asc ` ;
2025-03-21 10:15:35 +08:00
}
}
) ;
2025-07-28 10:25:47 +08:00
watch (
( ) => formData . typeId ,
( newTypeId ) => {
if ( needWatch . value ) {
2025-08-25 14:56:19 +08:00
// formData.cycleType = ''
2025-07-28 10:25:47 +08:00
}
}
) ;
2025-03-21 10:15:35 +08:00
/ * *
* 新增
* /
function add ( ) {
edit ( { } ) ;
}
2025-07-28 10:25:47 +08:00
const needWatch = ref ( false )
2025-08-04 14:48:44 +08:00
const showMedia = ref ( true )
2025-03-21 10:15:35 +08:00
/ * *
* 编辑
2025-07-15 08:39:29 +08:00
* isEditMedia _是否为编辑指令资源 ( 隐藏业务字段 )
2025-03-21 10:15:35 +08:00
* /
2025-08-06 16:01:50 +08:00
function edit ( record , isEditMedia _ = false , showMedia _ = true , showExistTags = true ) {
if ( ! ! record . bodyTags && showExistTags ) {
// 将逗号分隔的字符串转换为 "id = 'id1' or id = 'id2'" 格式
const bodyTagConditions = record . bodyTags . split ( ',' )
. map ( id => ` id = ' ${ id } ' ` )
. join ( ' or ' ) ;
bodyTagDictCode . value = ` nu_config_body_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 ` +
( bodyTagConditions ? ` and ( ${ bodyTagConditions } ) ` : '' ) +
` order by sort asc ` ;
}
if ( ! ! record . emotionTags && showExistTags ) {
// 将逗号分隔的字符串转换为 "id = 'id1' or id = 'id2'" 格式
const emotionTagConditions = record . emotionTags . split ( ',' )
. map ( id => ` id = ' ${ id } ' ` )
. join ( ' or ' ) ;
emotionTagDictCode . value = ` nu_config_emotion_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 ` +
( emotionTagConditions ? ` and ( ${ emotionTagConditions } ) ` : '' ) +
` order by sort asc ` ;
}
2025-07-28 10:25:47 +08:00
needWatch . value = false
2025-08-04 14:48:44 +08:00
showMedia . value = showMedia _
2025-07-28 10:25:47 +08:00
setTimeout ( ( ) => {
needWatch . value = true
} , 1000 )
2025-07-15 08:39:29 +08:00
isEditMedia . value = isEditMedia _
2025-04-28 16:08:53 +08:00
formData . bodyTags = ''
formData . emotionTags = ''
2025-03-21 10:15:35 +08:00
nextTick ( ( ) => {
resetFields ( ) ;
const tmpData = { } ;
Object . keys ( formData ) . forEach ( ( key ) => {
if ( record . hasOwnProperty ( key ) ) {
tmpData [ key ] = record [ key ]
}
} )
//赋值
Object . assign ( formData , tmpData ) ;
2025-09-03 09:25:14 +08:00
if ( props . opeType != 'dmlook' ) {
if ( ! formData . previewFile ) {
formData . previewFile = defaultPrePic
}
if ( ! formData . previewFileSmall ) {
formData . previewFileSmall = defaultPreSmallPic
}
if ( ! formData . immediateFile ) {
formData . immediateFile = defaultImmediatePic
}
2025-09-28 13:41:29 +08:00
if ( ! formData . immediateFileFocus ) {
formData . immediateFileFocus = defaultImmediatePic
}
2025-09-03 09:25:14 +08:00
}
2025-03-21 10:15:35 +08:00
} ) ;
}
/ * *
* 提交数据
* /
async function submitForm ( ) {
try {
// 触发表单验证
await validate ( ) ;
} catch ( { errorFields } ) {
if ( errorFields ) {
const firstField = errorFields [ 0 ] ;
if ( firstField ) {
formRef . value . scrollToField ( firstField . name , { behavior : 'smooth' , block : 'center' } ) ;
}
}
return Promise . reject ( errorFields ) ;
}
confirmLoading . value = true ;
const isUpdate = ref < boolean > ( false ) ;
//时间格式化
2025-07-16 08:34:10 +08:00
const computedData = formComputedData . value ;
const model = {
... formData ,
... computedData
} ;
2025-03-21 10:15:35 +08:00
if ( model . id ) {
isUpdate . value = true ;
}
//循环数据
for ( let data in model ) {
//如果该数据是数组并且是字符串类型
if ( model [ data ] instanceof Array ) {
let valueType = getValueType ( formRef . value . getProps , data ) ;
//如果是字符串类型的需要变成以逗号分割的字符串
if ( valueType === 'string' ) {
model [ data ] = model [ data ] . join ( ',' ) ;
}
}
}
2025-03-21 14:23:45 +08:00
//提成价格不能高于收费价格
2025-08-06 16:01:50 +08:00
if ( model . comPrice != 0 && model . tollPrice < model . comPrice ) {
2025-03-21 14:23:45 +08:00
createMessage . warning ( '提成价格不能高于收费价格!' ) ;
confirmLoading . value = false ;
2025-07-16 08:34:10 +08:00
return
2025-03-21 14:23:45 +08:00
}
2025-07-23 08:39:10 +08:00
model . mediaFileSavePath = formComputedData . value . mediaFileSavePath
2025-09-03 09:25:14 +08:00
if ( model . previewFile == defaultPrePic ) {
model . previewFile = null
}
if ( model . previewFileSmall == defaultPreSmallPic ) {
model . previewFileSmall = null
}
if ( model . immediateFile == defaultImmediatePic ) {
model . immediateFile = null
}
2025-09-28 13:41:29 +08:00
if ( model . immediateFileFocus == defaultImmediatePic ) {
model . immediateFileFocus = null
}
2025-09-03 09:25:14 +08:00
2025-03-21 10:15:35 +08:00
await saveOrUpdate ( model , isUpdate . value )
. then ( ( res ) => {
if ( res . success ) {
createMessage . success ( res . message ) ;
emit ( 'ok' ) ;
} else {
createMessage . warning ( res . message ) ;
}
} )
. finally ( ( ) => {
confirmLoading . value = false ;
} ) ;
}
2025-07-23 08:39:10 +08:00
/ * *
* 同步媒体资源给指令所有者对应业务平台
*
* /
function syncMediaForBizFunc ( ) {
formData . mediaFileSavePath = formComputedData . value . mediaFileSavePath
syncMediaForBiz ( formData )
. then ( ( res ) => {
createMessage . success ( '操作成功!' ) ;
emit ( 'ok' ) ;
} )
. finally ( ( ) => {
confirmLoading . value = false ;
} ) ;
}
/ * *
* 同步媒体资源给所有业务平台
*
* /
function syncMediaForAllBizFunc ( ) {
formData . mediaFileSavePath = formComputedData . value . mediaFileSavePath
syncMediaForAllBiz ( formData )
. then ( ( res ) => {
createMessage . success ( '操作成功!' ) ;
emit ( 'ok' ) ;
} )
. finally ( ( ) => {
confirmLoading . value = false ;
} ) ;
}
2025-08-11 17:04:01 +08:00
const directiveMediaBtnValue = ref ( 0 )
function mediaBtnChanged ( v _ ) {
directiveMediaBtnValue . value = v _
}
2025-08-07 16:24:07 +08:00
onMounted ( ( ) => {
} )
2025-03-21 10:15:35 +08:00
defineExpose ( {
add ,
edit ,
submitForm ,
2025-07-23 08:39:10 +08:00
syncMediaForBizFunc ,
syncMediaForAllBizFunc
2025-03-21 10:15:35 +08:00
} ) ;
< / script >
< style lang = "less" scoped >
. antd - modal - form {
padding : 14 px ;
}
2025-08-11 17:04:01 +08:00
: deep . ant - checkbox - wrapper {
margin - top : 5 px ;
margin - bottom : 10 px ;
width : 30 % ;
}
. upload - area {
display : flex ;
flex - direction : column ;
align - items : center ;
justify - content : center ;
}
. upload - icon {
margin - bottom : 16 px ;
}
. upload - text {
font - size : 16 px ;
color : rgba ( 0 , 0 , 0 , 0.85 ) ;
margin - bottom : 8 px ;
}
. upload - hint {
font - size : 12 px ;
color : rgba ( 0 , 0 , 0 , 0.45 ) ;
display : flex ;
align - items : center ;
gap : 8 px ;
}
. divider {
color : rgba ( 0 , 0 , 0 , 0.2 ) ;
}
. description - container {
position : relative ;
z - index : 1000 ;
}
. description - box {
position : absolute ;
bottom : 100 % ;
left : 0 ;
background : # f6faff ;
border - radius : 4 px ;
padding : 12 px ;
width : 43 vw ;
box - shadow : 0 3 px 10 px rgba ( 0 , 0 , 0 , 0.1 ) ;
margin - bottom : 8 px ;
}
. box - header {
display : flex ;
justify - content : space - between ;
align - items : center ;
padding - bottom : 8 px ;
margin - bottom : 12 px ;
}
. title {
font - weight : bold ;
font - size : 16 px ;
}
. collapse - icon {
color : # 1890 ff ;
cursor : pointer ;
}
. content {
background : # fff ;
border - radius : 4 px ;
padding : 12 px ;
position : relative ;
}
. instruction {
color : # 8 c8c8c ;
margin - bottom : 30 px ;
}
. confirm - btn {
position : absolute ;
right : 12 px ;
bottom : 12 px ;
background : # 1890 ff ;
border - radius : 20 px ;
}
/* 渐隐渐现动画 */
. slide - fade - enter - active {
transition : opacity 0.3 s ease - out ;
}
. slide - fade - leave - active {
transition : opacity 0.3 s cubic - bezier ( 0.5 , 0 , 0.8 , 1 ) ;
}
/* 进入时从透明开始 */
. slide - fade - enter - from {
opacity : 0 ;
}
/* 离开时渐变到透明 */
. slide - fade - leave - to {
opacity : 0 ;
}
/* 确保容器初始状态无变形 */
. slide - fade - enter - to ,
. slide - fade - leave - from {
opacity : 1 ;
}
2025-09-28 13:41:29 +08:00
< / style >