| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- <template>
- <!-- 新增拜访计划抽屉 -->
- <el-drawer title="新增拜访计划" :model-value="modelValue" @update:model-value="val => $emit('update:modelValue', val)" size="80%" direction="rtl" destroy-on-close class="plan-drawer">
- <div class="dialog-content-area">
- <!-- 基本信息 -->
- <div class="section-container">
- <div class="section-title">基本信息</div>
- <div class="section-content">
- <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="basic-info-form">
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="拜访人:" prop="visitorId">
- <el-select v-model="form.visitorId" placeholder="请选择" style="width: 100%" clearable filterable @change="handleStaffChange">
- <el-option v-for="item in staffOptions" :key="item.staffId" :label="item.staffName" :value="item.staffId" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="开始时间:" prop="startTime">
- <el-date-picker v-model="form.startTime" type="date" placeholder="请选择" style="width: 100%" value-format="YYYY-MM-DD" />
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="结束时间:" prop="endTime">
- <el-date-picker v-model="form.endTime" type="date" placeholder="请选择" style="width: 100%" value-format="YYYY-MM-DD" />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </div>
- </div>
- <!-- 日程信息 -->
- <div class="section-container">
- <div class="section-header">
- <div class="section-title">日程信息</div>
- <el-button link type="primary" icon="Plus" @click="handleAddSchedule">新建</el-button>
- </div>
- <el-table :data="form.detailList" border class="schedule-table" :header-cell-style="{ background: '#f8fafc', color: '#333', fontWeight: 'normal' }">
- <el-table-column label="拜访日期" align="center" prop="callDate" width="150" sortable>
- <template #default="scope">
- <span>{{ parseTime(scope.row.callDate, '{y}-{m}-{d}') }}</span>
- </template>
- </el-table-column>
- <el-table-column label="客户名称" align="center" prop="customerName" min-width="150" />
- <el-table-column label="关联对象" align="center" prop="objectName" min-width="150" />
- <el-table-column label="关联类型" align="center" prop="relevanceType" width="120">
- <template #default="scope">
- {{ scope.row.relevanceType === 0 ? '客户' : (scope.row.relevanceType === 1 ? '项目商机' : '年度入围') }}
- </template>
- </el-table-column>
- <el-table-column label="紧要程度" align="center" prop="importantLevel" width="100">
- <template #default="scope">
- {{ getUrgencyLabel(scope.row.importantLevel) }}
- </template>
- </el-table-column>
- <el-table-column label="拜访目的" align="center" prop="purposeVisit" min-width="150" show-overflow-tooltip />
- <el-table-column label="操作" align="center" width="120">
- <template #default="scope">
- <el-button link type="primary" @click="handleEditSchedule(scope.$index, scope.row)">编辑</el-button>
- <el-button link type="danger" @click="handleDeleteSchedule(scope.$index)">删除</el-button>
- </template>
- </el-table-column>
- <template #empty>
- <div style="padding: 30px 0; color: #909399;">暂无数据</div>
- </template>
- </el-table>
- </div>
- </div>
- <template #footer>
- <div class="drawer-footer">
- <el-button type="primary" @click="submitForm" :loading="submitting">确认新增</el-button>
- <el-button @click="cancel">取 消</el-button>
- </div>
- </template>
- <!-- 新建日程对话框 -->
- <el-dialog :title="scheduleTitle" v-model="scheduleOpen" width="600px" append-to-body destroy-on-close class="custom-dialog">
- <el-form ref="scheduleFormRef" :model="scheduleForm" :rules="scheduleRules" label-width="100px" label-position="right">
- <el-form-item label="关联类型" prop="relevanceType">
- <el-radio-group v-model="scheduleForm.relevanceType">
- <el-radio :label="0">客户</el-radio>
- <el-radio :label="1">项目商机</el-radio>
- <el-radio :label="2">年度入围</el-radio>
- </el-radio-group>
- </el-form-item>
-
- <el-form-item :label="scheduleTypeLabel" prop="customerName">
- <el-select v-model="scheduleForm.customerName" placeholder="请选择" style="width: 100%" filterable>
- <el-option v-for="item in currentOptions" :key="item.id || item.customerNo" :label="item.projectName || item.customerName" :value="item.projectName || item.customerName" />
- </el-select>
- </el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="拜访日期" prop="callDate">
- <el-date-picker v-model="scheduleForm.callDate" type="date" placeholder="请选择" style="width: 100%" value-format="YYYY-MM-DD" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="重要级别" prop="importantLevel">
- <el-select v-model="scheduleForm.importantLevel" placeholder="请选择" style="width: 100%">
- <el-option v-for="dict in urgencyOptions" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="随访人" prop="followPeopleName">
- <el-select v-model="scheduleForm.followPeopleName" placeholder="请选择" style="width: 100%" multiple clearable filterable collapse-tags>
- <el-option v-for="item in staffOptions" :key="item.staffId" :label="item.staffName" :value="item.staffName" />
- </el-select>
- </el-form-item>
- <el-form-item label="拜访目的" prop="purposeVisit">
- <el-input v-model="scheduleForm.purposeVisit" type="textarea" :rows="4" placeholder="请输入内容" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitSchedule" :loading="scheduleLoading">确 认</el-button>
- <el-button @click="scheduleOpen = false">取 消</el-button>
- </div>
- </template>
- </el-dialog>
- </el-drawer>
- </template>
- <script setup>
- import { ref, reactive, computed, watch, getCurrentInstance, onMounted, toRefs } from 'vue';
- import { addPlan } from "@/api/visit/plan";
- import { listComStaff } from "@/api/system/comStaff/index";
- import { listCustomerInfo } from "@/api/customer/customerInfo/index";
- import { listOpportunity } from "@/api/saleManage/opportunity";
- import { listProjectSelection } from "@/api/saleManage/projectSelection";
- const props = defineProps({
- modelValue: Boolean
- });
- const emit = defineEmits(['update:modelValue', 'success']);
- const proxy = getCurrentInstance().proxy;
- const { importance_level: urgencyOptions } = toRefs(reactive(proxy.useDict("importance_level")));
- const formRef = ref();
- const scheduleFormRef = ref();
- const staffOptions = ref([]);
- const customerOptions = ref([]);
- const opportunityOptions = ref([]);
- const annualOptions = ref([]);
- const scheduleOpen = ref(false);
- const scheduleTitle = ref("新建日程");
- const currentEditIndex = ref(-1);
- const scheduleForm = ref({
- relevanceType: 0,
- customerName: '',
- objectName: '',
- callDate: '',
- importantLevel: undefined,
- followPeopleName: [],
- purposeVisit: '',
- customerNo: ''
- });
- const currentOptions = computed(() => {
- if (scheduleForm.value.relevanceType === 1) return opportunityOptions.value;
- if (scheduleForm.value.relevanceType === 2) return annualOptions.value;
- return customerOptions.value;
- });
- const scheduleTypeLabel = computed(() => {
- if (scheduleForm.value.relevanceType === 1) return '项目商机';
- if (scheduleForm.value.relevanceType === 2) return '年度入围';
- return '客户';
- });
- watch(() => scheduleForm.value.relevanceType, () => {
- scheduleForm.value.customerName = '';
- scheduleForm.value.objectName = '';
- });
- watch(() => scheduleForm.value.customerName, (val) => {
- scheduleForm.value.objectName = val;
- if (val) {
- const item = currentOptions.value.find(i => (i.projectName || i.customerName) === val);
- if (item) {
- scheduleForm.value.customerNo = item.customerNo || item.projectNo || item.id;
- }
- }
- });
- const form = ref({
- visitorId: undefined,
- visitorName: '',
- startTime: '',
- endTime: '',
- detailList: []
- });
- const rules = {
- visitorId: [{ required: true, message: "请选择拜访人", trigger: "change" }],
- startTime: [{ required: true, message: "请选择开始时间", trigger: "change" }],
- endTime: [{ required: true, message: "请选择结束时间", trigger: "change" }]
- };
- const getUrgencyLabel = (val) => {
- const found = urgencyOptions.value.find(item => String(item.value) === String(val));
- return found ? found.label : (val || '--');
- };
- const scheduleRules = {
- customerName: [{ required: true, message: "请选择关联对象", trigger: "change" }],
- callDate: [{ required: true, message: "请选择拜访日期", trigger: "change" }],
- importantLevel: [{ required: true, message: "请选择紧要程度", trigger: "change" }],
- purposeVisit: [{ required: true, message: "请输入拜访目的", trigger: "blur" }]
- };
- /** 选择人员处理 */
- const handleStaffChange = (val) => {
- if (val) {
- const staff = staffOptions.value.find(item => item.staffId === val);
- if (staff) {
- form.value.visitorName = staff.staffName;
- }
- } else {
- form.value.visitorName = '';
- }
- };
- const handleAddSchedule = () => {
- scheduleForm.value = {
- relevanceType: 0,
- customerName: '',
- objectName: '',
- callDate: '',
- importantLevel: undefined,
- followPeopleName: [],
- purposeVisit: '',
- customerNo: ''
- };
- currentEditIndex.value = -1;
- scheduleTitle.value = "新建日程";
- scheduleOpen.value = true;
- };
- const handleEditSchedule = (index, row) => {
- const data = JSON.parse(JSON.stringify(row));
- if (data.followPeopleName && typeof data.followPeopleName === 'string') {
- data.followPeopleName = data.followPeopleName.split(',');
- } else if (!Array.isArray(data.followPeopleName)) {
- data.followPeopleName = [];
- }
- if (data.importantLevel !== undefined && data.importantLevel !== null) {
- data.importantLevel = String(data.importantLevel);
- }
- scheduleForm.value = data;
- currentEditIndex.value = index;
- scheduleTitle.value = "编辑日程";
- scheduleOpen.value = true;
- };
- const handleDeleteSchedule = (index) => {
- form.value.detailList.splice(index, 1);
- };
- const submitSchedule = () => {
- scheduleFormRef.value.validate((valid) => {
- if (valid) {
- scheduleLoading.value = true;
- const detail = {
- ...scheduleForm.value,
- followPeopleName: (scheduleForm.value.followPeopleName && scheduleForm.value.followPeopleName.length > 0) ? scheduleForm.value.followPeopleName.join(',') : ''
- };
- if (currentEditIndex.value === -1) {
- form.value.detailList.push(detail);
- } else {
- form.value.detailList[currentEditIndex.value] = detail;
- }
- scheduleOpen.value = false;
- scheduleLoading.value = false;
- }
- });
- };
- const submitForm = () => {
- formRef.value.validate((valid) => {
- if (valid) {
- submitting.value = true;
- addPlan(form.value).then(response => {
- proxy.$modal.msgSuccess("新增成功");
- emit('update:modelValue', false);
- emit('success');
- resetForm();
- }).finally(() => {
- submitting.value = false;
- });
- }
- });
- };
- const cancel = () => {
- emit('update:modelValue', false);
- resetForm();
- };
- const submitting = ref(false);
- const scheduleLoading = ref(false);
- const resetForm = () => {
- form.value = {
- visitorId: undefined,
- visitorName: '',
- startTime: '',
- endTime: '',
- detailList: []
- };
- };
- onMounted(() => {
- listComStaff({ pageSize: 1000 }).then(response => {
- staffOptions.value = response.rows || response.data || [];
- });
- listCustomerInfo({ pageNum: 1, pageSize: 500, isHighSeas: 'all' }).then(response => {
- customerOptions.value = response.rows || [];
- });
- listOpportunity({ pageSize: 500 }).then(response => {
- opportunityOptions.value = response.rows || [];
- });
- listProjectSelection({ pageSize: 500 }).then(response => {
- annualOptions.value = response.rows || [];
- });
- });
- </script>
- <style scoped lang="scss">
- .plan-drawer {
- :deep(.el-drawer__header) {
- border-bottom: 1px solid #f0f0f0;
- margin-bottom: 0;
- padding: 15px 20px;
- .el-drawer__title { font-size: 15px; color: #333; font-weight: normal; }
- }
- }
- .dialog-content-area { padding: 0 10px; }
- .section-container { margin-bottom: 20px; }
- .section-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- background-color: #f4f6fc;
- padding: 8px 15px;
- margin-bottom: 5px;
- }
- .section-title {
- font-size: 14px;
- color: #409eff;
- font-weight: normal;
- background-color: #f4f6fc;
- padding: 8px 15px;
- display: inline-block;
- width: 100%;
- }
- .basic-info-form :deep(.el-form-item__label),
- .schedule-dialog :deep(.el-form-item__label),
- .schedule-dialog :deep(.el-dialog__title),
- .schedule-dialog :deep(.el-button),
- .plan-drawer :deep(.el-form-item__label),
- .plan-drawer :deep(.el-drawer__title) {
- font-weight: normal !important;
- }
- .section-header .section-title { padding: 0; width: auto; }
- .section-content {
- padding: 15px;
- :deep(.el-form-item) {
- margin-bottom: 0;
- display: flex;
- align-items: center;
- }
- }
- .dialog-footer { text-align: right; padding: 20px 20px; }
- </style>
- <!-- 非作用域样式,用于覆盖 append-to-body 的弹窗 -->
- <style lang="scss">
- .schedule-dialog, .plan-drawer {
- .el-form-item__label,
- .el-dialog__title,
- .el-drawer__title,
- .el-button {
- font-weight: normal !important;
- }
- }
- </style>
|