目錄
一、總述
二、前端部分
1. 調整查詢調用
2. 關聯分類
三、后端部分
四、總結
一、總述
之前是在商品的分類管理中直接使用的若依的逆向代碼
有下面的幾個問題:
1. 表格上面的參數填寫之后,都是按照完全匹配進行搜索,沒有模糊匹配
2. 分頁有問題
上面的這兩個問題只要是你不做任何的修改,就是這個樣子
下面是這里品牌管理特殊的:
1. 每個品牌需要關聯分類
總的來說
前端:
在前端上面,將api啊,請求參數啊配好,因為其實這里是為了規范,原本的話,這個若依逆向生成的,的表單數據除了本身的填寫的那些信息,還有分頁參數也填上去了。這樣的話就一個參數,當然后端可以只用一個參數接收,但是這個參數類除了含品牌的信息還額外的需要分頁信息,就不合理了,因此得拆分,所以前端需要修改一下
另外因為每個品牌需要關聯分類,因此還得添加上關聯分類的這個按鈕
后端:
這里的話,還是發生了一些改變的,相比之前直接無腦用。
首先:
1. 查詢要分頁并且模糊查詢
2. 其次刪除接口不能只刪品牌本身,其品牌分類的關聯也要將其刪除(要有這種意識,其實這種意識是最基本的,我之前還傻傻的沒有意識到,寫博文的時候重看才發現問題的)
然后對于品牌本身接口就這些修改。然后這里涉及到品牌-分類關聯,因此
這里的話,這個關聯的相關接口,要考慮是否需要對逆向生成的接口作修改
1. 通過需求,顯示的時候需要顯示分類名和品牌名
還好這個在關系表中都做了冗余存儲,所以查的話正常查,不需要多次查啥的
2. 但是新增的時候,就需要查出品牌名和分類名,然后存入到關聯表中
二、前端部分
兩點:
1. 調整查詢調用
現在需要分頁(其實本來就可以分頁的,只是這里規范一下子,其實也不知道是不是真的規范,但是我現在就這樣弄吧!)
api:
// 查詢品牌列表
export function listBrand(brandParams,pageParams) {return request({url: '/product/brand/list',method: 'get',params: {brand: JSON.stringify(brandParams),pageParams: JSON.stringify(pageParams)}})
}
這里的話其實如果要想兩個參數還是get請求的話,就必須得這樣寫,就是先將其轉為字符串,
直接對象的話,我測試了后端接收不到。除非換成post請求,后端使用@RequestBody進行接收
調用:?
?
/** 查詢品牌列表 */getList() {this.loading = true;const {name,descript,firstLetter,sort} = this.queryParams;const {pageNum,pageSize} = this.queryParams;let brandParams = {name,descript,firstLetter,sort};let pageParams = {pageNum,pageSize};listBrand(brandParams,pageParams).then((response) => {this.brandList = response.rows;this.total = response.total;this.loading = false;});},
2. 關聯分類
1. 從老師給的代碼中選取相關構件(有基本樣子)
1. 1 將其”關聯分類“按鈕放好
<el-button type="text" size="mini" @click="updateCatelogHandle(scope.row.brandId)">關聯分類</el-button>
1.2 彈窗代碼放置好
<el-dialog title="關聯分類" :visible.sync="cateRelationDialogVisible" width="30%"><el-popover placement="right-end" v-model="popCatelogSelectVisible"><category-cascader :catelogPath.sync="catelogPath"></category-cascader><div style="text-align: right; margin: 0"><el-button size="mini" type="text" @click="popCatelogSelectVisible = false">取消</el-button><el-button type="primary" size="mini" @click="addCatelogSelect">確定</el-button></div><el-button slot="reference">新增關聯</el-button></el-popover><el-table :data="cateRelationTableData" style="width: 100%"><el-table-column prop="id" label="#"></el-table-column><el-table-column prop="brandName" label="品牌名"></el-table-column><el-table-column prop="catelogName" label="分類名"></el-table-column><el-table-column fixed="right" header-align="center" align="center" label="操作"><template slot-scope="scope"><el-buttontype="text"size="small"@click="deleteCateRelationHandle(scope.row.id,scope.row.brandId)">移除</el-button></template></el-table-column></el-table><span slot="footer" class="dialog-footer"><el-button @click="cateRelationDialogVisible = false">取 消</el-button><el-button type="primary" @click="cateRelationDialogVisible = false">確 定</el-button></span></el-dialog>
?注意到,它這里用了一個popover標簽,這其實就是彈出窗
還是嵌套彈出窗。我把最后的效果拿出來:
至于這個分類怎么出來的,就是下面這一句:
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
這里的sync的作用是當選擇的分類發生變化的時候,父組件中的catelogPath也將動態的變化
所以得在父組件也就是引用這個組件的組件,也就是在品牌的這個組件中,在數據域中聲明好:catelogPath這個屬性?
?這里就是一個分類組件,自己封裝的,因為很多地方需要使用
要正確使用還是那三步:
1. 抽取組件
這里之前第十天的時候添加屬性分組的時候,已經抽取出來了:
但是我那個比較簡單,沒有涉及到categoryPath的動態感應
沒什么好說的,直接用老師的:
<template>
<!--
使用說明:
1)、引入category-cascader.vue
2)、語法:<category-cascader :catelogPath.sync="catelogPath"></category-cascader>解釋:catelogPath:指定的值是cascader初始化需要顯示的值,應該和父組件的catelogPath綁定;由于有sync修飾符,所以cascader路徑變化以后自動會修改父的catelogPath,這是結合子組件this.$emit("update:catelogPath",v);做的--><div><el-cascaderfilterableclearable placeholder="試試搜索:手機"v-model="paths":options="categorys":props="setting"></el-cascader></div>
</template><script>
//這里可以導入其他文件(比如:組件,工具js,第三方插件js,json文件,圖片文件等等)
//例如:import?《組件名稱》?from?'《組件路徑》';
import {treeListCategory} from "@/api/product/category"
export default {//import引入的組件需要注入到對象中才能使用components: {},//接受父組件傳來的值props: {catelogPath: {type: Array,default(){return [];}}},data() {//這里存放數據return {setting: {value: "catId",label: "name",children: "children",expandTrigger: 'hover'},categorys: [],paths: this.catelogPath};},watch:{catelogPath(v){this.paths = this.catelogPath;},paths(v){this.$emit("update:catelogPath",v);//還可以使用pubsub-js進行傳值this.PubSub.publish("catPath",v);}},//方法集合methods: {getCategorys() {treeListCategory().then((response)=>{this.categorys = response.data;})}},//生命周期?-?創建完成(可以訪問當前this實例)created() {this.getCategorys();}
};
</script>
<style?scoped>
</style>
2. 導入組件
3. 使用組件
2. 從模板中提取好數據,綁定到數據域中
無非就是一些 彈窗的標志值還有數據
3. 修改方法
就是對老師給的方法看是不是要修改一下,無非就是修改一下數據格式,邏輯基本上不需要修改,無非就是請求那里使用自己的,導入一下自己的api,調用自己的請求對象
1.?
?這個沒什么好說的,不要修改,就是打開一下彈窗,并且記錄當前那一行的品牌id,為以后查關聯作鋪墊
?2. 獲取關聯列表
到這里,直接把查曾刪都全部導入進來
?這個沒什么好說的,主要是記得若依框架的查詢接口,最終是以TableDataInfo對象返回的,所以得拿到里面的row才是真正的數據,這里的話不涉及到分頁,所以拿到這個row真正的數據就行了。
//查詢關聯列表getCateRelation() {listRelation({brandId: this.brandId}).then((response)=>{this.cateRelationTableData = response.rows;})},
3. 新增關聯
沒什么好說的,傳上品牌id和分類id即可
//新增品牌分類關聯addCatelogSelect() {this.popCatelogSelectVisible =false;addRelation({brandId: this.brandId,catelogId: this.catelogPath[this.catelogPath.length-1]}).then((response)=>{if(response.code == 200){this.$modal.msgSuccess("新增品牌分類關系成功");this.getCateRelation();}else{this.$modal.confirm("新增品牌分類關系失敗");}})}
4. 刪除關聯
也沒什么好說的,直接傳入關聯id也就是當前這條記錄的id即可
//刪除關聯deleteCateRelationHandle(id) {delRelation(id).then((response)=>{if(response.code == 200){this.$modal.msgSuccess("刪除品牌分類關系成功");this.getCateRelation();}else{this.$modal.confirm("刪除品牌分類關系失敗");}})}
三、后端部分
1. 首先品牌本身
1.1 分頁模糊查詢
這個得話使用MP帶的分頁功能,因為若依自帶的我還沒弄明白。
需要注意的是要使用MP帶的分頁,就得配置一下,不然不起作用:
@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();paginationInnerInterceptor.setOptimizeJoin(true);paginationInnerInterceptor.setDbType(DbType.MYSQL);paginationInnerInterceptor.setOverflow(true);interceptor.addInnerInterceptor(paginationInnerInterceptor);OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);return interceptor;}
}
反正我用的3.4.3版本的MP是需要這個的:
?接口:
/*** 查詢品牌列表*/
@ApiOperation("查詢品牌列表")
//@PreAuthorize("@ss.hasPermi('product:brand:list')")
@GetMapping("/list")public TableDataInfo list(@RequestParam("brand") String brandJson,@RequestParam("pageParams") String pageParamsJson) {Brand brand = new Gson().fromJson(brandJson, Brand.class);PageParamsDto pageParamsDto = new Gson().fromJson(pageParamsJson, PageParamsDto.class);TableDataInfo tableDataInfo = brandService.pageList(brand,pageParamsDto);return tableDataInfo;}
當前端需要傳遞兩個參數還需要是get請求的時候,后端參數就是用字符串接收,然后使用Gson類進行解析?
前端部分接口:
// 查詢品牌列表
export function listBrand(brandParams,pageParams) {return request({url: '/product/brand/list',method: 'get',params: {brand: JSON.stringify(brandParams),pageParams: JSON.stringify(pageParams)}})
}
后端接口實現:
/*** 分頁并且模糊查詢獲取品牌列表** @param brand* @param pageParamsDto* @return*/@Overridepublic TableDataInfo pageList(Brand brand, PageParamsDto pageParamsDto) {LambdaQueryWrapper<Brand> wrapper = new LambdaQueryWrapper<>();wrapper.like(StringUtils.hasText(brand.getName()),Brand::getName,brand.getName());wrapper.eq(brand.getFirstLetter()!=null,Brand::getFirstLetter,brand.getFirstLetter());wrapper.eq(brand.getSort()!=null,Brand::getSort,brand.getSort());wrapper.eq(Brand::getShowStatus,1);wrapper.like(StringUtils.hasText(brand.getDescript()),Brand::getDescript,brand.getDescript());Page<Brand> page = new Page<>(pageParamsDto.getPageNum(),pageParamsDto.getPageSize());page(page,wrapper);return new TableDataInfo(page.getRecords(),page.getTotal());}
1.2?刪除需要注意關系也要刪除
接口:
/*** 刪除品牌*/@ApiOperation("刪除品牌")//@PreAuthorize("@ss.hasPermi('product:brand:remove')")@Log(title = "品牌", businessType = BusinessType.DELETE)@DeleteMapping("/{brandIds}")public AjaxResult remove(@PathVariable Long[] brandIds) {return toAjax(brandService.removeMore(Arrays.asList(brandIds)));}
實現:
@Override@Transactionalpublic boolean removeMore(List<Long> list) {boolean remove = removeByIds(list);AtomicBoolean flag = new AtomicBoolean(true);list.stream().forEach(item->{LambdaQueryWrapper<CategoryBrandRelation> wrapper = new LambdaQueryWrapper<CategoryBrandRelation>().eq(CategoryBrandRelation::getBrandId, item);if(categoryBrandRelationService.list(wrapper).size()!=0){boolean remove1 = categoryBrandRelationService.remove(wrapper);if (!remove1) {flag.set(false);}}});return remove&& flag.get();}
這里操作了多張表,加上@Transactional注解
注意這里是存在關系再去進行刪除,而非對每個都去刪除,當不存在的時候去刪除就是false,最終就會返回false了,就出錯了。
2. 關聯那邊的
2.1 查詢列表
很簡單,直接逆向的,因為不涉及分頁模糊
/*** 查詢品牌分類關聯列表*/
@ApiOperation("查詢品牌分類關聯列表")
//@PreAuthorize("@ss.hasPermi('product:relation:list')")
@GetMapping("/list")public TableDataInfo list(CategoryBrandRelation categoryBrandRelation) {startPage();List<CategoryBrandRelation> list = categoryBrandRelationService.list(new QueryWrapper<CategoryBrandRelation>(categoryBrandRelation));return getDataTable(list);}
2.2 新增
接口:
/*** 新增品牌分類關聯*/@ApiOperation("新增品牌分類關聯")//@PreAuthorize("@ss.hasPermi('product:relation:add')")@Log(title = "品牌分類關聯", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(@RequestBody CategoryBrandRelation categoryBrandRelation) {return categoryBrandRelationService.saveDetails(categoryBrandRelation);}
實現:
@Overridepublic AjaxResult saveDetails(CategoryBrandRelation categoryBrandRelation) {//先判斷當前的關聯關系是否已存在LambdaQueryWrapper<CategoryBrandRelation> wrapper = new LambdaQueryWrapper<>(categoryBrandRelation);CategoryBrandRelation relation = getOne(wrapper);if (relation != null) {return AjaxResult.error("當前分類關聯已存在");}Brand brand = brandService.getById(categoryBrandRelation.getBrandId());Category category = categoryService.getById(categoryBrandRelation.getCatelogId());categoryBrandRelation.setBrandName(brand.getName());categoryBrandRelation.setCatelogName(category.getName());boolean save = save(categoryBrandRelation);if (save) {return AjaxResult.success();}else{return AjaxResult.error();}}
這里要為兩個冗余字段附上值,以便查詢的時候不要多表去查,提高效率?
2.3 刪除
沒什么好說的,利用傳來的關聯id集合,直接使用MP的批量刪除就行了
/*** 刪除品牌分類關聯*/@ApiOperation("刪除品牌分類關聯")//@PreAuthorize("@ss.hasPermi('product:relation:remove')")@Log(title = "品牌分類關聯", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids) {return toAjax(categoryBrandRelationService.removeByIds(Arrays.asList(ids)));}
四、總結
前端就是引入那個分類關聯相關的東西,該導入的組件導好,該導入的方法導好,把數據域配好,方法修改好就行了
總結前端開發步驟:
1. 導入好組件相關的基本構件,就是那三部分
別的組件、方法等
2. 看數據域是否要增添
3. 看方法是否要修改
這里后端的話:
1. 要知道分頁模糊查詢,這是最基本的,知道配合若依開發
2. 要對增刪改接口有全局的意識,這點很重要,比如說增加的話,是不是需要額外的添加屬性
刪除的話,是不是還要刪其他表,修改的話是不是也要動其他表
3. 了解若依的返回邏輯,對于增刪改,若依是以toAjax()這種頂級封裝的方式進行返回的,按照布爾值,選擇是success還是error。而對于查詢,是以TableDataInfo對象返回的,我們可以根據自己的需要,也可以改變這種方式,在service實現中來返回request對象,這樣可以增加異常信息返回給前端。