458 lines
17 KiB
Vue
458 lines
17 KiB
Vue
|
|
<template>
|
||
|
|
<BasicDrawer v-bind="$attrs" @register="registerDrawer" width="800px" showFooter
|
||
|
|
:cancelText="t('common.cancelText','取消')"
|
||
|
|
:okText="t('common.okText','确定')"
|
||
|
|
@ok="handleSubmit" :closeFunc="onClose">
|
||
|
|
<template #title>
|
||
|
|
<a-space :size="10">
|
||
|
|
<div class="text-16px font-medium">{{ title }}</div>
|
||
|
|
<a-space-compact size="small" block v-if="dataForm.id">
|
||
|
|
<a-tooltip :title="t('common.prevRecord')">
|
||
|
|
<a-button size="small" :disabled="getPrevDisabled" @click="handlePrev">
|
||
|
|
<i class="icon-ym icon-ym-caret-left text-10px"></i>
|
||
|
|
</a-button>
|
||
|
|
</a-tooltip>
|
||
|
|
<a-tooltip :title="t('common.nextRecord')">
|
||
|
|
<a-button size="small" :disabled="getNextDisabled" @click="handleNext">
|
||
|
|
<i class="icon-ym icon-ym-caret-right text-10px"></i>
|
||
|
|
</a-button>
|
||
|
|
</a-tooltip>
|
||
|
|
</a-space-compact>
|
||
|
|
</a-space>
|
||
|
|
</template>
|
||
|
|
<template #insertFooter>
|
||
|
|
<div class="float-left mt-5px">
|
||
|
|
<yunzhupaasCheckboxSingle v-model:value="submitType" :label="continueText" />
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
<a-row class="p-10px dynamic-form ">
|
||
|
|
<!-- 表单 -->
|
||
|
|
<a-form :colon="false" size="middle" layout= "horizontal"
|
||
|
|
labelAlign= "right"
|
||
|
|
:labelCol="{ style: { width: '100px' } }" :model="dataForm" :rules="dataRule" ref="formRef" >
|
||
|
|
<a-row :gutter="15">
|
||
|
|
<!-- 具体表单 -->
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('lead_name')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="lead_name" >
|
||
|
|
<template #label>线索名称
|
||
|
|
</template> <YunzhupaasInput v-model:value="dataForm.lead_name" @change="changeData('lead_name',-1)"
|
||
|
|
placeholder="请输入线索名称" :maxlength="50" :allowClear='true' :style='{"width":"100%"}' :maskConfig = "maskConfig.lead_name" :showCount = "false" >
|
||
|
|
</YunzhupaasInput>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('mobile')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="mobile" >
|
||
|
|
<template #label>手机号
|
||
|
|
</template> <YunzhupaasInput v-model:value="dataForm.mobile" @change="changeData('mobile',-1)"
|
||
|
|
placeholder="请输入手机号" :maxlength="11" :allowClear='true' :style='{"width":"100%"}' :maskConfig = "maskConfig.mobile" :showCount = "false" >
|
||
|
|
</YunzhupaasInput>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('email')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="email" >
|
||
|
|
<template #label>邮箱
|
||
|
|
</template> <YunzhupaasInput v-model:value="dataForm.email" @change="changeData('email',-1)"
|
||
|
|
placeholder="请输入邮箱" :maxlength="50" :allowClear='true' :style='{"width":"100%"}' :maskConfig = "maskConfig.email" :showCount = "false" >
|
||
|
|
</YunzhupaasInput>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('lead_status')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="lead_status" >
|
||
|
|
<template #label>状态
|
||
|
|
</template> <YunzhupaasSelect v-model:value="dataForm.lead_status" @change="changeData('lead_status',-1)"
|
||
|
|
placeholder="请选择状态" :templateJson="state.interfaceRes.lead_status" :allowClear='true' :style='{"width":"100%"}' :showSearch='false' :options="optionsObj.lead_statusOptions" :fieldNames="optionsObj.lead_statusProps"
|
||
|
|
>
|
||
|
|
</YunzhupaasSelect>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('sales_id')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="sales_id" >
|
||
|
|
<template #label>销售人员
|
||
|
|
</template> <YunzhupaasUsersSelect v-model:value="dataForm.sales_id" @change="changeData('sales_id',-1)"
|
||
|
|
placeholder="请选择销售人员" :allowClear='true' :style='{"width":"100%"}' selectType="all" >
|
||
|
|
</YunzhupaasUsersSelect>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('customer_source')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="customer_source" >
|
||
|
|
<template #label>来源
|
||
|
|
</template> <YunzhupaasSelect v-model:value="dataForm.customer_source" @change="changeData('customer_source',-1)"
|
||
|
|
placeholder="请选择来源" :templateJson="state.interfaceRes.customer_source" :allowClear='true' :style='{"width":"100%"}' :showSearch='false' :options="optionsObj.customer_sourceOptions" :fieldNames="optionsObj.customer_sourceProps"
|
||
|
|
>
|
||
|
|
</YunzhupaasSelect>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<a-col :span="24" class="ant-col-item" v-if="hasFormP('remark')"
|
||
|
|
>
|
||
|
|
<a-form-item
|
||
|
|
name="remark" >
|
||
|
|
<template #label>备注
|
||
|
|
</template> <YunzhupaasTextarea v-model:value="dataForm.remark" @change="changeData('remark',-1)"
|
||
|
|
placeholder="请输入备注" :maxlength="200" :allowClear='true' :style='{"width":"100%"}' :autoSize='{"minRows":4,"maxRows":4}' :showCount = "false" >
|
||
|
|
</YunzhupaasTextarea>
|
||
|
|
</a-form-item>
|
||
|
|
</a-col>
|
||
|
|
<!-- 表单结束 -->
|
||
|
|
</a-row>
|
||
|
|
</a-form>
|
||
|
|
</a-row>
|
||
|
|
</BasicDrawer>
|
||
|
|
</template>
|
||
|
|
<script lang="ts" setup>
|
||
|
|
import { create, update, getInfo } from './helper/api';
|
||
|
|
import { reactive, toRefs, nextTick, ref, unref, computed,toRaw, inject } from 'vue';
|
||
|
|
import { BasicDrawer, useDrawer } from '@/components/Drawer';
|
||
|
|
import { yunzhupaasRelationForm } from '@/components/yunzhupaas';
|
||
|
|
import { useMessage } from '@/hooks/web/useMessage';
|
||
|
|
import { useI18n } from '@/hooks/web/useI18n';
|
||
|
|
import { useUserStore } from '@/store/modules/user';
|
||
|
|
import type { FormInstance } from 'ant-design-vue';
|
||
|
|
import { thousandsFormat , getDateTimeUnit, getTimeUnit} from '@/utils/yunzhupaas';
|
||
|
|
import { getDictionaryDataSelector } from '@/api/systemData/dictionary';
|
||
|
|
import { getDataInterfaceRes } from '@/api/systemData/dataInterface';
|
||
|
|
import dayjs from 'dayjs';
|
||
|
|
// 表单权限
|
||
|
|
import { usePermission } from '@/hooks/web/usePermission';
|
||
|
|
import { cloneDeep } from 'lodash-es';
|
||
|
|
import { buildUUID } from '@/utils/uuid';
|
||
|
|
import { CaretRightOutlined } from '@ant-design/icons-vue';
|
||
|
|
|
||
|
|
|
||
|
|
interface State {
|
||
|
|
dataForm: any;
|
||
|
|
tableRows: any;
|
||
|
|
dataRule: any;
|
||
|
|
optionsObj: any;
|
||
|
|
childIndex: any;
|
||
|
|
isEdit: any;
|
||
|
|
interfaceRes: any;
|
||
|
|
//可选范围默认值
|
||
|
|
ableAll: any;
|
||
|
|
//掩码配置
|
||
|
|
maskConfig:any;
|
||
|
|
//定位属性
|
||
|
|
locationScope:any;
|
||
|
|
extraOptions: any;
|
||
|
|
title: string;
|
||
|
|
continueText: string; allList: any[];
|
||
|
|
currIndex: number;
|
||
|
|
isContinue: boolean;
|
||
|
|
submitType: number;
|
||
|
|
showContinueBtn: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
const emit = defineEmits(['reload']);
|
||
|
|
const getLeftTreeActiveInfo: (() => any) | null = inject('getLeftTreeActiveInfo', null);
|
||
|
|
const userStore = useUserStore();
|
||
|
|
const userInfo = userStore.getUserInfo;
|
||
|
|
const { createMessage, createConfirm } = useMessage();
|
||
|
|
const { t } = useI18n();
|
||
|
|
const [registerDrawer, { openDrawer, setDrawerProps }] = useDrawer();
|
||
|
|
const formRef = ref<FormInstance>();
|
||
|
|
const state = reactive<State>({
|
||
|
|
dataForm: {
|
||
|
|
lead_name:undefined,
|
||
|
|
mobile:undefined,
|
||
|
|
email:undefined,
|
||
|
|
lead_status:'Unassigned',
|
||
|
|
sales_id:undefined,
|
||
|
|
customer_source:'',
|
||
|
|
remark:undefined,
|
||
|
|
version: 0,
|
||
|
|
},
|
||
|
|
|
||
|
|
tableRows:{
|
||
|
|
},
|
||
|
|
|
||
|
|
dataRule: {
|
||
|
|
lead_name: [
|
||
|
|
{
|
||
|
|
required: true,
|
||
|
|
message: t('sys.validate.textRequiredSuffix','不能为空'),
|
||
|
|
trigger: 'blur'
|
||
|
|
},
|
||
|
|
],
|
||
|
|
mobile: [
|
||
|
|
{
|
||
|
|
required: true,
|
||
|
|
message: t('sys.validate.textRequiredSuffix','不能为空'),
|
||
|
|
trigger: 'blur'
|
||
|
|
},
|
||
|
|
{
|
||
|
|
pattern: /^1[3456789]\d{9}$/,
|
||
|
|
message: t('sys.validate.mobilePhone','请输入正确的手机号码'),
|
||
|
|
trigger: 'blur'
|
||
|
|
},
|
||
|
|
],
|
||
|
|
email: [
|
||
|
|
{
|
||
|
|
pattern: /^[a-z0-9]+([._\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/,
|
||
|
|
message: t('sys.validate.email','请输入正确的邮箱'),
|
||
|
|
trigger: 'blur'
|
||
|
|
},
|
||
|
|
],
|
||
|
|
lead_status: [
|
||
|
|
{
|
||
|
|
required: true,
|
||
|
|
message: t('sys.validate.arrayRequiredPrefix ','请至少选择一个'),
|
||
|
|
trigger: 'change'
|
||
|
|
},
|
||
|
|
],
|
||
|
|
sales_id: [
|
||
|
|
{
|
||
|
|
required: true,
|
||
|
|
message: t('sys.validate.arrayRequiredPrefix ','请至少选择一个'),
|
||
|
|
trigger: 'change'
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
|
||
|
|
optionsObj:{
|
||
|
|
lead_statusOptions:[{"fullName":"待分配","id":"Unassigned"},{"fullName":"跟进中","id":"InProgress"},{"fullName":"已转换","id":"Converted"},{"fullName":"无效","id":"Invalid"}],
|
||
|
|
lead_statusProps:{"label":"fullName","value":"id" },
|
||
|
|
customer_sourceOptions:[],
|
||
|
|
customer_sourceProps:{"label":"fullName","value":"enCode" },
|
||
|
|
},
|
||
|
|
|
||
|
|
childIndex: -1,
|
||
|
|
isEdit: false,
|
||
|
|
interfaceRes: {"lead_status":[],"mobile":[],"lead_name":[],"customer_source":[],"remark":[],"sales_id":[],"email":[]},
|
||
|
|
//可选范围默认值
|
||
|
|
ableAll:{
|
||
|
|
},
|
||
|
|
|
||
|
|
//掩码配置
|
||
|
|
maskConfig:{
|
||
|
|
lead_name: {"prefixType":1,"useUnrealMask":false,"maskType":1,"unrealMaskLength":1,"prefixLimit":0,"suffixLimit":0,"filler":"*","prefixSpecifyChar":"","suffixType":1,"ignoreChar":"","suffixSpecifyChar":""} ,
|
||
|
|
mobile: {"prefixType":1,"useUnrealMask":false,"maskType":1,"unrealMaskLength":1,"prefixLimit":0,"suffixLimit":0,"filler":"*","prefixSpecifyChar":"","suffixType":1,"ignoreChar":"","suffixSpecifyChar":""} ,
|
||
|
|
email: {"prefixType":1,"useUnrealMask":false,"maskType":1,"unrealMaskLength":1,"prefixLimit":0,"suffixLimit":0,"filler":"*","prefixSpecifyChar":"","suffixType":1,"ignoreChar":"","suffixSpecifyChar":""} ,
|
||
|
|
},
|
||
|
|
|
||
|
|
//定位属性
|
||
|
|
locationScope:{
|
||
|
|
},
|
||
|
|
|
||
|
|
extraOptions:{
|
||
|
|
},
|
||
|
|
|
||
|
|
title: "",
|
||
|
|
continueText: "", allList: [],
|
||
|
|
currIndex: 0,
|
||
|
|
isContinue: false,
|
||
|
|
submitType: 0,
|
||
|
|
showContinueBtn: true ,
|
||
|
|
});
|
||
|
|
const { title, continueText, showContinueBtn, dataRule, dataForm, optionsObj, ableAll, maskConfig,submitType } = toRefs(state);
|
||
|
|
|
||
|
|
const getPrevDisabled = computed(() => state.currIndex === 0);
|
||
|
|
const getNextDisabled = computed(() => state.currIndex === state.allList.length - 1);
|
||
|
|
// 表单权限
|
||
|
|
const { hasFormP } = usePermission();
|
||
|
|
|
||
|
|
defineExpose({ init });
|
||
|
|
|
||
|
|
function init(data) {
|
||
|
|
state.submitType = 0;
|
||
|
|
state.isContinue = false;
|
||
|
|
state.title = !data.id ? t('common.add2Text','新增') : t('common.editText','编辑');
|
||
|
|
state.continueText = !data.id ? t('common.continueAndAddText','确定并新增') : t('common.continueText','确定并继续'); setFormProps({ continueLoading: false });
|
||
|
|
state.dataForm.id = data.id;
|
||
|
|
openDrawer();
|
||
|
|
state.allList = data.allList;
|
||
|
|
state.currIndex = state.allList.length && data.id ? state.allList.findIndex((item) => item.id === data.id) : 0;
|
||
|
|
nextTick(() => {
|
||
|
|
getForm().resetFields();
|
||
|
|
setTimeout(initData, 0);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
function initData() {
|
||
|
|
changeLoading(true);
|
||
|
|
if (state.dataForm.id) {
|
||
|
|
getData(state.dataForm.id);
|
||
|
|
} else {
|
||
|
|
//初始化options
|
||
|
|
getcustomer_sourceOptions();
|
||
|
|
|
||
|
|
// 设置默认值
|
||
|
|
state.dataForm={
|
||
|
|
lead_name:undefined,
|
||
|
|
mobile:undefined,
|
||
|
|
email:undefined,
|
||
|
|
lead_status:'Unassigned',
|
||
|
|
sales_id:undefined,
|
||
|
|
customer_source:'',
|
||
|
|
remark:undefined,
|
||
|
|
version: 0,
|
||
|
|
};
|
||
|
|
if (getLeftTreeActiveInfo) state.dataForm = {...state.dataForm, ...(getLeftTreeActiveInfo() || {}) };
|
||
|
|
state.childIndex = -1;
|
||
|
|
changeLoading(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function getForm() {
|
||
|
|
const form = unref(formRef);
|
||
|
|
if (!form) {
|
||
|
|
throw new Error('form is null!');
|
||
|
|
}
|
||
|
|
return form;
|
||
|
|
}
|
||
|
|
function getData(id) {
|
||
|
|
getInfo(id).then((res) => {
|
||
|
|
state.dataForm = res.data || {};
|
||
|
|
getcustomer_sourceOptions();
|
||
|
|
|
||
|
|
state.childIndex = -1;
|
||
|
|
changeLoading(false);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
async function handleSubmit(type) {
|
||
|
|
try {
|
||
|
|
const values = await getForm()?.validate();
|
||
|
|
if (!values) return;
|
||
|
|
|
||
|
|
|
||
|
|
setFormProps({ confirmLoading: true });
|
||
|
|
const formMethod = state.dataForm.id ? update : create;
|
||
|
|
formMethod(state.dataForm)
|
||
|
|
.then((res) => {
|
||
|
|
createMessage.success(res.msg);
|
||
|
|
setFormProps({ confirmLoading: false });
|
||
|
|
if (state.submitType == 1) {
|
||
|
|
initData();
|
||
|
|
state.isContinue = true;
|
||
|
|
} else {
|
||
|
|
setFormProps({ open: false });
|
||
|
|
emit('reload');
|
||
|
|
}
|
||
|
|
})
|
||
|
|
.catch(() => {
|
||
|
|
setFormProps({ confirmLoading: false });
|
||
|
|
});
|
||
|
|
} catch (_) {}
|
||
|
|
}
|
||
|
|
function handlePrev() {
|
||
|
|
state.currIndex--;
|
||
|
|
handleGetNewInfo();
|
||
|
|
}
|
||
|
|
function handleNext() {
|
||
|
|
state.currIndex++;
|
||
|
|
handleGetNewInfo();
|
||
|
|
}
|
||
|
|
function handleGetNewInfo() {
|
||
|
|
changeLoading(true);
|
||
|
|
getForm().resetFields();
|
||
|
|
const id = state.allList[state.currIndex].id;
|
||
|
|
getData(id);
|
||
|
|
}
|
||
|
|
function setFormProps(data) {
|
||
|
|
setDrawerProps(data);
|
||
|
|
}
|
||
|
|
function changeLoading(loading) {
|
||
|
|
setDrawerProps({ loading });
|
||
|
|
}
|
||
|
|
async function onClose() {
|
||
|
|
if (state.isContinue) emit('reload');
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
function changeData(model, index) {
|
||
|
|
state.isEdit = false
|
||
|
|
state.childIndex = index
|
||
|
|
for (let key in state.interfaceRes) {
|
||
|
|
if (key != model) {
|
||
|
|
let faceReList = state.interfaceRes[key]
|
||
|
|
for (let i = 0; i < faceReList.length; i++) {
|
||
|
|
let relationField = faceReList[i].relationField;
|
||
|
|
if(relationField){
|
||
|
|
let modelAll = relationField.split('-');
|
||
|
|
let faceMode = '';
|
||
|
|
let faceMode2 = modelAll.length == 2?modelAll[0].substring(0, modelAll[0].length-4) +modelAll[1]:""
|
||
|
|
for (let i = 0; i < modelAll.length; i++) {
|
||
|
|
faceMode += modelAll[i];
|
||
|
|
}
|
||
|
|
if (faceMode == model || faceMode2 == model ) {
|
||
|
|
let options = 'get' + key + 'Options';
|
||
|
|
eval(options)(true);
|
||
|
|
changeData(key, index)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
function changeDataFormData(type, data, model,index,defaultValue) {
|
||
|
|
if(!state.isEdit) {
|
||
|
|
if (type == 2) {
|
||
|
|
for (let i = 0; i < state.dataForm[data].length; i++) {
|
||
|
|
if (index == -1) {
|
||
|
|
state.dataForm[data][i][model] = defaultValue
|
||
|
|
} else if (index == i) {
|
||
|
|
state.dataForm[data][i][model] = defaultValue
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
state.dataForm[data] = defaultValue
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//数据选项--数据字典初始化方法
|
||
|
|
function getcustomer_sourceOptions() {
|
||
|
|
getDictionaryDataSelector('797256993944371205').then(res => {
|
||
|
|
state.optionsObj.customer_sourceOptions = res.data.list
|
||
|
|
})
|
||
|
|
}
|
||
|
|
function getRelationDate(timeRule, timeType, timeTarget, timeValueData, dataValue) {
|
||
|
|
let timeDataValue: any = null;
|
||
|
|
let timeValue = Number(timeValueData);
|
||
|
|
if (timeRule) {
|
||
|
|
if (timeType == 1) {
|
||
|
|
timeDataValue = timeValue;
|
||
|
|
} else if (timeType == 2) {
|
||
|
|
timeDataValue = dataValue;
|
||
|
|
} else if (timeType == 3) {
|
||
|
|
timeDataValue = new Date().getTime();
|
||
|
|
} else if (timeType == 4 || timeType == 5) {
|
||
|
|
const type = getTimeUnit(timeTarget);
|
||
|
|
const method = timeType == 4 ? 'subtract' : 'add';
|
||
|
|
timeDataValue = dayjs()[method](timeValue, type).valueOf();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return timeDataValue;
|
||
|
|
}
|
||
|
|
function getRelationTime(timeRule, timeType, timeTarget, timeValue, formatType, dataValue) {
|
||
|
|
let format = formatType == 'HH:mm' ? 'HH:mm:00' : formatType;
|
||
|
|
let timeDataValue: any = null;
|
||
|
|
if (timeRule) {
|
||
|
|
if (timeType == 1) {
|
||
|
|
timeDataValue = timeValue || '00:00:00';
|
||
|
|
if (timeDataValue.split(':').length == 3) {
|
||
|
|
timeDataValue = timeDataValue;
|
||
|
|
} else {
|
||
|
|
timeDataValue = timeDataValue + ':00';
|
||
|
|
}
|
||
|
|
} else if (timeType == 2) {
|
||
|
|
timeDataValue = dataValue;
|
||
|
|
} else if (timeType == 3) {
|
||
|
|
timeDataValue = dayjs().format(format);
|
||
|
|
} else if (timeType == 4 || timeType == 5) {
|
||
|
|
const type = getTimeUnit(timeTarget + 3);
|
||
|
|
const method = timeType == 4 ? 'subtract' : 'add';
|
||
|
|
timeDataValue = dayjs()[method](timeValue, type).format(format);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return timeDataValue;
|
||
|
|
}
|
||
|
|
</script>
|