Java道经 - 项目 - MyLesson - 后台前端(四)
传送门:JP4-7-MyLesson后台前端(一)
传送门:JP4-7-MyLesson后台前端(二)
传送门:JP4-7-MyLesson后台前端(三)
传送门:JP4-7-MyLesson后台前端(四)
传送门:JP4-7-MyLesson后台前端(五)
文章目录
- S05. SMS营销服务
- E01. 通知管理模块
- 1. 查看通知列表
- 2. 添加通知记录
- 3. 修改通知记录
- E02. 横幅管理模块
- 1. 查看横幅列表
- 2. 添加横幅记录
- 3. 修改横幅记录
- E03. 新闻管理模块
- 1. 查看新闻列表
- 2. 添加新闻记录
- 3. 修改新闻记录
- E04. 秒杀管理模块
- 1. 查看秒杀列表
- 2. 添加秒杀记录
- 3. 修改秒杀记录
- 4. 查看秒杀详情
- 5. 添加秒杀详情
- 6. 修改秒杀详情
- E05. 优惠卷管理模块
- 1. 查看优惠卷列表
- 2. 添加优惠卷记录
- 3. 修改优惠卷记录
S05. SMS营销服务
武技:搭建起始文件环境和对应的路由代码。
- 创建全部相关 Vue 页面,结构如下:
|__ views|__ sms|__ notice|__ Notice.vue|__ NoticeInsert.vue|__ NoticeUpdate.vue|__ article|__ Article.vue|__ ArticleInsert.vue|__ ArticleUpdate.vue|__ banner|__ Banner.vue|__ BannerInsert.vue|__ BannerUpdate.vue|__ seckill|__ Seckill.vue|__ SeckillInsert.vue|__ SeckillUpdate.vue|__ detail|__ SeckillDetail.vue|__ SeckillDetailInsert.vue|__ SeckillDetailUpdate.vue|__ coupons|__ Coupons.vue|__ CouponsInsert.vue|__ CouponsUpdate.vue
- 在 router/index.js 文件中开发全部相关页面路由配置
import Notice from "../views/sms/notice/Notice.vue";
import NoticeInsert from "../views/sms/notice/NoticeInsert.vue";
import NoticeUpdate from "../views/sms/notice/NoticeUpdate.vue";
import Article from "../views/sms/article/Article.vue";
import ArticleInsert from "../views/sms/article/ArticleInsert.vue";
import ArticleUpdate from "../views/sms/article/ArticleUpdate.vue";
import Banner from "../views/sms/banner/Banner.vue";
import BannerInsert from "../views/sms/banner/BannerInsert.vue";
import BannerUpdate from "../views/sms/banner/BannerUpdate.vue";
import Seckill from "../views/sms/seckill/Seckill.vue";
import SeckillInsert from "../views/sms/seckill/SeckillInsert.vue";
import SeckillUpdate from "../views/sms/seckill/SeckillUpdate.vue";
import SeckillDetail from "../views/sms/seckill/detail/SeckillDetail.vue";
import SeckillDetailInsert from "../views/sms/seckill/detail/SeckillDetailInsert.vue";
import SeckillDetailUpdate from "../views/sms/seckill/detail/SeckillDetailUpdate.vue";
import Coupons from "../views/sms/coupons/Coupons.vue";
import CouponsInsert from "../views/sms/coupons/CouponsInsert.vue";
import CouponsUpdate from "../views/sms/coupons/CouponsUpdate.vue";const router = createRouter({history: createWebHashHistory(),routes: [{path: '/', name: 'Login', component: Login},{path: '/Main', name: 'Main', component: Main,redirect: '/Dashboard',children: [...{path: '/Notice', name: 'Notice', component: Notice},{path: '/NoticeInsert', name: 'NoticeInsert', component: NoticeInsert},{path: '/NoticeUpdate', name: 'NoticeUpdate', component: NoticeUpdate},{path: '/Article', name: 'Article', component: Article},{path: '/ArticleInsert', name: 'ArticleInsert', component: ArticleInsert},{path: '/ArticleUpdate', name: 'ArticleUpdate', component: ArticleUpdate},{path: '/Banner', name: 'Banner', component: Banner},{path: '/BannerInsert', name: 'BannerInsert', component: BannerInsert},{path: '/BannerUpdate', name: 'BannerUpdate', component: BannerUpdate},{path: '/Seckill', name: 'Seckill', component: Seckill},{path: '/SeckillInsert', name: 'SeckillInsert', component: SeckillInsert},{path: '/SeckillUpdate', name: 'SeckillUpdate', component: SeckillUpdate},{path: '/SeckillDetail', name: 'SeckillDetail', component: SeckillDetail},{path: '/SeckillDetailInsert', name: 'SeckillDetailInsert', component: SeckillDetailInsert},{path: '/SeckillDetailUpdate', name: 'SeckillDetailUpdate', component: SeckillDetailUpdate},{path: '/Coupons', name: 'Coupons', component: Coupons},{path: '/CouponsInsert', name: 'CouponsInsert', component: CouponsInsert},{path: '/CouponsUpdate', name: 'CouponsUpdate', component: CouponsUpdate},]}]
});
E01. 通知管理模块
1. 查看通知列表
心法:查看通知列表页面
武技:开发查看通知列表页面 views/sms/notice/Notice.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyTable from "../../../components/MyTable.vue";
import {onMounted, reactive, ref} from "vue";
import {deleteApi, deleteBatchApi, pageApi} from "../../../api/index.js";
import {myPage} from "../../../request/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Opportunity', label: '通知列表'},
];
// 表格列
const columns = [{label: '序号', prop: 'idx', type: 'tag', width: 65},{label: '通知内容', prop: 'content', type: 'card', width: 500, tooltip: false},
];
// 表格数据 + 分页数据
let records = ref();
let pageInfo = reactive({pageNum: 1, pageSize: 5, callback: page});/*** 分页查询** 1. 定义分页基础配置,包括 records, pageInfo, api, params 等。* 2. 异步发送分页查询请求。** @param pageNum 当前第几页,默认 1* @param pageSize 每页多少条,默认 5*/
async function page(pageNum = pageInfo['pageNum'], pageSize = pageInfo['pageSize']) {let config = {api: pageApi,args: {module: 'notice'},params: {pageNum, pageSize},records, pageInfo,}await myPage(config);
}/* ==================== 加载函数 ==================== */onMounted(() => page());</script><template v-if="records"><my-nav :items="navItems"/><div style="height: 60px"/><my-table module="notice"insert-page="/NoticeInsert"update-page="/NoticeUpdate":delete-api="deleteApi":delete-batch-api="deleteBatchApi":delete-callback="page":records="records":columns="columns":page-info="pageInfo"/>
</template><style scoped lang="scss"></style>
2. 添加通知记录
心法:添加通知记录页面
武技:开发添加通知记录页面 views/sms/notice/NoticeInsert.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {insertApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../router/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Opportunity', label: '通知列表', url: '/Notice'},{icon: 'Plus', label: '添加通知'},
];/* ==================== 添加表单 ==================== */// 表单项 + 表单值 + 表单规则
let items = ref([{label: '排序', prop: 'idx', type: 'number', min: 1, required: true, span: 12},{label: '内容', prop: 'content', required: true, type: 'textarea'},
]);
let params = reactive({});
let rules = {content: RULE.CONTENT};/* ==================== 添加成功后 ==================== */function insertSuccess() {ElMessage.success('添加记录成功!');setTimeout(() => router.push('/Notice'), 1000);
}</script><template><my-nav :items="navItems"/><el-card class="notice-insert-card" header="添加通知"><my-form type="insert":items="items":rules="rules":params="params":api="insertApi":args="{module: 'notice'}":callback="insertSuccess"/></el-card>
</template><style scoped lang="scss">
.notice-insert-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
3. 修改通知记录
心法:修改通知记录页面
武技:开发修改通知记录页面 views/sms/notice/NoticeUpdate.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {updateApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../router/index.js";// 获取当前通知记录
let notice = JSON.parse(sessionStorage.getItem('row'));
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Opportunity', label: '通知列表', url: '/Notice'},{icon: 'Edit', label: '修改通知'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '通知排序', prop: 'idx', type: 'number', min: 1, required: true, span: 12},{label: '通知内容', prop: 'content', required: true, type: 'textarea'},
]);
let params = reactive(notice);
let rules = {content: RULE.CONTENT};/* ==================== 修改成功后 ==================== */function updateSuccess() {ElMessage.success('修改记录成功!');setTimeout(() => router.push('/Notice'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="notice-update-card" header="修改通知信息"><my-form type="update":items="items":rules="rules":params="params":api="updateApi":args="{module: 'notice'}":callback="updateSuccess"/></el-card>
</template><style scoped lang="scss">
.notice-update-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
E02. 横幅管理模块
1. 查看横幅列表
心法:查看横幅列表页面
武技:开发查看横幅列表页面 views/sms/banner/Banner.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyTable from "../../../components/MyTable.vue";
import {onMounted, reactive, ref} from "vue";
import {deleteApi, deleteBatchApi, pageApi} from "../../../api/index.js";
import {myPage} from "../../../request/index.js";
import {MINIO_BANNER} from "../../../const/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Picture', label: '横幅列表'},
];
// 表格列
const columns = [{label: '序号', prop: 'idx', type: 'tag', width: 70},{label: '横幅图片', prop: 'url', type: 'img', width: 100, minio: MINIO_BANNER},{label: '横幅描述', prop: 'info', type: 'card', width: 800},
];/* ==================== 分页查询 ==================== */// 表格数据 + 分页数据
let records = ref();
let pageInfo = reactive({pageNum: 1, pageSize: 5, callback: page});/*** 分页查询** 1. 定义分页基础配置,包括 records, pageInfo, api, params 等。* 2. 附加分页查询条件,如标题等。* 3. 异步发送分页查询请求。** @param pageNum 当前第几页,默认 1* @param pageSize 每页多少条,默认 5*/
async function page(pageNum = pageInfo['pageNum'], pageSize = pageInfo['pageSize']) {let config = {api: pageApi,args: {module: 'banner'},params: {pageNum, pageSize},records, pageInfo,}await myPage(config);
}/* ==================== 加载函数 ==================== */onMounted(() => page());</script><template v-if="records"><my-nav :items="navItems"/><div style="height: 60px"/><my-table module="banner"insert-page="/BannerInsert"update-page="/BannerUpdate":records="records":columns="columns":delete-api="deleteApi":delete-batch-api="deleteBatchApi":delete-callback="page":page-info="pageInfo"/>
</template><style scoped lang="scss"></style>
2. 添加横幅记录
心法:添加横幅记录页面
武技:开发添加横幅记录页面 views/sms/banner/BannerInsert.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {insertApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import router from "../../../router/index.js";
import {ElMessage} from "element-plus";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Picture', label: '横幅列表', url: '/Banner'},{icon: 'Plus', label: '添加横幅'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '横幅排序', prop: 'idx', type: 'number', min: 1, required: true, span: 12},{label: '横幅描述', prop: 'info', required: true, type: 'textarea'},
]);
let params = reactive({});
let rules = {info: RULE.INFO};/* ==================== 添加成功后 ==================== */function insertSuccess() {ElMessage.success('添加成功!');setTimeout(() => router.push('/Banner'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="banner-insert-card" header="添加横幅"><my-form type="insert":items="items":params="params":rules="rules":api="insertApi":args="{module: 'banner'}":callback="insertSuccess"/></el-card>
</template><style scoped lang="scss">
.banner-insert-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
3. 修改横幅记录
心法:修改横幅记录页面
武技:开发修改横幅记录页面 views/sms/banner/BannerUpdate.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import MyUpload from "../../../components/MyUpload.vue";
import {MINIO_BANNER, MINIO_COURSE_SUMMARY, RULE} from "../../../const/index.js";
import {reactive, ref} from "vue";
import {updateApi} from "../../../api/index.js";
import {UPLOAD_BANNER_URL} from "../../../api/sms/banner.js";
import {ElMessage} from "element-plus";
import router from "../../../router/index.js";// 获取当前横幅记录
let banner = JSON.parse(sessionStorage.getItem('row'));
let bannerUrl = ref(MINIO_BANNER(banner['url']));
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Picture', label: '横幅列表', url: '/Banner'},{icon: 'Edit', label: '修改横幅信息'},
];
// 表单项 + 表单值 + 表单规则
let updateFormItems = ref([{label: '横幅排序', prop: 'idx', type: 'number', min: 1, required: true, span: 12},{label: '横幅描述', prop: 'info', required: true, type: 'textarea', rows: 18},
]);
let updateFormParams = reactive(banner);
let updateFormRules = {info: RULE.INFO,};/* ==================== 修改成功后 ==================== */function updateSuccess() {ElMessage.success('修改记录成功!');setTimeout(() => router.push('/Banner'), 1000);
}/* ==================== 上传成功后 ==================== */function uploadSuccess(data) {bannerUrl.value = MINIO_BANNER(data);
}
</script><template><my-nav :items="navItems"/><div class="banner-update-body"><el-row :gutter="20"><el-col :span="8"><el-card class="banner-info-card"><el-image class="banner-image" :src="bannerUrl"/></el-card><el-card class="upload-banner-card" header="上传轮播图片"><my-upload name="bannerFile":url="UPLOAD_BANNER_URL + '/' +banner['id']":autoUpload="true":callback="uploadSuccess"/></el-card></el-col><el-col :span="16"><el-card class="update-card" header="修改基本信息"><my-form type="update":items="updateFormItems":rules="updateFormRules":params="updateFormParams":api="updateApi":args="{module: 'banner'}":callback="updateSuccess"/></el-card></el-col></el-row></div>
</template><style scoped lang="scss">
.banner-update-body {width: 90%; // 宽度margin: 65px auto 0; // 外边距.banner-info-card {text-align: center; // 内容居中.banner-image {height: 170px; // 高度}}.upload-banner-card {margin-top: 18px; // 上外边距}
}
</style>
E03. 新闻管理模块
1. 查看新闻列表
心法:查看新闻列表页面
武技:开发查看新闻列表页面 views/sms/article/Article.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyHead from "../../../components/MyHead.vue";
import MyTable from "../../../components/MyTable.vue";
import {onMounted, reactive, ref} from "vue";
import {deleteApi, deleteBatchApi, pageApi} from "../../../api/index.js";
import {myPage} from "../../../request/index.js";
import {isNotEmpty, isNotNull} from "../../../util/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'WindPower', label: '新闻列表'},
];
// 数据头
const headItems = [{type: 'ipt', span: 5, placeholder: '按标题搜索', callback: pageLikeTitle},
];
// 表格列
const columns = [{label: '序号', prop: 'idx', type: 'tag', width: 70},{label: '标题', prop: 'title', width: 300},{label: '内容', prop: 'content', type: 'card', width: 500, tooltip: false},
];/* ==================== 分页查询 ==================== */// 表格行 + 分页 + 新闻标题
let records = ref();
let pageInfo = reactive({pageNum: 1, pageSize: 5, callback: page});
let title = ref();/*** 分页查询** 1. 定义分页基础配置,包括 records, pageInfo, api, params 等。* 2. 附加分页查询条件,如标题等。* 3. 异步发送分页查询请求。** @param pageNum 当前第几页,默认 1* @param pageSize 每页多少条,默认 5*/
async function page(pageNum = pageInfo['pageNum'], pageSize = pageInfo['pageSize']) {let config = {api: pageApi,args: {module: 'article'},params: {pageNum, pageSize},records, pageInfo,}if (isNotEmpty(title.value)) config['params']['title'] = title.value;await myPage(config);
}/* ==================== 搜索新闻标题 ==================== *//*** 按新闻标题模糊查询** 1. 将输入框中的值赋值给分页条件字段变量。* 2. 重新发送分页请求。** @param val 输入框中的值*/
function pageLikeTitle(val) {if (isNotNull(val) || title.value) {title.value = val;page();}
}/* ==================== 加载函数 ==================== */onMounted(() => page());
</script><template v-if="records"><my-nav :items="navItems"/><my-head :items="headItems"/><my-table module="article"insert-page="/ArticleInsert"update-page="/ArticleUpdate":delete-api="deleteApi":delete-batch-api="deleteBatchApi":delete-callback="page":records="records":columns="columns":page-info="pageInfo"/>
</template><style scoped lang="scss"></style>
2. 添加新闻记录
心法:添加新闻记录页面
武技:开发添加新闻记录页面 views/sms/article/ArticleInsert.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {insertApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import router from "../../../router/index.js";
import {ElMessage} from "element-plus";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'WindPower', label: '新闻列表', url: '/Article'},{icon: 'Plus', label: '添加新闻'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '排序', prop: 'idx', type: 'number', min: 1, required: true, span: 12},{hidden: true, span: 12},{label: '标题', prop: 'title', required: true, type: 'textarea', rows: 3},{label: '内容', prop: 'content', required: true, type: 'textarea'},
]);
let params = reactive({});
let rules = {content: RULE.CONTENT};/* ==================== 添加成功后 ==================== */function insertSuccess() {ElMessage.success('添加成功!');setTimeout(() => router.push('/Article'), 1000);
}</script><template><my-nav :items="navItems"/><el-card class="article-insert-card" header="添加新闻"><my-form type="insert":items="items":rules="rules":params="params":api="insertApi":args="{module: 'article'}":callback="insertSuccess"/></el-card>
</template><style scoped lang="scss">
.article-insert-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
3. 修改新闻记录
心法:修改新闻记录页面
武技:开发修改新闻记录页面 views/sms/article/ArticleUpdate.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {updateApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../router/index.js";// 获取当前新闻记录
let article = JSON.parse(sessionStorage.getItem('row'));
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'WindPower', label: '新闻列表', url: '/Article'},{icon: 'Edit', label: '修改新闻'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '排序', prop: 'idx', type: 'number', min: 1, required: true, span: 12},{hidden: true, span: 12},{label: '标题', prop: 'title', required: true, type: 'textarea', rows: 3},{label: '内容', prop: 'content', required: true, type: 'textarea'},
]);
let params = reactive(article);
let rules = {content: RULE.INFO};/* ==================== 修改成功后 ==================== */function updateSuccess() {ElMessage.success('修改记录成功!');setTimeout(() => router.push('/Article'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="article-update-card" header="修改新闻信息"><my-form type="update":items="items":params="params":rules="rules":api="updateApi":args="{module: 'article'}":callback="updateSuccess"/></el-card>
</template><style scoped lang="scss">
.article-update-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
E04. 秒杀管理模块
1. 查看秒杀列表
心法:查看秒杀列表页面
武技:开发查看秒杀列表页面 views/sms/seckill/Seckill.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyHead from "../../../components/MyHead.vue";
import MyTable from "../../../components/MyTable.vue";
import {onMounted, reactive, ref} from "vue";
import {deleteApi, deleteBatchApi, pageApi} from "../../../api/index.js";
import {myPage} from "../../../request/index.js";
import {dateFormat, isNotEmpty, isNotNull, seckillStatusFormat} from "../../../util/index.js";
import router from "../../../router/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Stopwatch', label: '秒杀列表'},
];
// 数据头
const headItems = [{type: 'ipt', span: 5, placeholder: '按标题搜索', callback: pageLikeTitle},
];
// 表格列
const columns = [{label: '活动标题', prop: 'title', width: 120},{label: '开始时间', prop: 'startTime', format: dateFormat},{label: '结束时间', prop: 'endTime', format: dateFormat},{label: '活动状态', prop: 'status', type: 'tag', format: seckillStatusFormat},{label: '活动描述', prop: 'info', type: 'card', tooltip: false},
];
// 按钮列
const buttons = [{label: '秒杀详情', type: 'success', callback: seckillDetail},
];
// 表格数据 + 分页数据 + 秒杀活动标题
let records = ref();
let pageInfo = reactive({pageNum: 1, pageSize: 5, callback: page});
let title = ref();/*** 分页查询** 1. 定义分页基础配置,包括 records, pageInfo, api, params 等。* 2. 附加分页查询条件,如标题等。* 3. 异步发送分页查询请求。** @param pageNum 当前第几页,默认 1* @param pageSize 每页多少条,默认 5*/
async function page(pageNum = pageInfo['pageNum'], pageSize = pageInfo['pageSize']) {let config = {api: pageApi,args: {module: 'seckill'},params: {pageNum, pageSize},records, pageInfo,}if (isNotEmpty(title.value)) config['params']['title'] = title.value;await myPage(config);
}/* ==================== 搜索秒杀标题 ==================== *//*** 按秒杀标题模糊查询** 1. 将输入框中的值赋值给分页条件字段变量。* 2. 重新发送分页请求。** @param val 输入框中的值*/
function pageLikeTitle(val) {if (isNotNull(val) || title.value) {title.value = val;page();}
}/* ==================== 秒杀详情 ==================== */function seckillDetail(row) {sessionStorage.setItem('seckillId', row['id']);sessionStorage.setItem('seckillTitle', row['title'].toString());router.push('/SeckillDetail');
}/* ==================== 加载函数 ==================== */onMounted(() => page());</script><template v-if="records"><my-nav :items="navItems"/><my-head :items="headItems"/><my-table module="seckill"insert-page="/SeckillInsert"update-page="/SeckillUpdate":records="records":columns="columns":buttons="buttons":delete-api="deleteApi":delete-batch-api="deleteBatchApi":delete-callback="page":page-info="pageInfo"/>
</template><style scoped lang="scss"></style>
2. 添加秒杀记录
心法:添加秒杀记录页面
武技:开发添加秒杀记录页面 views/sms/seckill/SeckillInsert.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {insertApi} from "../../../api/index.js";
import {RULE, SECKILL_STATUS_OPTIONS} from "../../../const/index.js";
import router from "../../../router/index.js";
import {ElMessage} from "element-plus";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Stopwatch', label: '秒杀列表', url: '/Seckill'},{icon: 'Plus', label: '添加秒杀'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '活动标题', prop: 'title', required: true, span: 12},{label: '活动状态', prop: 'status', span: 12, type: 'select', required: true, options: SECKILL_STATUS_OPTIONS, placeholder: '请选择活动状态'},{label: '开始时间', prop: 'startTime', type: 'datetime', required: true, span: 12},{label: '结束时间', prop: 'endTime', type: 'datetime', required: true, span: 12},{label: '活动描述', prop: 'info', required: true, type: 'textarea'},
]);
let params = reactive({});
let rules = {info: RULE.INFO};/* ==================== 添加成功后 ==================== */function insertSuccess() {ElMessage.success('添加成功!');setTimeout(() => router.push('/Seckill'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="seckill-insert-card" header="添加秒杀活动"><my-form type="insert":items="items":rules="rules":params="params":api="insertApi":args="{module: 'seckill'}":callback="insertSuccess"/></el-card>
</template><style scoped lang="scss">
.seckill-insert-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
3. 修改秒杀记录
心法:修改秒杀记录页面
武技:开发修改秒杀记录页面 views/sms/seckill/SeckillUpdate.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {updateApi} from "../../../api/index.js";
import {RULE, SECKILL_STATUS_OPTIONS} from "../../../const/index.js";
import router from "../../../router/index.js";
import {ElMessage} from "element-plus";// 获取当前秒杀记录
let seckill = JSON.parse(sessionStorage.getItem('row'));
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Stopwatch', label: '秒杀列表', url: '/Seckill'},{icon: 'Edit', label: '修改秒杀'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '活动标题', prop: 'title', required: true, span: 12},{label: '活动状态', prop: 'status', span: 12, type: 'select', required: true, options: SECKILL_STATUS_OPTIONS, placeholder: '请选择活动状态'},{label: '开始时间', prop: 'startTime', type: 'datetime', required: true, span: 12},{label: '结束时间', prop: 'endTime', type: 'datetime', required: true, span: 12},{label: '活动描述', prop: 'info', required: true, type: 'textarea'},
]);
let params = reactive(seckill);
let rules = {info: RULE.INFO};/* ==================== 修改成功后 ==================== */function updateSuccess() {ElMessage.success('修改记录成功!');setTimeout(() => router.push('/Seckill'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="seckill-update-card" header="修改秒杀活动信息"><my-form type="update":items="items":rules="rules":params="params":api="updateApi":args="{module: 'seckill'}":callback="updateSuccess"/></el-card>
</template><style scoped lang="scss">
.seckill-update-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
4. 查看秒杀详情
心法:查看秒杀详情页面
武技:开发查看秒杀详情页面 views/sms/seckill/detail/SeckillDetail.vue
<script setup>
import MyNav from "../../../../components/MyNav.vue";
import MyHead from "../../../../components/MyHead.vue";
import MyTable from "../../../../components/MyTable.vue";
import {onMounted, reactive, ref} from "vue";
import {deleteApi, deleteBatchApi, pageApi} from "../../../../api/index.js";
import {isNotEmpty, isNotNull} from "../../../../util/index.js";
import {myPage} from "../../../../request/index.js";
import {MINIO_COURSE_COVER} from "../../../../const/index.js";// 所属秒杀活动ID和秒杀活动标题
let seckillId = sessionStorage.getItem('seckillId');
let seckillTitle = sessionStorage.getItem('seckillTitle');
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Stopwatch', label: '秒杀列表', url: '/Seckill'},{icon: 'Stopwatch', label: `《${seckillTitle}》活动详情`},
];
// 数据头
const headItems = [{type: 'ipt', span: 5, placeholder: '按标题搜索', callback: pageLikeCourseTitle},
];
// 表格列
const columns = [{label: '课程标题', prop: 'courseTitle'},{label: '课程封面', prop: 'courseCover', type: 'img', minio: MINIO_COURSE_COVER},{label: '课程原价', prop: 'coursePrice', suffix: '.00元'},{label: '课程秒杀价', prop: 'skPrice', suffix: '.00元'},{label: '课程秒杀数量', prop: 'skCount'},{label: '秒杀描述', prop: 'info', type: 'card', tooltip: false},
];
// 表格数据 + 分页数据 + 课程标题
let records = ref();
let pageInfo = reactive({pageNum: 1, pageSize: 5, callback: page});
let courseTitle = ref();/* ==================== 分页查询 ==================== *//*** 分页查询记录** 1. 定义分页基础配置,包括 records, pageInfo, api, params 等。* 2. 附加分页查询条件,如标题等。* 3. 异步发送分页查询请求。* 4. 将 seckillTitle 融入表格数据的每一项,方便进行展示。** @param pageNum 当前第几页,默认 1* @param pageSize 每页多少条,默认 5*/
async function page(pageNum = pageInfo['pageNum'], pageSize = pageInfo['pageSize']) {let config = {api: pageApi,args: {module: 'seckillDetail'},params: {pageNum, pageSize, seckillId},records, pageInfo,}if (isNotEmpty(courseTitle.value)) config['params']['courseTitle'] = courseTitle.value;await myPage(config);if(isNotNull(records.value)){Object.values(records.value).forEach(seckill => seckill['seckillTitle'] = `${seckillTitle}`);}
}/* ==================== 搜索课程标题 ==================== *//*** 按秒杀详情标题模糊查询** 1. 将输入框中的值赋值给分页条件字段变量。* 2. 重新发送分页请求。** @param val 输入框中的值*/
function pageLikeCourseTitle(val) {if (isNotNull(val) || courseTitle.value) {courseTitle.value = val;page();}
}/* ==================== 加载函数 ==================== */onMounted(() => page());</script><template v-if="records"><my-nav :items="navItems"/><my-head :items="headItems"/><my-table module="seckillDetail"insert-page="/SeckillDetailInsert"update-page="/SeckillDetailUpdate":records="records":columns="columns":delete-api="deleteApi":delete-batch-api="deleteBatchApi":delete-callback="page":page-info="pageInfo"/>
</template><style scoped lang="scss"></style>
5. 添加秒杀详情
心法:添加秒杀详情页面
武技:开发添加秒杀详情页面 views/sms/seckill/detail/SeckillDetailInsert.vue
<script setup>
import MyNav from "../../../../components/MyNav.vue";
import MyForm from "../../../../components/MyForm.vue";
import {onMounted, reactive, ref} from "vue";
import {insertApi, simpleListApi} from "../../../../api/index.js";
import {getResponseData} from "../../../../request/index.js";
import {RULE} from "../../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../../router/index.js";// 所属秒杀活动ID和秒杀活动标题
let seckillId = sessionStorage.getItem('seckillId');
let seckillTitle = sessionStorage.getItem('seckillTitle');
// 全部课程下拉菜单选项
let courseOptions = ref([]);
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Stopwatch', label: '秒杀列表', url: '/Seckill'},{icon: 'Stopwatch', label: `《${seckillTitle}》活动详情`, url: '/SeckillDetail'},{icon: 'Plus', label: '添加活动课程'},
];/* ==================== 添加表单 ==================== */// 表单项 + 表单值 + 表单规则
let items = ref([{label: '所属活动', prop: 'seckillTitle', disabled: true, span: 12},{label: '活动课程', prop: 'fkCourseId', required: true, span: 12, type: 'select', options: courseOptions, placeholder: '请选择课程'},{label: '秒杀价格', prop: 'skPrice', type: 'number', min: 1, required: true, span: 12},{label: '秒杀数量', prop: 'skCount', type: 'number', min: 1, required: true, span: 12},{label: '秒杀描述', prop: 'info', required: true, type: 'textarea'},
]);
let params = reactive({seckillTitle, 'fkSeckillId': seckillId});
let rules = {info: RULE.INFO};/* ==================== 添加成功后 ==================== */function insertSuccess() {ElMessage.success('添加成功!');setTimeout(() => router.push('/SeckillDetail'), 1000);
}/* ==================== 加载函数 ==================== */onMounted(async () => {// 查询全部课程并添加到下拉菜单选项中Object.values(getResponseData(await simpleListApi(null, {module: 'course'}))).forEach(course => {courseOptions.value.push({label: course['title'] + '(¥' + course['price'] + ')', value: course['id']});});
});
</script><template><my-nav :items="navItems"/><el-card v-if="courseOptions.length > 0" class="seckill-detail-insert-card" header="添加活动课程"><my-form type="insert":items="items":rules="rules":params="params":api="insertApi":args="{module: 'seckillDetail'}":callback="insertSuccess"/></el-card>
</template><style scoped lang="scss">
.seckill-detail-insert-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
6. 修改秒杀详情
心法:修改秒杀详情页面
武技:开发修改秒杀详情页面 views/sms/seckill/detail/SeckillDetailUpdate.vue
<script setup>
import MyNav from "../../../../components/MyNav.vue";
import MyForm from "../../../../components/MyForm.vue";
import {onMounted, reactive, ref} from "vue";
import {simpleListApi, updateApi} from "../../../../api/index.js";
import {getResponseData} from "../../../../request/index.js";
import {RULE} from "../../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../../router/index.js";// 获取当前秒杀详情记录
let seckillDetail = JSON.parse(sessionStorage.getItem('row'));
// 所属秒杀活动ID和秒杀活动标题
let seckillId = sessionStorage.getItem('seckillId');
let seckillTitle = sessionStorage.getItem('seckillTitle');
// 全部课程下拉菜单选项
let courseOptions = ref([]);
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Stopwatch', label: '秒杀列表', url: '/Seckill'},{icon: 'Stopwatch', label: `《${seckillTitle}》活动详情`, url: '/SeckillDetail'},{icon: 'Edit', label: '修改秒杀详情'},
];/* ==================== 修改表单 ==================== */// 表单项 + 表单值 + 表单规则
let items = ref([{label: '所属活动', prop: 'seckillTitle', disabled: true, span: 12},{label: '活动课程', prop: 'fkCourseId', required: true, span: 12, type: 'select', options: courseOptions, placeholder: '请选择课程'},{label: '秒杀价格', prop: 'skPrice', type: 'number', min: 1, required: true, span: 12},{label: '秒杀数量', prop: 'skCount', type: 'number', min: 1, required: true, span: 12},{label: '秒杀描述', prop: 'info', type: 'textarea'},
]);
let params = reactive(seckillDetail);
let rules = {info: RULE.INFO};/* ==================== 修改成功后 ==================== */function updateSuccess() {ElMessage.success('添加成功!');setTimeout(() => router.push('/SeckillDetail'), 1000);
}/* ==================== 加载函数 ==================== */onMounted(async () => {// 查询全部课程并添加到下拉菜单选项中Object.values(getResponseData(await simpleListApi(null, {module: 'course'}))).forEach(course => {courseOptions.value.push({label: course['title'] + '(¥' + course['price'] + ')', value: course['id']});});
});
</script><template><my-nav :items="navItems"/><el-card v-if="courseOptions.length > 0" class="sub-seckill-detail-update-card" header="修改秒杀详情信息"><my-form type="update":items="items":rules="rules":params="params":api="updateApi":args="{module: 'seckillDetail'}":callback="updateSuccess"/></el-card>
</template><style scoped lang="scss">
.sub-seckill-detail-update-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
E05. 优惠卷管理模块
1. 查看优惠卷列表
心法:查看优惠卷列表页面
武技:开发查看优惠卷列表页面 views/sms/coupons/Coupons.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyTable from "../../../components/MyTable.vue";
import MyHead from "../../../components/MyHead.vue";
import {onMounted, reactive, ref} from "vue";
import {deleteApi, deleteBatchApi, pageApi} from "../../../api/index.js";
import {myPage} from "../../../request/index.js";
import {dateFormat, isNotEmpty, isNotNull} from "../../../util/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Opportunity', label: '优惠卷列表'},
];
// 数据头
const headItems = [{type: 'ipt', span: 5, placeholder: '按标题搜索', callback: pageLikeTitle},{type: 'ipt', span: 5, placeholder: '按口令搜索', callback: pageLikeCode},
];
// 表格列
const columns = [{label: '兑换码', prop: 'code', type: 'tag', sortable: false},{label: '标题', prop: 'title'},{label: '优惠价格', prop: 'cpPrice', suffix: '.00 元', width: 130},{label: '生效时间', prop: 'startTime', format: dateFormat, width: 150},{label: '失效时间', prop: 'endTime', format: dateFormat, width: 150},{label: '优惠卷描述', prop: 'info', type: 'card', tooltip: false},
];/* ==================== 分页查询 ==================== */// 表格数据 + 分页数据 + 优惠卷标题 + 优惠卷口令
let records = ref();
let pageInfo = reactive({pageNum: 1, pageSize: 5, callback: page});
let title = ref();
let code = ref();/*** 分页查询** 1. 定义分页基础配置,包括 records, pageInfo, api, params 等。* 2. 附加分页查询条件,如标题,口令等。* 3. 异步发送分页查询请求。** @param pageNum 当前第几页,默认 1* @param pageSize 每页多少条,默认 5*/
async function page(pageNum = pageInfo['pageNum'], pageSize = pageInfo['pageSize']) {let config = {api: pageApi,args: {module: 'coupons'},params: {pageNum, pageSize, pid: 0},records, pageInfo,}if (isNotEmpty(title.value)) config['params']['title'] = title.value;if (isNotEmpty(code.value)) config['params']['code'] = code.value;await myPage(config);
}/* ==================== 搜索优惠卷标题 ==================== *//*** 按优惠卷标题模糊查询** 1. 将输入框中的值赋值给分页条件字段变量。* 2. 重新发送分页请求。** @param val 输入框中的值*/
function pageLikeTitle(val) {if (isNotNull(val) || title.value) {title.value = val;page();}
}/* ==================== 搜索优惠卷口令 ==================== *//*** 按优惠卷口令模糊查询** 1. 将输入框中的值赋值给分页条件字段变量。* 2. 重新发送分页请求。** @param val 输入框中的值*/
function pageLikeCode(val) {if (isNotNull(val) || code.value) {code.value = val;page();}
}/* ==================== 加载函数 ==================== */onMounted(() => page());</script><template v-if="records"><my-nav :items="navItems"/><my-head :items="headItems"/><my-table module="coupons"insert-page="/CouponsInsert"update-page="/CouponsUpdate":records="records":columns="columns":delete-api="deleteApi":delete-batch-api="deleteBatchApi":delete-callback="page":page-info="pageInfo"/>
</template><style scoped lang="scss"></style>
2. 添加优惠卷记录
心法:添加优惠卷记录页面
武技:开发添加优惠卷记录页面 views/sms/coupons/CouponsInsert.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {insertApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../router/index.js";// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Opportunity', label: '优惠卷列表', url: '/Coupons'},{icon: 'Plus', label: '添加优惠卷'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '兑换口令', prop: 'code', required: true},{label: '标题', prop: 'title', required: true, span: 12},{label: '优惠价格', prop: 'cpPrice', type: 'number', min: 1, required: true, span: 12},{label: '生效时间', prop: 'startTime', type: 'datetime', required: true, span: 12},{label: '失效时间', prop: 'endTime', type: 'datetime', required: true, span: 12},{label: '描述', prop: 'info', required: true, type: 'textarea'},
]);
let params = reactive({});
let rules = {code: RULE.CODE, title: RULE.TITLE, content: RULE.INFO,};/* ==================== 添加成功后 ==================== */function insertSuccess() {ElMessage.success('添加成功!');setTimeout(() => router.push('/Coupons'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="coupons-insert-card" header="添加优惠卷"><my-form type="insert":items="items":rules="rules":params="params":api="insertApi":args="{module: 'coupons'}":callback="insertSuccess"/></el-card>
</template><style scoped lang="scss">
.coupons-insert-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
3. 修改优惠卷记录
心法:修改优惠卷记录页面
武技:开发修改优惠卷记录页面 views/sms/coupons/CouponsUpdate.vue
<script setup>
import MyNav from "../../../components/MyNav.vue";
import MyForm from "../../../components/MyForm.vue";
import {reactive, ref} from "vue";
import {updateApi} from "../../../api/index.js";
import {RULE} from "../../../const/index.js";
import {ElMessage} from "element-plus";
import router from "../../../router/index.js";// 获取当前优惠卷记录
let coupons = JSON.parse(sessionStorage.getItem('row'));
// 路径导航
const navItems = [{icon: 'Goods', label: '营销管理'},{icon: 'Opportunity', label: '优惠卷列表', url: '/Coupons'},{icon: 'Edit', label: '修改优惠卷'},
];
// 表单项 + 表单值 + 表单规则
let items = ref([{label: '兑换口令', prop: 'code', required: true},{label: '标题', prop: 'title', required: true, span: 12},{label: '优惠价格', prop: 'cpPrice', type: 'number', min: 1, required: true, span: 12},{label: '生效时间', prop: 'startTime', type: 'datetime', required: true, span: 12},{label: '失效时间', prop: 'endTime', type: 'datetime', required: true, span: 12},{label: '描述', prop: 'info', required: true, type: 'textarea'},
]);
let params = reactive(coupons);
let rules = {code: RULE.CODE, title: RULE.TITLE, content: RULE.INFO};/* ==================== 修改成功后 ==================== */function updateSuccess() {ElMessage.success('修改记录成功!');setTimeout(() => router.push('/Coupons'), 1000);
}
</script><template><my-nav :items="navItems"/><el-card class="coupons-update-card" header="修改优惠卷信息"><my-form type="update":items="items":rules="rules":params="params":api="updateApi":args="{module: 'coupons'}":callback="updateSuccess"/></el-card>
</template><style scoped lang="scss">
.coupons-update-card {width: 60%; // 宽度margin: 65px auto 0; // 外边距
}
</style>
Java道经 - 项目 - MyLesson - 后台前端(四)
传送门:JP4-7-MyLesson后台前端(一)
传送门:JP4-7-MyLesson后台前端(二)
传送门:JP4-7-MyLesson后台前端(三)
传送门:JP4-7-MyLesson后台前端(四)
传送门:JP4-7-MyLesson后台前端(五)