Просмотр исходного кода

完成广告活动-广告结构页面开发;修改mCard组件和TextSelector的@change暴露的newVal和oldVal顺序

WanGxC 1 год назад
Родитель
Сommit
c68843b3f7

+ 42 - 0
src/views/adManage/sb/adPlacement/api.ts

@@ -0,0 +1,42 @@
+import { request } from '/@/utils/service';
+import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
+import XEUtils from 'xe-utils';
+
+export const apiPrefix = '/api/ad_manage/spkeywords/';
+export function GetList(query: UserPageQuery) {
+    return request({
+        url: apiPrefix,
+        method: 'get',
+        params: query,
+    })
+}
+export function GetObj(id: InfoReq) {
+    return request({
+        url: apiPrefix + id + "/",
+        method: 'get',
+    });
+}
+
+export function AddObj(obj: AddReq) {
+    return request({
+        url: apiPrefix,
+        method: 'post',
+        data: obj,
+    });
+}
+
+export function UpdateObj(obj: EditReq) {
+    return request({
+        url: apiPrefix + obj.id + '/',
+        method: 'put',
+        data: obj,
+    });
+}
+
+export function DelObj(id: DelReq) {
+    return request({
+        url: apiPrefix + id + '/',
+        method: 'delete',
+        data: { id },
+    });
+}

+ 114 - 0
src/views/adManage/sb/adPlacement/crud.tsx

@@ -0,0 +1,114 @@
+import * as api from './api'
+import { dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'
+import { inject, nextTick, ref } from 'vue'
+import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn.js'
+
+
+export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
+	const pageRequest = async (query: UserPageQuery) => {
+		return await api.GetList(query);
+	};
+	const editRequest = async ({ form, row }: EditReq) => {
+		form.id = row.id;
+		return await api.UpdateObj(form);
+	};
+	const delRequest = async ({ row }: DelReq) => {
+		return await api.DelObj(row.id);
+	};
+	const addRequest = async ({ form }: AddReq) => {
+		return await api.AddObj(form);
+	};
+
+	//权限判定
+	const hasPermissions = inject('$hasPermissions');
+
+	return {
+		crudOptions: {
+			table: {
+				height: 600
+			},
+			container: {
+        fixedHeight: false
+      },
+			actionbar: {
+				show: true,
+				buttons: {
+					add: {
+						show: false
+					}
+				}
+			},
+			search: {
+				show: false
+			},
+			toolbar: {
+        buttons: {
+					search: {
+						show: true
+					},
+					compact: {
+						show: false
+					}
+				}
+			},
+			request: {
+				pageRequest,
+				addRequest,
+				editRequest,
+				delRequest,
+			},
+			rowHandle: {
+				fixed: 'right',
+				width: 80,
+				buttons: {
+					view: {
+						show: false,
+					},
+					edit: {
+						iconRight: 'Edit',
+						type: 'text',
+            text: null
+						// show: hasPermissions('dictionary:Update'),
+					},
+					remove: {
+						iconRight: 'Delete',
+						type: 'text',
+            text: null
+						// show: hasPermissions('dictionary:Delete'),
+					},
+				},
+			},
+			columns: {
+        keywordText: {
+          title: '关键词'
+        },
+				matchType: {
+					title: '匹配类型',
+					type: 'dict-select',
+					search: {
+						show: true
+					},
+					dict: dict({
+						data: [
+							{ value: 'BROAD', label: '广泛匹配' },
+							{ value: 'PHRASE', label: '词组匹配' },
+							{ value: 'EXACT', label: '精准匹配' },
+						]
+					})
+				},
+				state: {
+					title: '状态'
+				},
+				bid: {
+					title: '出价'
+				},
+				"campaign": {
+					title: '广告活动'
+				},
+				"adGroup": {
+					title: '广告组'
+				}
+			}
+		}
+	}
+}

+ 112 - 0
src/views/adManage/sb/adPlacement/index.vue

