paas常用代码块配置

1.开始和结束时间的值校验事件

const [value, rule, ctx] = arguments

const fields = Object.values(ctx.form.fields).filter(f => f.data)
const field = fields.find(item => item?.data.source?.field?.apiName === 'market_time_end')
let endDate = field.value

if (endDate) {
  endDate = new Date(endDate).getTime()
  if (value && endDate < new Date(value).getTime()) {
    return '投放开始时间必须小于等于投放截止时间'
  }
  
  if (field.errors && field.errors.length) {
    field.validate()
  }
}
const [value, rule, ctx] = arguments

const fields = Object.values(ctx.form.fields).filter(f => f.data)
const field = fields.find(item => item?.data.source?.field?.apiName === 'market_time_start')
let startDate = field.value

if (startDate) {
  startDate = new Date(startDate).getTime()
  if (value && startDate > new Date(value).getTime()) {
    return '投放截止时间必须大于等于投放开始时间'
  }
  
  if (field && field.errors && field.errors.length) {
    field.validate()
  }
}

2.手机和邮箱必填一个的值校验事件

手机字段:

const [value, rule, ctx ] = arguments

// 翻译方法
const getTrans = ctx?.getTranslateText


function getGeneralFieldByApiName(apiName){
  const {extendsParams:{fieldQueue}, form} = ctx
  const field = fieldQueue?.find(f=>f.field?.apiName === apiName)
    
  return form?.query(field?.field?.instanceCode)?.take()
}

const field = getGeneralFieldByApiName('c_email')

if(!field.value && !value) {
  return getTrans('messageTip.phoneOrEmail', ' 手机号码和邮箱必须填一个')
}

邮箱字段:

const [value, rule, ctx ] = arguments
// 翻译方法
const getTrans = ctx?.getTranslateText

function getGeneralFieldByApiName(apiName){
  const {extendsParams:{fieldQueue}, form} = ctx
  const field = fieldQueue?.find(f=>f.field?.apiName === apiName)
    
  return form?.query(field?.field?.instanceCode)?.take()
}

const field = getGeneralFieldByApiName('c_mobile')
if(!field.value && !value) {
  return getTrans('messageTip.phoneOrEmail', ' 手机号码和邮箱必须填一个')
}

 

3.表单国际化处理的方法

const [value, rule, ctx ] = arguments

// 翻译方法
const getTrans = ctx?.getTranslateText

getTrans('messageTip.phoneOrEmail', ' 手机号码和邮箱必须填一个')

4.表单值改变事件

const [value, form, fieldQueue, bindObj] = arguments

function getInsCode(fieldCode){
  const field = fieldQueue?.find(f => f.field?.apiName === fieldCode)
  return form?.query(field?.field?.instanceCode)?.take()
}

const doThing = () => {
  getInsCode('market_time')?.setValue('')
  getInsCode('market_time_start')?.setValue('')
  getInsCode('market_time_end')?.setValue('')
  getInsCode('rotating_mode')?.setValue('')
  getInsCode('eventing')?.setValue('')
}
doThing()
const [value, form, fieldQueue, bindObj] = arguments

function getInsCode(fieldCode){
  const field = fieldQueue?.find(f => f.field?.apiName === fieldCode)
  return form?.query(field?.field?.instanceCode)?.take()
}

const data = JSON.parse(sessionStorage.getItem('$_channel_account_list'))

const emailUsername = data?.emailUsername.map(item => ({
  label: item,
  value: item,
}))
const smsUsername = data?.smsUsername.map(item => ({
  label: item,
  value: item,
}))
const doThing = () => {
  const type = getInsCode('type').value
  const channel_account = getInsCode('channel_account')
  const channel_value = getInsCode('channel_value')
  const channel_value_domain = getInsCode('channel_value_domain')
  const recipient = getInsCode('recipient')
  const message_recipient = getInsCode('message_recipient')
  const email_content = getInsCode('email_content')
  const sms_content = getInsCode('sms_content')
  channel_account?.setValue('')
  channel_value?.setValue('')
  channel_value_domain?.setValue('')
  email_content?.setValue('')
  sms_content?.setValue('')
  setTimeout(() => {
    recipient?.setValue('')
    message_recipient?.setValue('')
  }, 100)
  
  
  if (type === 'ST_0') {
    // 邮件
    channel_account?.setComponentProps({ placeholder: '请选择Umail账号' })
    channel_account?.setComponentProps({
      onVisibleChange() {
        channel_account.setDataSource(emailUsername)
      }
    })
  } else {
    channel_account?.setComponentProps({ placeholder: '请选择账号' })
    channel_account?.setComponentProps({
      onVisibleChange() {
        channel_account.setDataSource(smsUsername)
      }
    })
  }
}
doThing()

5.表单渲染完成事件

pc端:

const [form, deferredObj, bindObj, fieldQueue, basicInfo] = arguments
const { primaryVal, pageParamType } = basicInfo
console.log('arguments', arguments)

function getGeneralFieldByApiName(fieldCode){
  const field = fieldQueue?.find(f => f.field?.apiName === fieldCode)
  return form?.query(field?.field?.instanceCode)?.take()
}

if(!primaryVal && pageParamType.allocationStatus == 0 ) {
  const poolField = getGeneralFieldByApiName('c_leads_pool')
  poolField.setValue(pageParamType.poolId)
}

  const lxr = getGeneralFieldByApiName('c_follow_up_contact')
 
  deferredObj[lxr.data?.source?.field.instanceCode].promise.then(() => {
    if (pageParamType.followUpMatterId && pageParamType.parentObjectCode === 'c_contact') {
      lxr.setValue([pageParamType.followUpMatterId])
    }
  })

