|
@@ -0,0 +1,445 @@
|
|
|
+<script lang="ts" setup>
|
|
|
+/**
|
|
|
+ * @Name: PlanningSales.vue
|
|
|
+ * @Description: 计划销售额录入
|
|
|
+ * @Author: xinyan
|
|
|
+ */
|
|
|
+
|
|
|
+import {
|
|
|
+ exportPlanSalesData,
|
|
|
+ getPlanSalesData,
|
|
|
+ postCreatePlanSalesData,
|
|
|
+ postUpdatePlanSalesData
|
|
|
+} from '/src/views/reportManage/dataCenter/api';
|
|
|
+import { planColumns } from '/src/views/reportManage/TaskManage/utils/columns';
|
|
|
+import { reactive, ref } from 'vue';
|
|
|
+import { VxeGridInstance } from 'vxe-table';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import Selector from '/src/views/reportManage/dataCenter/normalDisplay/components/Selector/index.vue';
|
|
|
+import { ElMessage, FormInstance, FormRules } from 'element-plus';
|
|
|
+import { dateType } from '/src/views/reportManage/TaskManage/utils/enum';
|
|
|
+import { exportTaskData, getPlanList } from '/src/views/reportManage/TaskManage/api';
|
|
|
+
|
|
|
+// 年份选择器
|
|
|
+const currentYear = ref('');
|
|
|
+// 筛选查询
|
|
|
+const selectorRef = ref(null);
|
|
|
+const taskIds = ref({});
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const dialogVisible = ref(false);
|
|
|
+const formRef = ref<FormInstance>();
|
|
|
+const formData = reactive({
|
|
|
+ january: null,
|
|
|
+ february: null,
|
|
|
+ march: null,
|
|
|
+ april: null,
|
|
|
+ may: null,
|
|
|
+ june: null,
|
|
|
+ july: null,
|
|
|
+ august: null,
|
|
|
+ september: null,
|
|
|
+ october: null,
|
|
|
+ november: null,
|
|
|
+ december: null
|
|
|
+});
|
|
|
+const rules = reactive<FormRules>({
|
|
|
+ january: [{ required: true, message: '请输入1月的计划销售额', trigger: 'blur' }],
|
|
|
+ february: [{ required: true, message: '请输入2月的计划销售额', trigger: 'blur' }],
|
|
|
+ march: [{ required: true, message: '请输入3月的计划销售额', trigger: 'blur' }],
|
|
|
+ april: [{ required: true, message: '请输入4月的计划销售额', trigger: 'blur' }],
|
|
|
+ may: [{ required: true, message: '请输入5月的计划销售额', trigger: 'blur' }],
|
|
|
+ june: [{ required: true, message: '请输入6月的计划销售额', trigger: 'blur' }],
|
|
|
+ july: [{ required: true, message: '请输入7月的计划销售额', trigger: 'blur' }],
|
|
|
+ august: [{ required: true, message: '请输入8月的计划销售额', trigger: 'blur' }],
|
|
|
+ september: [{ required: true, message: '请输入9月的计划销售额', trigger: 'blur' }],
|
|
|
+ october: [{ required: true, message: '请输入10月的计划销售额', trigger: 'blur' }],
|
|
|
+ november: [{ required: true, message: '请输入11月的计划销售额', trigger: 'blur' }],
|
|
|
+ december: [{ required: true, message: '请输入12月的计划销售额', trigger: 'blur' }]
|
|
|
+});
|
|
|
+// 表单项配置,用于动态生成输入框
|
|
|
+const formItems = [
|
|
|
+ { field: 'january', label: '1月' },
|
|
|
+ { field: 'february', label: '2月' },
|
|
|
+ { field: 'march', label: '3月' },
|
|
|
+ { field: 'april', label: '4月' },
|
|
|
+ { field: 'may', label: '5月' },
|
|
|
+ { field: 'june', label: '6月' },
|
|
|
+ { field: 'july', label: '7月' },
|
|
|
+ { field: 'august', label: '8月' },
|
|
|
+ { field: 'september', label: '9月' },
|
|
|
+ { field: 'october', label: '10月' },
|
|
|
+ { field: 'november', label: '11月' },
|
|
|
+ { field: 'december', label: '12月' }
|
|
|
+];
|
|
|
+// 表格
|
|
|
+const currentRow = ref('');
|
|
|
+const months = [
|
|
|
+ '1月', '2月', '3月', '4月', '5月',
|
|
|
+ '6月', '7月', '8月', '9月', '10月',
|
|
|
+ '11月', '12月'
|
|
|
+];
|
|
|
+const originalData = ref([]);
|
|
|
+
|
|
|
+const xGrid = ref<VxeGridInstance>();
|
|
|
+const activeEditRow = ref(null);
|
|
|
+
|
|
|
+const gridOptions = reactive({
|
|
|
+ border: 'inner',
|
|
|
+ // showOverflow: true,
|
|
|
+ height: 750,
|
|
|
+ loading: false,
|
|
|
+ round: true,
|
|
|
+ editConfig: {
|
|
|
+ trigger: 'manual',
|
|
|
+ mode: 'row',
|
|
|
+ showStatus: true,
|
|
|
+ autoClear: false,
|
|
|
+ },
|
|
|
+ columnConfig: {
|
|
|
+ resizable: true,
|
|
|
+ },
|
|
|
+ toolbarConfig: {
|
|
|
+ custom: true,
|
|
|
+ zoom: {
|
|
|
+ iconIn: 'vxe-icon-fullscreen',
|
|
|
+ iconOut: 'vxe-icon-minimize'
|
|
|
+ },
|
|
|
+ slots: {
|
|
|
+ // buttons: 'toolbar_buttons',
|
|
|
+ tools: 'toolbar_tools'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ pagerConfig: {
|
|
|
+ enabled: true,
|
|
|
+ total: 20,
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 20,
|
|
|
+ pageSizes: [10, 20, 30],
|
|
|
+ },
|
|
|
+ columns: planColumns,
|
|
|
+ data: [],
|
|
|
+});
|
|
|
+
|
|
|
+function setDefaultDate() {
|
|
|
+ currentYear.value = dayjs().format('YYYY');
|
|
|
+}
|
|
|
+
|
|
|
+const disabledDate = (time: Date) => {
|
|
|
+ const currentYear = new Date().getFullYear();
|
|
|
+ const selectedYear = time.getFullYear();
|
|
|
+ return selectedYear > currentYear + 1;
|
|
|
+};
|
|
|
+
|
|
|
+async function create(row) {
|
|
|
+ currentRow.value = row;
|
|
|
+ dialogVisible.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+const resetForm = (formEl: FormInstance | undefined) => {
|
|
|
+ if (!formEl) return;
|
|
|
+ formEl.resetFields();
|
|
|
+};
|
|
|
+
|
|
|
+async function handleSave() {
|
|
|
+ const monthMap = {
|
|
|
+ january: 1,
|
|
|
+ february: 2,
|
|
|
+ march: 3,
|
|
|
+ april: 4,
|
|
|
+ may: 5,
|
|
|
+ june: 6,
|
|
|
+ july: 7,
|
|
|
+ august: 8,
|
|
|
+ september: 9,
|
|
|
+ october: 10,
|
|
|
+ november: 11,
|
|
|
+ december: 12
|
|
|
+ };
|
|
|
+ const monthPlanSales = Object.keys(formData).map((month) => ({
|
|
|
+ month: monthMap[month], // 使用映射表获取对应的月份数字
|
|
|
+ planSales: parseFloat(formData[month]) || 0 // 计划销售额转换为数字
|
|
|
+ }));
|
|
|
+
|
|
|
+ const body = {
|
|
|
+ year_date: currentYear.value,
|
|
|
+ task: currentRow.value.task || 0,
|
|
|
+ month_plan_sales: monthPlanSales,
|
|
|
+ };
|
|
|
+ try {
|
|
|
+ await postCreatePlanSalesData(body);
|
|
|
+ dialogVisible.value = false;
|
|
|
+ await getList();
|
|
|
+ } catch (error) {
|
|
|
+ console.error('提交数据时出错:', error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const submitForm = async (formEl: FormInstance | undefined) => {
|
|
|
+ if (!formEl) return;
|
|
|
+ await formEl.validate((valid, fields) => {
|
|
|
+ if (valid) {
|
|
|
+ handleSave();
|
|
|
+ formEl.resetFields();
|
|
|
+ ElMessage.success('创建成功');
|
|
|
+ } else {
|
|
|
+ ElMessage.error('添加失败,请检查填写数据');
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const gridEvents = {
|
|
|
+ pageChange({ currentPage, pageSize }) {
|
|
|
+ if (gridOptions.pagerConfig) {
|
|
|
+ gridOptions.pagerConfig.currentPage = currentPage;
|
|
|
+ gridOptions.pagerConfig.pageSize = pageSize;
|
|
|
+ }
|
|
|
+ getList();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const isMonthIdExist = (row) => {
|
|
|
+ return months.some(month => row[month] && row[month].id);
|
|
|
+};
|
|
|
+
|
|
|
+const hasActiveEditRow = (row) => {
|
|
|
+ const $grid = xGrid.value;
|
|
|
+ if ($grid) {
|
|
|
+ return $grid.isEditByRow(row);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+};
|
|
|
+
|
|
|
+const clearRowEvent = (row) => {
|
|
|
+ activeEditRow.value = false;
|
|
|
+ const $grid = xGrid.value;
|
|
|
+ if ($grid) {
|
|
|
+ $grid.clearEdit();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 进入编辑模式
|
|
|
+const handelEditRow = (row) => {
|
|
|
+ activeEditRow.value = true;
|
|
|
+ const $grid = xGrid.value;
|
|
|
+ if ($grid) {
|
|
|
+ for (const month in row) {
|
|
|
+ if (row[month] && row[month].id) {
|
|
|
+ originalData.value = JSON.parse(JSON.stringify(row[month]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $grid.setEditRow(row);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+async function saveRow(row) {
|
|
|
+ const $grid = xGrid.value;
|
|
|
+ if ($grid) {
|
|
|
+ const updatedData = [];
|
|
|
+ for (const month in row) {
|
|
|
+ if (row[month] && row[month].id) {
|
|
|
+ const planSales = parseFloat(row[month].planSales);
|
|
|
+
|
|
|
+ if (!isNaN(planSales)) {
|
|
|
+ updatedData.push({
|
|
|
+ id: row[month].id,
|
|
|
+ planSales: planSales
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ await postUpdatePlanSalesData(updatedData);
|
|
|
+ activeEditRow.value = false;
|
|
|
+ await $grid.clearEdit();
|
|
|
+ await getList();
|
|
|
+ ElMessage.success('更新成功');
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('更新失败,请检查填写数据');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+async function getList() {
|
|
|
+ try {
|
|
|
+ gridOptions.loading = true;
|
|
|
+ const response = await getPlanList({
|
|
|
+ page: gridOptions.pagerConfig.currentPage,
|
|
|
+ limit: gridOptions.pagerConfig.pageSize,
|
|
|
+ year_date: currentYear.value,
|
|
|
+ task_ids: taskIds.value,
|
|
|
+ });
|
|
|
+ gridOptions.data = response.data;
|
|
|
+ gridOptions.pagerConfig.total = response.total;
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error fetching task data:', error);
|
|
|
+ } finally {
|
|
|
+ gridOptions.loading = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function updateDataChange(newId) {
|
|
|
+ if (selectorRef.value) {
|
|
|
+ if (gridOptions.pagerConfig) {
|
|
|
+ gridOptions.pagerConfig.currentPage = 1;
|
|
|
+ }
|
|
|
+ taskIds.value = newId.value;
|
|
|
+ getList();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function handleExport() {
|
|
|
+ try {
|
|
|
+ gridOptions.loading = true;
|
|
|
+ const response = await exportPlanSalesData({
|
|
|
+ year_date: currentYear.value,
|
|
|
+ task_ids: taskIds.value,
|
|
|
+ });
|
|
|
+ const url = window.URL.createObjectURL(new Blob([response.data]));
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = url;
|
|
|
+ link.setAttribute('download', '计划销售额数据.xlsx');
|
|
|
+ document.body.appendChild(link);
|
|
|
+ link.click();
|
|
|
+ gridOptions.loading = false;
|
|
|
+ ElMessage.success('导出数据成功');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('导出数据失败:', error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+watch(currentYear, (newVal, oldVal) => {
|
|
|
+ if (newVal !== oldVal) {
|
|
|
+ currentYear.value = dayjs(newVal).format('YYYY');
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const cellStyle = () => {
|
|
|
+ return {
|
|
|
+ fontSize: '13px',
|
|
|
+ fontWeight: '500',
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+const headerCellStyle = () => {
|
|
|
+ return {
|
|
|
+ fontSize: '13px',
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ setDefaultDate();
|
|
|
+ // getList();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <el-card class=" my-3 mx-8 p-0">
|
|
|
+ <div class="flex gap-1.5 justify-between mx-2 items-center">
|
|
|
+ <Selector ref="selectorRef" @update:updateData="updateDataChange" />
|
|
|
+ <div class="demo-date-picker">
|
|
|
+ <div class="block">
|
|
|
+ <span class="demonstration">年份:</span>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="currentYear"
|
|
|
+ :disabled-date="disabledDate"
|
|
|
+ placeholder="Pick a year"
|
|
|
+ style="width: 150px"
|
|
|
+ type="year"
|
|
|
+ @change="getList"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ <el-card class="mx-8">
|
|
|
+ <vxe-grid ref="xGrid" :cell-style="cellStyle" :header-cell-style="headerCellStyle" v-bind="gridOptions"
|
|
|
+ v-on="gridEvents">
|
|
|
+ <template #toolbar_tools>
|
|
|
+ <div class="pr-2.5">
|
|
|
+ <el-tooltip content="下载表格" placement="top">
|
|
|
+ <vxe-button circle icon="vxe-icon-download" @click="handleExport"></vxe-button>
|
|
|
+ </el-tooltip>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #operate="{ row }">
|
|
|
+ <template v-if="hasActiveEditRow(row)">
|
|
|
+ <el-button link size="small" @click="clearRowEvent(row)">取消</el-button>
|
|
|
+ <el-button link size="small" type="warning" @click="saveRow(row)">保存</el-button>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-button :disabled="!isMonthIdExist(row)||activeEditRow" link size="small" type="success"
|
|
|
+ @click="handelEditRow(row)">
|
|
|
+ 修改
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ <el-button v-if="!hasActiveEditRow(row)" :disabled="isMonthIdExist(row)||activeEditRow" link size="small"
|
|
|
+ type="primary"
|
|
|
+ @click="create(row)">创建
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ <template v-for="col in planColumns" #[`${col.slots?.edit}`]="{ row }">
|
|
|
+ <el-input v-model="row[col.field].planSales" />
|
|
|
+ </template>
|
|
|
+ </vxe-grid>
|
|
|
+ </el-card>
|
|
|
+ <el-dialog v-model="dialogVisible" :before-close="handleClose" style="border-radius: 10px;"
|
|
|
+ title="创建计划销售额" width="600">
|
|
|
+ <template #title>
|
|
|
+ <span class="text-xl">创建计划销售额</span>
|
|
|
+ <div class="mt-2" style="display: flex; align-items: center;color: darkgray">
|
|
|
+ <div style="margin-right: 8px;">
|
|
|
+ 平台编号:
|
|
|
+ <span class="italic pl-1 pr-2">{{ currentRow.platformNumber }}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ 平台名称:
|
|
|
+ <span class="italic pl-1">{{ currentRow.platformName }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="rules"
|
|
|
+ label-position="top"
|
|
|
+ label-width="auto"
|
|
|
+ status-icon
|
|
|
+ >
|
|
|
+ <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 5px">
|
|
|
+ <el-form-item v-for="item in formItems" :label="`${item.label}计划销售额`" :prop="item.field">
|
|
|
+ <el-input v-model="formData[item.field]"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="dayFormVisible = false ;resetForm(formRef)">取消</el-button>
|
|
|
+ <el-button type="primary" @click="submitForm(formRef)">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.demo-date-picker {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row-reverse;
|
|
|
+}
|
|
|
+
|
|
|
+.block {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex-wrap: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ /* width: 100%; */
|
|
|
+}
|
|
|
+
|
|
|
+.demo-date-picker .demonstration {
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
+ font-size: 14px;
|
|
|
+ white-space: nowrap;
|
|
|
+ margin-right: 2px;
|
|
|
+}
|
|
|
+</style>
|