Merge branch 'dev' of https://git.yfgame.vip/r/hangtag into dev

This commit is contained in:
Mrking 2025-01-19 22:41:39 +08:00
commit b20d5916d3
16 changed files with 462 additions and 19 deletions

View File

@ -10,7 +10,7 @@ import java.io.Serializable;
public class FilterItem implements Serializable {
/**
* 类型 = > >= < <= != in notIn like likeLef likeRight keyword
* 类型 = > >= < <= != in notIn like likeLef likeRight handler
* {@link QueryFilterTypeEnum}
*/
private String type = QueryFilterTypeEnum.EQ.getValue();

View File

@ -0,0 +1,42 @@
package cn.hangtag.module.oms.base.controller.admin.keyword;
import cn.hangtag.framework.common.pojo.CommonResult;
import cn.hangtag.framework.common.util.FuncUtil;
import cn.hangtag.module.oms.base.controller.admin.keyword.handler.OmsKeywordUtil;
import cn.hangtag.module.oms.base.controller.admin.keyword.vo.KeywordResultVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
@Tag(name = "关键字获取")
@RestController
@RequestMapping("/oms/base/keyword")
@Validated
public class KeywordController {
/**
* 获取关键字列表
*
* @param type 类型 关键字的类型 BeanName
* @param count 计数 查询数量
* @param keyword 关键字 搜索关键字
* @param filter 滤波器 前置过滤
* @return {@link CommonResult }<{@link List }<{@link KeywordResultVO }>>
*/
@GetMapping("/list/{type}/{count}")
@Operation(summary = "获取关键字 ")
public CommonResult<List<KeywordResultVO>> getKeywordList(@PathVariable("type") String type,
@PathVariable("count") Long count,
@RequestParam(required = false) String keyword,
@RequestParam(required = false) String filter
) {
return success(OmsKeywordUtil.search(type, keyword, FuncUtil.tolong(count,10),filter));
}
}

View File

@ -0,0 +1,18 @@
package cn.hangtag.module.oms.base.controller.admin.keyword.handler;
import cn.hangtag.module.oms.base.controller.admin.keyword.vo.KeywordResultVO;
import java.util.List;
/**
* abs基础关键字搜索处理程序
*
* @author YuanFeng
* @date 2022/12/01
*/
public abstract class AbsBaseKeywordSearchHandler {
public abstract List<KeywordResultVO> search(String keyword, long maxCount,String filter);
}

View File

@ -0,0 +1,30 @@
package cn.hangtag.module.oms.base.controller.admin.keyword.handler;
import cn.hangtag.module.oms.util.SpringBeanUtil;
import cn.hangtag.module.oms.base.controller.admin.keyword.vo.KeywordResultVO;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class OmsKeywordUtil {
private static Map<String, AbsBaseKeywordSearchHandler> HANDLER_MAP = new HashMap<>();
public static void init(){
// 获取所有实现类
HANDLER_MAP = SpringBeanUtil.getBeanMap(AbsBaseKeywordSearchHandler.class);
}
private static AbsBaseKeywordSearchHandler getHandler(String type){
return HANDLER_MAP.get(type);
}
public static List<KeywordResultVO> search(String type, String keyword,long maxCount,String filter){
AbsBaseKeywordSearchHandler handler = getHandler(type);
if(handler == null){
return new ArrayList<>();
}
return handler.search(keyword,maxCount,filter);
}
}

View File

@ -0,0 +1,65 @@
package cn.hangtag.module.oms.base.controller.admin.keyword.handler.impl;
import cn.hangtag.framework.common.util.FuncUtil;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
import cn.hangtag.module.oms.base.controller.admin.keyword.vo.KeywordResultVO;
import cn.hangtag.module.oms.base.controller.admin.keyword.handler.AbsBaseKeywordSearchHandler;
import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO;
import cn.hangtag.module.oms.dal.mysql.productinfo.ProductInfoMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 关键字搜索处理器
*
* @author YuanFeng
* @date 2023/11/27
*/
@AllArgsConstructor
@Component
public class KeywordSearchHandler {
private final ProductInfoMapper productInfoMapper;
/**
* 产品信息 code 关键字搜索处理器
*
* @return {@link AbsBaseKeywordSearchHandler }<{@link Object }>
*/
@Bean("productInfoCode")
public AbsBaseKeywordSearchHandler productInfoCodeHandler() {
AbsBaseKeywordSearchHandler handler = new AbsBaseKeywordSearchHandler() {
@Override
public List<KeywordResultVO> search(String keyword, long maxCount,String filter) {
Page page = new Page();
page.setSize(maxCount);
LambdaQueryWrapper<ProductInfoDO> queryWrapper = new LambdaQueryWrapper<>();
if(FuncUtil.isNotEmpty(keyword)){
queryWrapper.like(ProductInfoDO::getCode, keyword);
}
if(FuncUtil.isNotEmpty(filter)){
queryWrapper.eq(ProductInfoDO::getBrandId, filter);
}
queryWrapper.eq(BaseDO::getDeleted,false);
queryWrapper.groupBy(ProductInfoDO::getCode);
Page<ProductInfoDO> page1 = productInfoMapper.selectPage(page, queryWrapper);
List<ProductInfoDO> records = page1.getRecords();
List<KeywordResultVO> res = new ArrayList<>();
for (ProductInfoDO record : records) {
res.add(new KeywordResultVO(record.getCode(), record.getCode()));
}
return res;
}
};
return handler;
}
}

View File

@ -0,0 +1,23 @@
package cn.hangtag.module.oms.base.controller.admin.keyword.vo;
import lombok.Data;
import java.io.Serializable;
/**
* 关键字结果vo
*
* @author YuanFeng
*/
@Data
public class KeywordResultVO implements Serializable {
private String value;
private String label;
private Object data;
public KeywordResultVO(String value, String label) {
this.value = value;
this.label = label;
}
}

View File

@ -25,7 +25,7 @@ public interface ProductInfoMapper extends BaseMapperX<ProductInfoDO> {
default PageResult<ProductInfoDO> selectPage(ProductInfoPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ProductInfoDO>()
.eqIfPresent(ProductInfoDO::getCode, reqVO.getCode())
.likeIfPresent(ProductInfoDO::getCode, reqVO.getCode())
.likeIfPresent(ProductInfoDO::getName, reqVO.getName())
.eqIfPresent(ProductInfoDO::getCover, reqVO.getCover())
.eqIfPresent(ProductInfoDO::getBrandId, reqVO.getBrandId())

View File

@ -0,0 +1,61 @@
package cn.hangtag.module.oms.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
public class SpringBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringBeanUtil.applicationContext == null) {
SpringBeanUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
public static <T> List<T> getBeanList(Class<T> clazz){
Map<String, T> beansOfType = getBeanMap(clazz);
Set<String> keySet = beansOfType.keySet();
List<T> list = new ArrayList<>();
for (String s : keySet) {
list.add(beansOfType.get(s));
}
return list;
}
public static <T> Map<String, T> getBeanMap(Class<T> clazz){
return getApplicationContext().getBeansOfType(clazz);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过class获取所有Bean.
public static <T> Map<String, T> getBeansOfType(Class<T> clazz){
return getApplicationContext().getBeansOfType(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}

View File

@ -1,5 +1,6 @@
package cn.hangtag.server;
import cn.hangtag.module.oms.base.controller.admin.keyword.handler.OmsKeywordUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -15,7 +16,7 @@ public class HangtagServerApplication {
// new SpringApplicationBuilder(HangtagServerApplication.class)
// .applicationStartup(new BufferingApplicationStartup(20480))
// .run(args);
OmsKeywordUtil.init();
}

View File

@ -562,7 +562,8 @@ export default {
"tipsUseProportion": "The total proportion cannot exceed 100. The actual value is",
"tipsUseProportion2": "The desired proportion is 100%, but the actual value is",
"tipsDuplicate": "Duplicate",
"tipsDataTransmitting": "Data transmitting..."
"tipsDataTransmitting": "Data transmitting...",
"tipsDataChange": "DataChange Click Update Button",
},
"createOrder": {
"title1": "Order Information",
@ -669,7 +670,6 @@ export default {
"labelRemark": "Remark",
"viewOrder": "viewOrder",
"backHome": "BackHome",
"tipsDataChange": "DataChange Click Update Button",
"downloadSuccess": "downloadSuccess",
},
"productDialogList": {

View File

@ -558,6 +558,7 @@ export default {
tipsUseProportion2: '中占比希望是100%,实际是',
tipsDuplicate: '重复',
tipsDataTransmitting: '数据传输中...',
tipsDataChange: "数据已更新,请点击更新按钮",
},
createOrder: {
title1: '订单信息',
@ -665,7 +666,6 @@ export default {
placeRemark: "请输入备注",
viewOrder: "查看订单",
backHome: "返回首页",
tipsDataChange: "数据已更新,请点击更新按钮",
downloadSuccess: "下载成功",
},
productDialogList:{

View File

@ -0,0 +1,18 @@
import request from '@/config/axios'
// 关键字 API
export const KeywordApi = {
// 查询关键字列表
list: async (filter: string, type: string, keyword: string, maxCount = 10) => {
return await request.get({
url: `/oms/base/keyword/list/${type}/${maxCount}`,
params: {
filter: filter,
keyword: keyword,
}
})
},
}

View File

@ -0,0 +1,173 @@
<template>
<el-autocomplete
v-model="inputValue"
:fetch-suggestions="querySearch"
@change="changeInput"
clearable
v-bind="attr"
>
<template #default="{item}">
<div>
<span v-html="toHighlightText(item.value,inputValue)"></span>
</div>
</template>
</el-autocomplete>
</template>
<script lang="ts" setup name="KeywordSearch">
//@ts-nocheck
import {KeywordApi} from "@/api/base/keyword";
import {computed} from "vue";
/** 稿件图片库 */
defineOptions({name: 'ProductInfoList'})
const emit = defineEmits(['update:modelValue', 'update:visible', 'submit']) // success
const {t} = useI18n() //
const $attrs = useAttrs();
const props = defineProps({
modelValue: {
type: [String],
required: true
},
type: {
type: String,
default: 'productInfoCode'
},
count: {
type: Number,
default: 15
},
filter: { //
type: [Object,String] ,
default: () => ""
}
})
const attr = computed(() => {
return {
placeholder: t("common.keywordPlaceholder"),
width: '100%',
...$attrs
}
})
const changeInput = (val) => {
emit('update:modelValue', val)
}
const inputValue = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
}
})
const that = reactive({
codeKeywordList: [],
})
const keys = [];
const querySearch = (queryString: string, cb: any) => {
let results = getResult(queryString);
if (!results || results.length === 0) {
console.log(444)
//
getList(queryString, props.count).then(res => {
results = getResult(queryString);
cb(results)
});
} else {
console.log("results", results)
cb(results)
}
}
const getResult = (queryString) => {
return queryString
? that.codeKeywordList.filter((item) => {
return `${item.value}`.toUpperCase().indexOf(queryString.toUpperCase()) != -1
})
: that.codeKeywordList
}
let preFilter = computed(()=>{
if(props.filter && typeof props.filter === 'object'){
return JSON.stringify(props.filter)
}
return props.filter || ""
})
const getList = (queryString: string, count: number) => {
return new Promise((resolve, reject) => {
KeywordApi.list(preFilter.value,props.type, queryString, count).then(res => {
if (res.length > 0) {
for (let i = 0; i < res.length; i++) {
const item = res[i];
if (!keys.includes(item.value)) {
keys.push(item.value);
that.codeKeywordList.push({
value: item.value,
label: item.label,
})
}
}
resolve(that.codeKeywordList);
} else {
resolve(that.codeKeywordList);
}
}).catch((err) => {
reject(err);
})
})
}
const toHighlightText = (originalText: string, keyword: string) => {
if (originalText && keyword) {
const keyArray = parseKeywordList(keyword)
if (keyArray.length > 0) {
const arr = originalText.split("")
let highlightedText = ""
arr.forEach(s => {
// @ts-ignore
if (s && keyArray.includes(s.toUpperCase())) {
highlightedText += `<span style="color: #ff0000">${s}</span>`
} else {
highlightedText += `${s}`;
}
})
// HTML
return highlightedText;
}
}
return originalText;
}
const parseKeywordList = (keyword: string): [] => {
//@ts-ignore
const arr = []
if (keyword) {
//
keyword = keyword.replace(/\s/g, '')
const strings = keyword.toUpperCase().split('')
strings.forEach(s => {
//@ts-ignore
if (!arr.includes(s)) {
arr.push(s)
}
})
}
//@ts-ignore
return arr
}
/** 初始化 **/
onMounted(() => {
getList("", props.count * 2)
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -26,6 +26,14 @@
</el-select>
</div>
</template>
<template #code="{data}">
<div>
<KeywordSearch v-model="data.code"
:type="'productInfoCode'"
:filter="that.queryInfo.brandId"
:count="15"/>
</div>
</template>
</Search>
</ContentWrap>
@ -78,6 +86,7 @@ import {allSchemas} from './config.data'
import {ProductInfoApi} from '@/api/oms/productinfo'
import DataForm from './DataForm.vue'
import {ProductTypeApi} from "@/api/base/producttype";
import {KeywordApi} from "@/api/base/keyword";
/** 稿件图片库 */
defineOptions({name: 'ProductInfoList'})
@ -134,10 +143,18 @@ const that = reactive({
showValue: '',
visible: false,
keyword: '',
codeKeywordList: [
{
value: 'abc',
label: '请选择'
}
],
typeList: [],
selectRow: [],
queryInfo: {
productTypeId: null,
code: '',
brandId:'',
}
})
@ -147,6 +164,7 @@ const getLabel = (id) => {
const res = that.typeList.find(item => item.id === id);
return res ? res.label : id
}
const openDialog = (filter = {}) => {
that.queryInfo = {
...that.queryInfo,
@ -248,14 +266,6 @@ const {getList, setSearchParams} = tableMethods
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = (id: number) => {
tableMethods.delList(id, false)
}
/** 初始化 **/
onMounted(() => {

View File

@ -54,7 +54,8 @@ export default {
updateTime: 'Update Time',
copy: 'Copy',
copySuccess: 'Copy Success',
copyError: 'Copy Error'
copyError: 'Copy Error',
keywordPlaceholder: 'Please enter a keyword'
},
lock: {
lockScreen: 'Lock screen',
@ -563,7 +564,8 @@ export default {
"tipsUseProportion": "The total proportion cannot exceed 100. The actual value is",
"tipsUseProportion2": "The desired proportion is 100%, but the actual value is",
"tipsDuplicate": "Duplicate",
"tipsDataTransmitting": "Data transmitting..."
"tipsDataTransmitting": "Data transmitting...",
"tipsDataChange": "DataChange Click Update Button",
},
"createOrder": {
"title1": "Order Information",
@ -670,7 +672,6 @@ export default {
"labelRemark": "Remark",
"viewOrder": "viewOrder",
"backHome": "BackHome",
"tipsDataChange": "DataChange Click Update Button",
"downloadSuccess": "downloadSuccess",
},

View File

@ -54,7 +54,8 @@ export default {
updateTime: '更新时间',
copy: '复制',
copySuccess: '复制成功',
copyError: '复制失败'
copyError: '复制失败',
keywordPlaceholder: '请输入关键字'
},
lock: {
lockScreen: '锁定屏幕',
@ -559,6 +560,7 @@ export default {
tipsUseProportion2: '中占比希望是100%,实际是',
tipsDuplicate: '重复',
tipsDataTransmitting: '数据传输中...',
tipsDataChange: "数据已更新,请点击更新按钮",
},
createOrder: {
title1: '订单信息',
@ -666,7 +668,6 @@ export default {
placeRemark: "请输入备注",
viewOrder: "查看订单",
backHome: "返回首页",
tipsDataChange: "数据已更新,请点击更新按钮",
downloadSuccess: "下载成功",
},
productDialogList:{