移动端:

const [form, deferredObj, bindObj, fieldQueue, mode, basicInfo] = arguments
const { primaryVal, pageParamType } = basicInfo

const fields = Object.values(form.fields).filter(f => f.data)
function getGeneralFieldByApiName(fieldCode) {
  const field = fields?.find(f => f?.data?.source?.field?.apiName === fieldCode)
  return form?.query(field?.data?.source?.field?.instanceCode)?.take?.()
}

if(!primaryVal && pageParamType.allocationStatus == 0 ) {
  const poolField = getGeneralFieldByApiName('c_leads_pool')
  poolField.setValue(pageParamType.poolId)
}

6.自定义按钮打开弹框列表,请求不用fetch,使用平台的request

<template>
  <el-dialog v-model="visible" title="线索去重" :width="1300" @close="handleClose">
    <section class="page">
      <LowCodePaasList
        ref="lowCodePaasListRef"
        objectCode="c_leads"
        :layoutCodeLoad="layoutCode"
        :extendsParams="extendsParams"
        :table-height="390"
        :switchView="false"
        isPopupSelection
        @initFinshed="tableInitFinshed"
        @handleSelectionChange="handleSelectionChange"
      ></LowCodePaasList>
    </section>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose" size="default" type="sceondary">关闭</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
  import { ref, nextTick, defineOptions, defineProps, useAttrs, defineExpose, watch, computed } from 'vue'
  import { ElMessage } from 'element-plus'
  defineOptions({
    name: 'leadsCheck'
  })
  
  let attrs = useAttrs()
  const props = defineProps({
    data: {
      type: Object,
      default: () => ({}),
    },
    baseApi: {
        type: Object,
        default: () => ({}),
      },
    XToken: {
        type: String,
        default: ''
      },
    request: {
      type: Object,
        default: () => ({}),
    }
  })
  const lowCodePaasListRef = ref(null)
  const extendsParams:any = ref({})
  const visible = ref(false)
  const layoutCode = ref('LYT_h7ujw2lqlf') 

  const hook = ref(null)

  const init = (info?, callback?) => {
    console.log('open', info, callback, props)
    hook.value = callback
    getData(info)
  }

  const showDialog = (data) => {
    let extendsParam = {
      dialogConfig: {
        showDialogFooter: true,
        singleChoice: false
      },
      hasExpandButton: false,
      // 列表打开判断逻辑,新增属性表示打开列表来源
      // 列表中 isFormilyPopupSelection 判断使用
      source: 'customCode',
      multiple: false,
    }
  
    extendsParams.value = extendsParam
    sessionStorage.setItem('$advanced_search_keys_pageparam', JSON.stringify({
      id: data
    }))

    visible.value = true
  }

  
  const getData =(info)=>{
    return new Promise((resolve,reject) => {
      let url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime-extender/leads/duplicateCheck`
      let dataObj = {
        email: info.apiValues.c_email,
        mobile: info.apiValues.c_mobile,
        id: basicInfo().primaryVal
      }
      props.request({
        url,
        method: 'post',
        data: dataObj
      }).then((res) => {
          const data = res.data || {}
          if(data.duplication){
            showDialog(data.data)
          } else{
            callback.handleSubmit()
          }
        }).catch(()=>{
          reject()
        })
    })
  }
  
  const handleClose = () => {
    visible.value = false
  }
  
  defineExpose({
    init
  })
  </script>
  <style>
  
  </style>
  

7.点击按钮打开表单

pc端:

<template>
  <div>
    <FormResult ref="formResultRef"  @update="refreshFn"></FormResult>
  </div>
</template>


<script setup>
  import { ref, inject } from 'vue'
  import { ElMessage } from 'element-plus'
  import FormResult from 'FormResult'
  const basicInfo = inject('basicInfo')
  const refresh = inject('refresh')
  const refreshFn = () => {
    refresh?.()
  }
  const formResultRef = ref(null)
  
  const props = defineProps({
    data: {
      type: Object,
      default: () => ({}),
    },
    baseApi: {
        type: Object,
        default: () => ({}),
      },
    XToken: {
        type: String,
        default: ''
      }
  })
  const callbackFn = ref()
  
 //  callback 对象下可能会有 handleSubmit cancelSubmit  validateFormWidget(表单验证) 等方法。
  const init = (info,callback) =>{
    console.log(info,callback)
    callbackFn.value = callback
    const param = {
        "objectCode": "c_visit_schedule",
        "layoutCode": "C_LYT_aimwg07hcy",
        "openType": "Dialog",
        "pageParamType": {
          "businessTypeCode": 'C_BTE_qs5a0vlvgd',
          "clueId": info?.context?.pageParamType?.id
        }
     }
    formResultRef.value.open({ param }, callbackFn.value)
  }
                   
  defineExpose({
    init
  })
 
</script>

移动端:

<template>
  <div>
    <van-action-sheet v-model:show="dialogVisible" title="业务类型" :close="handleClose">
      <van-cell v-for="row,index in typeList" :key="index" :title="row.name" value="选择" @click="check(row)" value-class="valueBtn"/>
    </van-action-sheet>
  </div>
</template>


<script setup>
  import { ref, inject, useAttrs } from 'vue'
  import { Toast, Cell, ActionSheet } from 'vant';
  const attrs = useAttrs()
  const { router } = attrs
  // import { ElMessage } from 'element-plus'
  // import FormResult from 'FormResult'
  const basicInfo = inject('basicInfo')
  const refresh = inject('refresh')
  const refreshFn = () => {
    refresh?.()
  }
  // const formResultRef = ref(null)
  const typeList = ref([])
  const dialogVisible = ref(false)
  
  const props = defineProps({
    data: {
      type: Object,
      default: () => ({}),
    },
    baseApi: {
        type: Object,
        default: () => ({}),
      },
    XToken: {
        type: String,
        default: ''
      }
  })
  
  const callbackFn = ref()
  
 //  callback 对象下可能会有 handleSubmit cancelSubmit  validateFormWidget(表单验证) 等方法。
  const init = (info,callback) =>{
    console.log(info,callback,"====1111")
    callbackFn.value = callback
    // dialogVisible.value = true
    // typeList.value = [
    //   {selectorId:'C_BTE_sk1vgdtc4f',selectorName:'联系人'},
    //   {selectorId:'C_BTE_qs5a0vlvgd',selectorName:'线索'},
    //   {selectorId:'C_BTE_sfuzglu572',selectorName:'出差'},
    //   {selectorId:'C_BTE_t3k33kasmn',selectorName:'客户'},
    // ]
    getData(info).then(res => {
      typeList.value = res.data || []
      if (typeList.value.length > 1) {
        dialogVisible.value = true
      } else if (typeList.value.length === 1) {
        sessionStorage.setItem('$_form_params', JSON.stringify({
          "objectCode": "c_visit_schedule",
          "layoutCode": "C_LYT_pq2uivc0jj",
          "openType": "Drawer",
          "pageParamType": {
            "businessTypeCode": typeList.value[0].code,
          }
        }))
        router.push(`/form`)
      } else if (res.data.length === 0) {
        showToast("无可用的业务类型,请联系管理员")
      }
    })
  }
                   
  defineExpose({
    init
  })

  const check = (row) => {
    sessionStorage.setItem('$_form_params', JSON.stringify({
      "objectCode": "c_visit_schedule",
      "layoutCode": "C_LYT_pq2uivc0jj",
      "openType": "Drawer",
      "pageParamType": {
        "businessTypeCode": row.code,
      }
    }))
    dialogVisible.value = false
    router.push(`/form`)
  }
  const getData =(info)=>{
    return new Promise((resolve) => {
      let url = `${props.baseApi.VITE_APP_PAAS_BASE_API}/runtime/businessType/c_visit_schedule/list`
      fetch(url, {
        method: 'get',
        headers: { 
            'X-Token': props.XToken ,
            'Content-Type': 'application/json'
        },
      })
        .then((res) => {
          return res.json()
        })
        .then((res) => {
          const data = res.data || {}
          // const { selectors = [], selectIdMappingValue, selectNameMappingValue } = data
          resolve({
            data
          })
        })
    })
  }
</script>
<style>
  .valueBtn {
    color: #165DFF !important;
  }
</style>
sessionStorage.setItem('$_form_params', JSON.stringify({
    businessType: baseInfo.value?.context.businessType,
    layoutCode: layoutCode,
    layoutCodeLoad: layoutCode,
    objectCode: "c_visit_record",
    openType: "Dialog",
    primaryVal: res.data?.recordId || null,
    pageParamType: {
      ...obj,
      scheduleId: baseInfo.value?.context.id
    }
  }))
  hook.value.router.push(`/form?layoutCode=${layoutCode}&objectCode=c_visit_record`)

8.自定义按钮打开sdk组件

<template>
  <tenant-expansion-component
    ref="sdkComponent"
    code="tenant_sdk_CPT_qo0d7yy06e"
  />
</template>

<script setup>
  import { provide, ref } from 'vue'
  const sdkComponent = ref()
  const init = (info, callback) => {
    sdkComponent.value.dynamic?.open({
      dataId: info?.context?.id
    })
  }
  defineExpose({
    init
  })
</script>

9.自定义按钮国际化提示

<template>
</template>
<script lang="ts" setup>
// 联系人-新建保存按钮
import { nextTick, ref, inject } from 'vue'
import { ElMessage } from 'element-plus'
const getTrans = inject('getTranslateText')

const props = defineProps({
  baseApi: {
    type: Object,
    default: () => ({})
  },
  XToken: {
    type: String,
    default: ''
  }
})

const baseInfo = ref(null)
const hook = ref(null)

const init = (info, callback) => {
  baseInfo.value = info
  hook.value = callback
  console.log(info, callback, props)
  formValidate()
}

async function formValidate() {
  let url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime-extender/contact/save`
  let params = {
    code: baseInfo.value.apiValues.c_code,
    name: baseInfo.value.apiValues.c_name,
    businessTypeCode: baseInfo.value.apiValues.business_type_code,
    customerId: baseInfo.value.apiValues.c_customer_id,
    gender: baseInfo.value.apiValues.c_gender,
    role: baseInfo.value.apiValues.c_role,
    department: baseInfo.value.apiValues.c_department,
    position: baseInfo.value.apiValues.c_position,
    ownerId: baseInfo.value.apiValues.data_owner_id,
    remark: baseInfo.value.apiValues.c_remark,
    mobile: baseInfo.value.apiValues.c_mobile,
    email: baseInfo.value.apiValues.c_email,
    spareMobile: baseInfo.value.apiValues.c_spare_mobile,
    businessCard: baseInfo.value.apiValues.c_business_card
  }
  if (!params.mobile && !params.email) {
    ElMessage.warning(getTrans()('messageTip.phoneNoEmpty', '联系人: 手机和邮箱必须填一个'))
    return
  }
  fetch(url, {
    method: 'post',
    headers: { 'X-Token': props.XToken, 'Content-Type': 'application/json' },
    body: JSON.stringify(params)
  }).then((res) => {
    return res.json()
  }).then((res) => {
    if (res.code === '0') {
      ElMessage.success(res.msg || '')
      hook.value.closeDialog()
      hook.value.refreshList()
    } else {
      ElMessage.warning(res.msg || '')
    }
  })
}

defineExpose({
  init
})
</script>
<style lang='scss' scoped>
</style>

10.自定义按钮打开详情抽屉

<template>
  <LowCodePaasDetail ref="LowCodePaasDetailRef" />
</template>
<script setup>
import { ref } from 'vue'
import LowCodePaasDetail from 'low-code-paas-detail'
const props = defineProps({
  data: {
    type: Object,
    default: () => ({}),
  },
  objectCode: {
    type: String,
    default: '',
  },
})
const LowCodePaasDetailRef = ref(null)

const init = (p1, p2) => {
LowCodePaasDetailRef.value.initData({openType: 'Drawer',objectCode: 'c_marketing_activity', columnValue: p1?.context?.id})
}
defineExpose({
init
})
</script>

11.表单渲染完成后事件更改弹框的标题

const [form, deferredObj, bindObj, fields, btnInfo] = arguments

const { primaryVal, businessType } = btnInfo
const prefix = primaryVal ? '编辑 ' : '新建 '
if (businessType === 'BTE_0000000000') {
  bindObj.setDialogTitle(prefix + '品牌方')
} else {
  bindObj.setDialogTitle(prefix + '合作伙伴')
}

12.自定义按钮保存表单

<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import { ElMessage } from 'element-plus'
import RuleDialog from 'RuleDialog'

const props = defineProps({
  baseApi: {
    type: Object,
    default: () => ({})
  },
  XToken: {
    type: String,
    default: ''
  }
})

const baseInfo = ref(null)
const hook = ref(null)
const ruleOpenDialog = ref(null)
const rowId = ref('')

const init = (info, callback) => {
  baseInfo.value = info
  hook.value = callback
  console.log('init', info, callback, props)
  callback.validateFormWidget().then((res) => {
    formSubmit(res)
  }).catch((err) => {
    console.error(err)
  })
}// 表单提交
async function formSubmit(params) {
  let url = ''
  if (baseInfo.value.context.id) {
    url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime/bizData/c_order/${baseInfo.value.context.id}`
  } else {
    url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime/bizData/c_order`
  }
  fetch(url, {
    method: baseInfo.value.context.id ? 'put' : 'post',
    headers: { 'X-Token': props.XToken, 'Content-Type': 'application/json' },
    body: JSON.stringify(params)
  }).then((res) => {
    return res.json()
  }).then((res) => {
    if (res.code === '0') {
      ElMessage.success(res.msg || '')
      hook.value.closeDialog()
      hook.value.refreshList()
    } else {
      ElMessage.warning(res.msg || '')
    }
  })
}

defineExpose({
  init
})
</script>
<style lang='scss' scoped>
</style>

13.批量移交自定义按钮

移动端:

<template>
  <van-dialog v-model:show="show" title="提示" @closed="handleClose" @confirm="handleClose">
    <p style="padding: 16px;">
      本次操作{{ resultData.total }}条数据,执行成功{{ resultData.successTotal }}条,失败{{ resultData.failureTotal }}条;
      <span @click="toDetail" style="color: #165dff;">查看执行结果详情</span>
    </p>
  </van-dialog>
</template>
<script setup lang="ts">
import { ref, inject } from 'vue'
import { showConfirmDialog } from 'vant'

const props = defineProps({
  data: {
    type: Object,
    default: () => ({})
  },
  baseApi: {
    type: Object,
    default: () => ({})
  },
  XToken: {
    type: String,
    default: ''
  }
})

const show = ref(false)
const resultData = ref({})

const baseInfo = ref(null)
const hook = ref(null)
const batchIds = ref([])

const init = (info, callback) => {
  console.log('init', info, callback, props)
  baseInfo.value = info
  hook.value = callback
  batchIds.value = info?.batchIds || info.context?.pageParamType?.batchIds || []
  callback.validateFormWidget().then((item)=>{
    getData(info).then(res => {
      resultData.value = res.data
      if (info.context.pageParamType.batchIds && info.context.pageParamType.batchIds?.length) {
        show.value = true
      } else {
        handleClose()
      }
    })
  })
}

function getData(info) {
  return new Promise((resolve) => {
    let url = `${props.baseApi.VITE_APP_PAAS_BASE_API}/runtime-extender/standardPrice/handover`
    let dataObj = {
        ids: info.context.pageParamType.batchIds,
        id: info.context.id,
        description: info.apiValues.reason_for_handover,
        receiverId: info.apiValues.data_owner_id
      }
    fetch(url, {
      method: 'post',
      headers: {
        'X-Token': props.XToken,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(dataObj)
    }).then((res) => {
      return res.json()
    }).then((res) => {
      const data = res.data || {}
      resolve({
        data
      })
    })
  })
}

function toDetail() {
  sessionStorage.setItem('$_form_params', JSON.stringify({
    businessType: baseInfo.value?.context?.businessType,
    layoutCode: 'C_LYT_fcn15dpyib', // 批量执行结果
    objectCode: resultData.value?.objectCode,
    openType: 'Dialog',
    primaryVal: resultData.value?.resultId
  }))
  hook.value.router.replace({
    path: '/detail',
    query: {
      id: resultData.value?.resultId,
      objectCode: resultData.value?.objectCode,
      layoutCode: 'C_LYT_fcn15dpyib'
    }
  })
}

// close
function handleClose() {
  show.value = false
  hook.value?.router?.back()
  // hook.value?.freshData?.()
}

defineExpose({
  init
})
</script>

pc端:

<template>
   <Result ref="resultRef"></Result>
</template>


<script setup>
  import {ref,inject} from 'vue'
  import { ElMessageBox } from 'element-plus'
  import Result from 'Result'
  const resultRef = ref(null)
  const basicInfo = inject('basicInfo')
  
  const props = defineProps({
    data: {
      type: Object,
      default: () => ({}),
    },
    baseApi: {
        type: Object,
        default: () => ({}),
      },
    XToken: {
        type: String,
        default: ''
      }
  })
  
  const emits = defineEmits(['closeForm'])
  
 //  callback 对象下可能会有 handleSubmit cancelSubmit  validateFormWidget(表单验证) 等方法。
  const init = (info,callback) =>{
    // 先走表单校验
    callback.validateFormWidget().then((item)=>{
      console.log(item)
      getData(info).then(res=>{
        emits('closeForm')
        if (info.context.pageParamType.batchIds && info.context.pageParamType.batchIds?.length) {
          ElMessageBox.confirm(
            `总共${res.data.total}条,成功${res.data.successTotal}条,失败${res.data.failureTotal}条`,
            '提示',
            {
              cancelButtonClass: 'is-text is-has-bg',
              type: 'warning',
              confirmButtonText: '查看结果',
              showCancelButton:false,
              lockScroll:true
            }
          )
            .then(() => {
              const resObj = {
                ...res.data,
              }
              // 打开组件 组件内部有自定义的详情 然后打开详情页面
              resultRef.value.open(resObj)
            })
        }
      })
    })
  }
                   
  defineExpose({
    init
  })
  const getData =(info)=>{
    return new Promise((resolve) => {
      let url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime-extender/priceList/handover`
      let dataObj = {
        ids: info.context.pageParamType.batchIds,
        id: info.context.id,
        description: info.apiValues.reason_for_handover,
        receiverId: info.apiValues.data_owner_id
      }
      fetch(url, {
        method: 'post',
        headers: { 
            'X-Token': props.XToken ,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(dataObj)
      })
        .then((res) => {
          return res.json()
        })
        .then((res) => {
          const data = res.data || {}
          resolve({
            data
          })
        })
    })
  }
 
</script>

14.批量删除自定义按钮

移动端:

<template>
  <van-dialog v-model:show="show" title="提示" @closed="handleClose">
    <p style="padding: 16px; font-size: 14px;">
      本次操作{{ resultData.total }}条数据,执行成功{{ resultData.successTotal }}条,失败{{ resultData.failureTotal }}条;
      <span @click="toDetail" style="color: #165dff;">查看执行结果详情</span>
    </p>
  </van-dialog>
</template>
<script setup lang="ts">
// 客户-批量删除-结果显示-直接
import { ref, inject } from 'vue'
import { showConfirmDialog } from 'vant'

const props = defineProps({
  data: {
    type: Object,
    default: () => ({})
  },
  baseApi: {
    type: Object,
    default: () => ({})
  },
  XToken: {
    type: String,
    default: ''
  }
})

const show = ref(false)
const resultData = ref({})

const baseInfo = ref(null)
const hook = ref(null)
const batchIds = ref([])

//  callback 对象下可能会有 handleSubmit cancelSubmit  validateFormWidget(表单验证) 等方法。
const init = (info, callback) => {
  console.log('init', info, callback, props)
  baseInfo.value = info
  hook.value = callback
  batchIds.value = info?.batchIds || info.context?.pageParamType?.batchIds || []

  showConfirmDialog({
    title: '提示',
    message:
      `删除后无法恢复,请确认是否删除这${batchIds.value.length || 0}条数据?`
  }).then(() => {
    getData(info).then(res => {
      resultData.value = res.data
      hook.value?.freshData?.()
      show.value = true
    })
  }).catch(() => {
    // on cancel
  })
}

function getData(info) {
  return new Promise((resolve) => {
    let url = `${props.baseApi.VITE_APP_PAAS_BASE_API}/runtime-extender/standardPrice/delete`
    let dataObj = {
      ids: batchIds.value
    }
    fetch(url, {
      method: 'post',
      headers: {
        'X-Token': props.XToken,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(dataObj)
    }).then((res) => {
      return res.json()
    }).then((res) => {
      const data = res.data || {}
      resolve({
        data
      })
    })
  })
}

function toDetail() {
  handleClose() 
  sessionStorage.setItem('$_form_params', JSON.stringify({
    businessType: baseInfo.value?.context?.businessType,
    layoutCode: 'C_LYT_fcn15dpyib', // 批量执行结果
    objectCode: resultData.value?.objectCode,
    openType: 'Dialog',
    primaryVal: resultData.value?.resultId
  }))
  hook.value.router.push({
    path: '/detail',
    query: {
      id: resultData.value?.resultId,
      objectCode: resultData.value?.objectCode,
      layoutCode: 'C_LYT_fcn15dpyib'
    }
  })
}

// close
function handleClose() {
  show.value = false
  // hook.value?.freshData?.()
  // hook.value?.router?.back()
}

defineExpose({
  init
})
</script>

pc端:

<template>
   <Result ref="resultRef"></Result>
</template>


<script setup>
  import { ref, inject } from 'vue'
  import { ElMessageBox } from 'element-plus'
  import Result from 'Result'
  const resultRef = ref(null)
  const getTrans = inject('getTranslateText')
  
  const props = defineProps({
    data: {
      type: Object,
      default: () => ({}),
    },
    baseApi: {
        type: Object,
        default: () => ({}),
      },
    XToken: {
        type: String,
        default: ''
      },
    request: {
      type: Object,
        default: () => ({}),
    }
  })
  
 //  callback 对象下可能会有 handleSubmit cancelSubmit  validateFormWidget(表单验证) 等方法。
  const init = (info,callback) =>{
    console.log(info.batchIds, 'info.batchIds')
    ElMessageBox.confirm(
        `${getTrans()('dataPrmissions.selected', '已选择')}<span style="color: var(--el-color-primary)">${info.batchIds.length}</span>条数据,删除后无法恢复。是否确认删除?`,
        getTrans()('Import.prompt', '提示'),
        {
          cancelButtonClass: 'is-text is-has-bg',
          type: 'warning',
          confirmButtonText: getTrans()('tranfer.confirm', '确定'),
          cancelButtonText: getTrans()('tranfer.cancel', '取消'),
          lockScroll:true,
          dangerouslyUseHTMLString: true,
        }
      )
      .then(() => {
        getData(info).then(res=>{
          callback.freshData?.() // 刷新列表
          ElMessageBox.confirm(
            `${getTrans()('messageTip.resultTip1', '本次操作')}${res.data.total}${getTrans()('messageTip.resultTip2', '条数据,执行成功')}${res.data.successTotal}${getTrans()('messageTip.resultTip3', '条,失败')}${res.data.failureTotal}${getTrans()('messageTip.resultTip4', '条;')}`,
            getTrans()('Import.prompt', '提示'),
            {
              cancelButtonClass: 'is-text is-has-bg',
              type: 'warning',
              confirmButtonText: getTrans()('messageTip.lookResult', '查看结果'),
              showCancelButton:false,
              lockScroll:true
            }
          )
            .then(() => {
              const resObj = {
                ...res.data,
              }
              // 打开组件 组件内部有自定义的详情 然后打开详情页面
              resultRef.value.open(resObj)
            })
        })
      })
      .catch(()=>{})
  }                       
  defineExpose({
    init
  })
  const getData =(info)=>{
    return new Promise((resolve, reject) => {
      let url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime-extender/priceList/delete`
      let dataObj = {
        ids: info.batchIds,
      }
      props.request({
        url,
        method: 'post',
        data: dataObj
      }).then((res) => {
        const data = res.data || {}
        resolve({
          data
        })
      })
    })
  }
 
</script>

15.列表列值改变事件

const [listData, index, headerInfo, emits, props, BigNumber, form, callback] = arguments

if (listData.length === 0) {
  return emits('dataValChangeEffectForm', [ { instanceCode:'FID_kfmbqd84o9', value: 0 } ])
}

function getInsCode(apiName) {
  return props.tableColumns.find(v => v.apiName === apiName)?.instanceCode
}

// 回款金额
const amount = getInsCode('collection_details_amount')
let amountTotal = 0

listData.forEach((cur) => { 
  amountTotal = new BigNumber(amountTotal).plus(Number(cur[amount]?.key || 0))
})

emits('dataValChangeEffectForm', [ { instanceCode:'FID_kfmbqd84o9', value: amountTotal.toFixed(2) } ])

16.列表列值校验事件

const [value, callback, ctx, row] = arguments

let maxAmount = row?.rowData?.['FID_l4ss56bopt']?.key

if (maxAmount) {
  if (Number(value) > Number(maxAmount)) {
    return callback(new Error('回款明细金额不能超过最大可回款金额'))
  }
}

callback()
const [value, callback, ctx, table] = arguments

function calculateTotal(row) {
  if (!row?.listData) return 0;
  
  return row.listData.reduce((total, item) => {
    const value = Number(item?.['FID_qi05bd6iff']?.key) || 0;
    return total + value;
  }, 0);
}

// 使用
const total = calculateTotal(table);

if (total > 100) {
  return callback(new Error('总占比不能超过100'))
}

callback()

17.表单字段赋值操作

const [value, form, fieldQueue, bindObj] = arguments

// 根据apiName获取field
function getGeneralFieldByApiName(fieldCode) {
  const field = fieldQueue?.find(f => f.field?.apiName === fieldCode)
  return form?.query(field?.field?.instanceCode)?.take()
}

const fieldOrderTotal = getGeneralFieldByApiName('order_details_total')
const fieldContractTotal = getGeneralFieldByApiName('contract_details_total')
// 回款金额
const fieldTotal = getGeneralFieldByApiName('c_receivable_money')

const total = new bindObj.BigNumber(Number(fieldOrderTotal.value || 0))
  .plus(Number(fieldContractTotal.value || 0))
  .toFixed(2)

fieldTotal.setValue(total)

18.HTML列

<template>
  <div class="no-wrap" :class="{'isblue': obj.value}" @click="openDetail">
     <span v-if="obj.value"> 【{{obj.value}}】{{ contract_number.value }} {{c_number.value}} </span>
     <span v-else>--</span>
  </div>
  
  <LowCodePaasDetail ref="LowCodePaasDetailRef" />
</template>
<script setup>
  import { ref, onMounted, watch, computed } from 'vue'
   import LowCodePaasDetail from 'low-code-paas-detail'
    // import CustomTooltip from 'custom-tooltip'
  const props = defineProps({
    data: {
      type: Object,
      default: () => ({}),
    },
    objectCode: {
      type: String,
      default: '',
    },
    sourceDataId: {
      type: String,
      default: '',
    },
    token: {
      type: String,
      default: '',
    },
    processEnv: {
      type: String,
      default: '',
    }
  })

  const LowCodePaasDetailRef = ref(null)

  
  const obj = computed(() => {
    return props.data?.c_invoice_c_invoice_object
  })

  const openDetail = () => {
    if (obj.value.value == '订单') {
        LowCodePaasDetailRef.value.initData({openType: 'Drawer',objectCode: 'c_order', columnValue: props.data?.c_invoice_c_order_id?.key })
    } else if (obj.value.value == '合同') {
       LowCodePaasDetailRef.value.initData({openType: 'Drawer',objectCode: 'c_contract', columnValue: props.data?.c_invoice_c_contract_id?.key })
    }
  }
  const contract_number = computed(() => {
    
    return props.data?.c_invoice_c_contract_id
  })
  const c_number = computed(() => {
    return props.data?.c_invoice_c_order_id
  })
</script>
<style>
  .isblue {
      color: rgb(22, 93, 255)!important;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .name {
    display: flex;
    align-items: center;
  }
</style>

19.sdk表单组件时间校验

const [value, rule, ctx] = arguments

function getGeneralFieldByApiName(sdk) {
  const { extendsParams: { fieldQueue }, form } = ctx
  return form?.query(sdk)?.take()
}

const compareField = getGeneralFieldByApiName('_expansion_sdk_components_iv5mv1vq3')
if (compareField.value['C_FID_hzbj0h9vn4'] && value['C_FID_nuvqizd6g5']) {
  let curTime = new Date(value['C_FID_nuvqizd6g5']).getTime()
  let compareTime = new Date(compareField.value['C_FID_hzbj0h9vn4']).getTime()
  if (curTime >= compareTime) {
    return '开始有效时间不能早于结束有效时间'
  }
}
const [value, rule, ctx] = arguments

function getGeneralFieldByApiName(sdk) {
  const { extendsParams: { fieldQueue }, form } = ctx
  return form?.query(sdk)?.take()
}

const compareField = getGeneralFieldByApiName('_expansion_sdk_components_uyxp6xd1e')
if (compareField.value['C_FID_nuvqizd6g5'] && value['C_FID_hzbj0h9vn4']) {
  let curTime = new Date(value['C_FID_hzbj0h9vn4']).getTime()
  let compareTime = new Date(compareField.value['C_FID_nuvqizd6g5']).getTime()
  if (curTime <= compareTime) {
    return '结束有效时间不能晚于开始有效时间'
  } else {
    compareField.validate()
  }
}

 20.表单值改变后调用接口给其他字段赋值

const [value, form, fieldQueue, bindObj] = arguments
function getGeneralFieldByApiName(fieldCode){
  const field = fieldQueue?.find(f => f.field?.apiName === fieldCode)
  return form?.query(field?.field?.instanceCode)?.take()
}

getGeneralFieldByApiName('c_contract_id')?.setValue(null)
getGeneralFieldByApiName('c_sign_party')?.setValue(null)
getGeneralFieldByApiName('c_contract_subject_name')?.setValue(null)

const getInfo = (objectCode, id) => {
  return new Promise((resolve) => {
    let url = `${bindObj.baseApi.VITE_PAAS_BASE_URL}/runtime/bizData/${objectCode}/${id}`
    fetch(url, {
      method: 'get',
      headers: { 
        'X-Token': bindObj.XToken,
        'Content-Type': 'application/json'
      }
    })
      .then((res) => {
        return res.json()
      })
      .then((res) => {
        const data = res.data || {}
        resolve({
          data
        })
      })
  })
}

const doThing = async () => {
  if (!value) return
  const userData = await getInfo('c_customer', value)
  // // 开票公司
  // const invoice_company = userData?.data?.C_FID_o0846dvbxo?.value
  // getGeneralFieldByApiName('c_invoice_company')?.setValue(invoice_company)
}
doThing()

21.pc自定义按钮保存并发起审批

<script lang="ts" setup>
import { nextTick, ref, inject } from 'vue'
import { ElMessage } from 'element-plus'

const props = defineProps({
  baseApi: {
    type: Object,
    default: () => ({})
  },
  XToken: {
    type: String,
    default: ''
  },
  request: {
    type: Object,
    default: () => ({}),
  }
})
const basicInfo = inject('basicInfo')
const baseInfo = ref(null)
const hook = ref(null)
const ruleOpenDialog = ref(null)
const rowId = ref('')

const init = (info, callback) => {
  baseInfo.value = info
  hook.value = callback
  console.log('init', info, callback, props)
  callback.validateFormWidget().then(async(res) => {
    if(info.context.id) {
      const checkRes = await checkContract()
      if(!checkRes?.data) return false
    }
    callback?.setAutoCloseAfterSubmit?.(false)
    callback?.handleSubmit().then(res => {
       attchmentSubmit(res.responseData.data, res.valueMap?.FID_jjza83g67d || [])
       hook.value?.submitApprove({
        ...baseInfo.value,
         actionInfo: {},
        objectCode: 'c_contract'
      }).then(res => {
          ElMessage.success('操作成功')
          hook.value.closeDialog()
          hook.value.refreshList()
      }).finally(() => {
         hook.value.submitLoading = false
      })
    })
  }).catch((err) => {
    console.error(err)
  })
}

// 校验合同金额
const checkContract = () => {
  return new Promise((resolve) => {
    let url = `${props.baseApi.VITE_PAAS_BASE_URL}/runtime-extender/contract/checkContract`
    const { context = {} } = baseInfo.value
    let params = {
      id: context.id,
      contractMoney: context?.C_FID_yrkbdw3jrn * 1 // 合同金额
    }
    props.request({
      url,
      method: 'post',
      data: params
    }).then((res) => {
      if (res.code !== '0') {
        return ElMessage.warning(res.msg || '')
      }
      const data = res.data || {}
      resolve({ data })
    })
  })
}

// 提交附件
const attchmentSubmit = (id, list) => {
  const attachmentAuthInfoList = list.map(item => ({
    fileId: item.id,
    settingList: item.settings || []
  }))
  hook.value.submitLoading = true
  props.request({
    url: `${props.baseApi.VITE_PAAS_BASE_URL}/runtime-extender/file/saveAttachmentList`,
    method: 'post',
    data: {
      objectCode: basicInfo()?.objectCode,
      objectId: id || baseInfo.value.context.id,
      isLeadTransform: false,
      transformLeadId: null,
      attachmentAuthInfoList,
    }
  }).then(res => {
    
  }).catch(err => {
    console.log(err)
  })
}


  
defineExpose({
  init
})
</script>
<style lang='scss' scoped>
</style>

22.订单表单页,明细模块的订阅事件

23.报价单转合同

24.报价单转订单

25.合同转订单

26.报价单批量编辑

27.表单渲染完成事件对时间disabled的处理

pc端:

const [form, deferredObj, bindObj, fieldQueue, basicInfo] = arguments
const { primaryVal, pageParamType } = basicInfo

function getGeneralFieldByApiName(fieldCode){
  const field = fieldQueue?.find(f => f.field?.apiName === fieldCode)
  return form?.query(field?.field?.instanceCode)?.take()
}

const setVisibleState = (field, value) => {
  const display = value ? 'visible': 'hidden'
  const { parent } = field
  if (parent.componentType === 'FormGrid.GridColumn') {
    parent.setDisplay(display)
  }
  field.setDisplay(display)
  field.noEffectHidden = true
}

const doThing = () => {
  const lxr = getGeneralFieldByApiName('c_follow_up_contact')
  
  deferredObj[lxr.data?.source?.field.instanceCode].promise.then(() => {
    if (pageParamType.followUpMatterId && pageParamType.parentObjectCode === 'c_contact') {
      lxr.setValue([pageParamType.followUpMatterId])
    }
  })

  const curField = getGeneralFieldByApiName('c_custome_object')
  deferredObj[curField.data?.source?.field.instanceCode].promise.then(() => {
    const value = curField.data?.source.field.value?.value
    if (!value) {
      return
    }
    const curDataSource = curField.dataSource
    const curFieldItem = curDataSource.find(item => item.value === value)
    // 线索
    const xiansuoField = getGeneralFieldByApiName('c_leads_id')
    // 商机
    const shangjiField = getGeneralFieldByApiName('c_business_id')
    // 客户
    const kehuField = getGeneralFieldByApiName('c_customer_id')
    if (curFieldItem.label === '线索') {
      setVisibleState(xiansuoField, true)
    } else if (curFieldItem.label === '客户') {
      setVisibleState(kehuField, true)
    } else if (curFieldItem.label === '商机') {
      setVisibleState(shangjiField, true)
    }
  })

  const next_followup_time = getGeneralFieldByApiName('next_followup_time')
  
  next_followup_time.setComponentProps({
    'disabled-date': (time) => {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      return time.getTime() < today.getTime();
    }
  })

  if (primaryVal) {
    setVisibleState(next_followup_time, false)
    setTimeout(() => {
      setVisibleState(next_followup_time, true)
    }, 200)
  }
  
}
doThing()

移动端:

const [form, deferredObj, bindObj, fieldQueue, mode, basicInfo] = arguments
const { primaryVal, pageParamType } = basicInfo

const fields = Object.values(form.fields).filter(f => f.data)
function getGeneralFieldByApiName(fieldCode) {
  const field = fields?.find(f => f?.data?.source?.field?.apiName === fieldCode)
  return form?.query(field?.data?.source?.field?.instanceCode)?.take?.()
}

const setVisibleState = (field, value) => {
  const display = value ? 'visible': 'hidden'
  const { parent } = field
  if (parent.componentType === 'FormGrid.GridColumn') {
    parent.setDisplay(display)
  }
  field.setDisplay(display)
  field.noEffectHidden = true
}

const doThing = () => {
  const lxr = getGeneralFieldByApiName('c_follow_up_contact')
  
  deferredObj[lxr.data?.source?.field.instanceCode].promise.then(() => {
    if (pageParamType.followUpMatterId && pageParamType.parentObjectCode === 'c_contact') {
      lxr.setValue([pageParamType.followUpMatterId])
    }
  })

  const curField = getGeneralFieldByApiName('c_custome_object')
  deferredObj[curField.data?.source?.field.instanceCode].promise.then(() => {
    const value = curField.data?.source.field.value?.value
    if (!value) {
      return
    }
    const curDataSource = curField.dataSource
    const curFieldItem = curDataSource.find(item => item.value === value)
    // 线索
    const xiansuoField = getGeneralFieldByApiName('c_leads_id')
    // 商机
    const shangjiField = getGeneralFieldByApiName('c_business_id')
    // 客户
    const kehuField = getGeneralFieldByApiName('c_customer_id')
    if (curFieldItem.label === '线索') {
      setVisibleState(xiansuoField, true)
    } else if (curFieldItem.label === '客户') {
      setVisibleState(kehuField, true)
    } else if (curFieldItem.label === '商机') {
      setVisibleState(shangjiField, true)
    }
  })

  const next_followup_time = getGeneralFieldByApiName('next_followup_time')
  // 获取当前日期
  let today = new Date();
  // 计算昨天的日期(月份从0开始计算)
  today = new Date(today.getFullYear(), today.getMonth(), today.getDate());

  next_followup_time.setComponentProps({
    'datePickerProps': {
      ...next_followup_time.componentProps.datePickerProps,
      'min-date': today
    }
  })
}
doThing()

 

posted @ 2025-07-08 13:51  wjs0509  阅读(60)  评论(0)    收藏  举报