@@ -0,0 +1,112 @@
+<template>
+    <fs-page class="fs-page-custom">
+        <fs-crud ref="crudRef" v-bind="crudBinding">
+            <template #header-middle>
+                <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card" @tab-change="changeTab">
+                    <el-tab-pane label="数据趋势" name="barLine">
+                        <MetricsCards v-model="metrics" :metric-items="options" @change="changeMetric"></MetricsCards>
+                        <div style="display: flex; justify-content: flex-end">
+                            <el-button-group class="ml-4" style="margin-top: 10px; margin-right: 30px">
+                                <el-button type="primary" @click="changeChartData">日</el-button>
+                                <el-button type="primary" @click="changeChartData">周</el-button>
+                                <el-button type="primary" @click="changeChartData">月</el-button>
+                            </el-button-group>
+                        </div>
+                        <BarLineChart ref="barLineRef" :barLineData="barLineData"/>
+                    </el-tab-pane>
+                    <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
+                </el-tabs>
+            </template>
+        </fs-crud>
+    </fs-page>
+</template>
+
+<script setup>
+import {ref, onMounted, onBeforeUnmount, watch, nextTick, onActivated, reactive} from 'vue'
+import {useFs, FsPage} from '@fast-crud/fast-crud'
+import {createCrudOptions} from './crud'
+import {useRoute, useRouter} from 'vue-router'
+import MetricsCards from '/@/components/MetricsCards/index.vue'
+import AdStructChart from '/@/views/adManage/sp/campaigns/chartComponents/adStruct.vue'
+import DataTendencyChart from '/@/views/adManage/sp/campaigns/chartComponents/dataTendency.vue'
+import BarLineChart from '/@/components/echartsComponents/BarLineChart.vue'
+import PieBarChart from '/@/components/echartsComponents/PieBarChart.vue'
+import BarChart from "/@/components/echartsComponents/BarChart.vue"
+
+const tabActiveName = ref('barLine')
+const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: {}})
+
+const metrics = ref([{metric: 'ACOS', color: 'blue'}])
+const options = ref([
+    {label: 'ACOS', value: 'ACOS', metricVal: '18.00%', preVal: '20.15%', gapVal: '-2.00%', disabled: true},
+    {label: '点击量', value: 'clicks', metricVal: '19.00%', preVal: '20.15%', gapVal: '-1.00%', disabled: true},
+    {label: '曝光量', value: 'impression', metricVal: '20.00%', preVal: '15.00%', gapVal: '5.00%', disabled: true},
+    {label: '转化率1', value: 'rate1', metricVal: '1.00%', preVal: '15.00%', gapVal: '5.00%', disabled: true},
+    {label: '转化率2', value: 'rate2', metricVal: '2.00%', preVal: '15.00%', gapVal: '5.00%', disabled: true},
+    {label: '转化率3', value: 'rate3', metricVal: '3.00%', preVal: '15.00%', gapVal: '5.00%', disabled: true},
+    {label: '转化率4', value: 'rate4', metricVal: '4.00%', preVal: '15.00%', gapVal: '5.00%'},
+    {label: '转化率5', value: 'rate5', metricVal: '5.00%', preVal: '15.00%', gapVal: '5.00%'},
+    {label: '转化率6', value: 'rate6', metricVal: '6.00%', preVal: '15.00%', gapVal: '5.00%'},
+])
+const route = useRoute()
+const router = useRouter()
+const barLineRef = ref()
+
+const barLineData = reactive({
+    xData: ['2023-10-18', '2023-10-19', '2023-10-20', '2023-10-21', '2023-10-22', '2023-10-23', '2023-10-24'],
+    barData: [12, 13.4, 12.5, 16, 14.5, 15.6, 12.3],
+    yData1: [18, 13, 10, 8, 9, 10, 14.2],
+    yData2: [14, 15, 12, 16, 15, 13, 14.5]
+})
+
+onMounted(() => {
+    crudExpose.doRefresh()
+})
+
+const resizeTabChart = () => {
+    if (tabActiveName.value === 'barLine') {
+        barLineRef.value.resizeChart()
+    } else if (tabActiveName.value === 'bar') {
+        // BarChartRef.value.resizeChart()
+    }
+}
+const changeTab = () => {
+    nextTick(() => {
+        resizeTabChart()
+    })
+}
+const changeMetric = () => {
+    console.log(metrics.value)
+}
+
+// todo 发送请求获取数据切换图表
+function changeChartData() {
+    updateData({
+        xData: ['2023-10-18', '2023-10-19', '2023-10-20', '2023-10-21', '2023-10-22', '2023-10-23', '2023-10-24'],
+        barData: [10, 13.4, 12, 14, 20, 14, 11.1],
+        yData1: [7, 2, 4, 8, 4, 15, 10],
+        yData2: [15, 10, 12, 14, 12, 10, 12.5]
+    });
+}
+
+function updateData(newData) {
+    // 更新响应式数据
+    Object.assign(barLineData, newData)
+    // 然后更新图表
+    barLineRef.value.updateChart()
+}
+
+defineExpose({resizeTabChart})
+
+</script>
+
+<style lang="scss">
+.chart-tabs {
+    margin: 5px 0;
+
+    .el-tabs__nav {
+        padding-left: 0 !important;
+    }
+}
+
+</style>

+ 42 - 0
src/views/authorization/api.ts

