123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- <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>
|