@@ -0,0 +1,42 @@
+import { request } from '/@/utils/service';
+import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
+import XEUtils from 'xe-utils';
+
+export const apiPrefix = '/api/ad_manage/';
+export function GetList(query: PageQuery) {
+    return request({
+        url: apiPrefix,
+        method: 'get',
+        params: query,
+    })
+}
+export function GetObj(id: InfoReq) {
+    return request({
+        url: apiPrefix + id,
+        method: 'get',
+    });
+}
+
+export function AddObj(obj: AddReq) {
+    return request({
+        url: apiPrefix,
+        method: 'post',
+        data: obj,
+    });
+}
+
+export function UpdateObj(obj: EditReq) {
+    return request({
+        url: apiPrefix + obj.id + '/',
+        method: 'put',
+        data: obj,
+    });
+}
+
+export function DelObj(id: DelReq) {
+    return request({
+        url: apiPrefix + id + '/',
+        method: 'delete',
+        data: { id },
+    });
+}

+ 150 - 0
src/views/authorization/crud.tsx

@@ -0,0 +1,150 @@
+import * as api from './api'
+import {dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet} from '@fast-crud/fast-crud'
+import {inject, nextTick, ref} from 'vue'
+import {BaseColumn} from '/@/views/adManage/utils/commonTabColumn.js'
+import {useRouter} from 'vue-router'
+
+export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
+	const pageRequest = async (query: UserPageQuery) => {
+		return await api.GetList(query)
+	}
+	const editRequest = async ({form, row}: EditReq) => {
+		form.id = row.id
+		return await api.UpdateObj(form)
+	}
+	const delRequest = async ({row}: DelReq) => {
+		return await api.DelObj(row.id)
+	}
+	const addRequest = async ({form}: AddReq) => {
+		return await api.AddObj(form)
+	}
+
+	//权限判定
+	const hasPermissions = inject('$hasPermissions')
+
+	// todo 点击新建广告活动进行路由跳转(还有问题)
+	const router = useRouter()
+
+	function goCreate() {
+		router.push('/createcampaigns')
+	}
+
+	return {
+		crudOptions: {
+			table: {
+				height: 800
+			},
+			container: {
+				fixedHeight: false
+			},
+			actionbar: {
+				show: true,
+				buttons: {
+					add: {
+						text: 'xxx',
+						show: false
+					},
+					create: {
+						text: '新建广告活动',
+						type: 'primary',
+						show: true,
+						click() {
+							goCreate()
+						}
+					}
+				}
+			},
+			search: {
+				show: false
+			},
+			toolbar: {
+				buttons: {
+					search: {
+						show: true
+					},
+					compact: {
+						show: false
+					}
+				}
+			},
+			request: {
+				pageRequest,
+				addRequest,
+				editRequest,
+				delRequest,
+			},
+			rowHandle: {
+				fixed: 'right',
+				width: 80,
+				buttons: {
+					view: {
+						show: false,
+					},
+					edit: {
+						iconRight: 'Edit',
+						type: 'text',
+						text: null
+						// show: hasPermissions('dictionary:Update'),
+					},
+					remove: {
+						iconRight: 'Delete',
+						type: 'text',
+						text: null
+						// show: hasPermissions('dictionary:Delete'),
+					},
+				},
+			},
+			columns: {
+				campaignName: {
+					title: '广告活动',
+					column: {
+						width: '150px'
+					},
+					search: {
+						show: true,
+						component: {
+							props: {
+								clearable: true
+							}
+						}
+					},
+					form: {
+						rules: [{required: true, message: '必填项'}]
+					}
+				},
+				// targetingType: {
+				// 	title: '投放类型',
+				// 	type: 'dict-select',
+				// 	search: {
+				// 		show: true
+				// 	},
+				// 	dict: dict({
+				// 		data: [
+				// 			{ value: 'AUTO', label: '自动' },
+				// 			{ value: 'MANUAL', label: '手动' },
+				// 		]
+				// 	})
+				// },
+				state: {
+					title: '状态'
+				},
+				// state: {
+				//     title: '竞价'
+				// },
+				startDate: {
+					title: '开始日期'
+				},
+				endDate: {
+					title: '结束日期'
+				},
+				portfolio: {
+					title: '广告组合'
+				},
+				budget: {
+					title: '预算'
+				},
+				...BaseColumn
+			}
+		}
+	}
+}

+ 30 - 0
src/views/authorization/index.vue

@@ -0,0 +1,30 @@
+<template>
+    <fs-page class="fs-page-custom">
+        <fs-crud ref="crudRef" v-bind="crudBinding">
+            <template #header-middle>
+
+            </template>
+        </fs-crud>
+    </fs-page>
+</template>
+
+<script setup>
+import { ref, onMounted, inject, nextTick } from 'vue'
+import { useFs, FsPage } from '@fast-crud/fast-crud'
+import { createCrudOptions } from './crud'
+import BarLineChart from '/@/components/echartsComponents/BarLineChart.vue'
+import PieBarChart from '/@/components/echartsComponents/PieBarChart.vue'
+import ScatterChart from '/@/components/echartsComponents/ScatterChart.vue'
+import MetricsCards from "/@/components/MetricsCards/index.vue"
+
+const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} })
+
+onMounted(() => {
+    crudExpose.doRefresh()
+})
+
+</script>
+
+<style scoped>
+
+</style>