diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Optimization.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Optimization.kt index 0d74442..1ddba99 100644 --- a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Optimization.kt +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/Optimization.kt @@ -8,16 +8,39 @@ import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.NONE interface Optimization { companion object { + fun listArgument(argument: Any): List { + if (argument !is List<*>) throw IllegalArgumentException("Argument must be a list") + return argument + .map { it as String } + .filter { it.isNotBlank() } + } + + fun mapArgument(argument: Any): Map { + if (argument !is Map<*, *>) throw IllegalArgumentException("Argument must be a map") + return argument + .map { (k, v) -> (k as String) to (v as String) } + .toMap() + } + fun process(root: JsonNode, optimizationMap: Map): List { - val text = root.get("text").asText() + val text = root + .get("text") + .asText() val nodes = root.get("optimizations") ?: emptyList() var lines = listOf(text) for (node in nodes) { - val type = node.get("type").asText() + val type = node + .get("type") + .asText() val optimization = optimizationMap[type] ?: throw IllegalArgumentException("Unknown optimization type: $type") lines = when (optimization.argumentType()) { NONE -> optimization.handle(lines, Unit) - LIST -> optimization.handle(lines, node.get("argument").map { it.asText() }) + LIST -> optimization.handle( + lines, + node + .get("argument") + .map { it.asText() }) + MAP -> optimization.handle(lines, node .get("argument") @@ -45,13 +68,13 @@ interface Optimization { class SliceOptimization() : Optimization { override fun key(): String = "slice-${argumentType()}" - override fun name(): String = "切分" + override fun name(): String = "正则切分" override fun handle(line: List, argument: Any): List { - val keys = argument as List + val keys = Optimization.listArgument(argument) var result = line for (key in keys) { - result = result.flatMap { it.split(key) } + result = result.flatMap { it.split(Regex(key)) } } return result } @@ -59,6 +82,19 @@ class SliceOptimization() : Optimization { override fun argumentType(): Optimization.ArgumentType = Optimization.ArgumentType.LIST } +class RemoveBlankLineOptimization : Optimization { + override fun key(): String = "remove-blank-${argumentType()}" + + override fun name(): String = "移除空白行" + + override fun handle(line: List, argument: Any): List { + return line.filter { it.isNotBlank() } + } + + override fun argumentType(): Optimization.ArgumentType = Optimization.ArgumentType.NONE + +} + abstract class AbstractOptimization(private val key: String, private val name: String) : Optimization { override fun key(): String = "${key}-${argumentType()}" override fun name(): String = name @@ -72,6 +108,24 @@ abstract class AbstractOptimization(private val key: String, private val name: S abstract fun handle(line: String, argument: Any): String } +class RemoveOptimization : AbstractOptimization("remove", "移除") { + override fun handle(line: String, argument: Any): String { + val words = Optimization.listArgument(argument) + return words.fold(line) { result, word -> result.replace(word, "") } + } + + override fun argumentType(): Optimization.ArgumentType = LIST +} + +class RegexRemoveOptimization : AbstractOptimization("regex-remove", "正则移除") { + override fun handle(line: String, argument: Any): String { + val words = Optimization.listArgument(argument) + return words.fold(line) { result, word -> result.replace(Regex(word), "") } + } + + override fun argumentType(): Optimization.ArgumentType = LIST +} + class TrimOptimization : AbstractOptimization("trim", "移除前后空白") { override fun handle(line: String, argument: Any): String { if (line.isBlank()) return line diff --git a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/OptimizationController.kt b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/OptimizationController.kt index 2d56a83..aedc2da 100644 --- a/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/OptimizationController.kt +++ b/src/main/kotlin/com/lanyuanxiaoyao/bookstore/controller/OptimizationController.kt @@ -5,11 +5,14 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import com.lanyuanxiaoyao.bookstore.CharWidthOptimization import com.lanyuanxiaoyao.bookstore.ListResponse +import com.lanyuanxiaoyao.bookstore.MapResponse import com.lanyuanxiaoyao.bookstore.Optimization import com.lanyuanxiaoyao.bookstore.OptimizationTemplate import com.lanyuanxiaoyao.bookstore.OptimizationTemplateRepository import com.lanyuanxiaoyao.bookstore.PageResponse -import com.lanyuanxiaoyao.bookstore.SingleResponse +import com.lanyuanxiaoyao.bookstore.RegexRemoveOptimization +import com.lanyuanxiaoyao.bookstore.RemoveBlankLineOptimization +import com.lanyuanxiaoyao.bookstore.RemoveOptimization import com.lanyuanxiaoyao.bookstore.SliceOptimization import com.lanyuanxiaoyao.bookstore.TrimOptimization import jakarta.transaction.Transactional @@ -35,7 +38,10 @@ class OptimizationController( private val mapper: ObjectMapper = builder.build() private val optimizations: List = listOf( SliceOptimization(), + RemoveBlankLineOptimization(), TrimOptimization(), + RemoveOptimization(), + RegexRemoveOptimization(), CharWidthOptimization(), ) private val optimizationMap: Map = optimizations.associateBy { it.key() } @@ -46,10 +52,16 @@ class OptimizationController( } @PostMapping("execute") - fun execute(@RequestBody json: String): SingleResponse { + fun execute(@RequestBody json: String): MapResponse { val root = mapper.readTree(json) val lines = Optimization.process(root, optimizationMap) - return SingleResponse(lines.joinToString("\n")) + log.info("处理后行数:{}", lines.size) + return MapResponse( + mapOf( + "item" to lines.joinToString("\n"), + "count" to lines.size, + ) + ) } @GetMapping("list") @@ -86,7 +98,9 @@ class OptimizationController( @GetMapping("detail/{templateId}") fun detail(@PathVariable("templateId") templateId: String): ViewItem { - val template = optimizationTemplateRepository.findById(templateId).orElseThrow() + val template = optimizationTemplateRepository + .findById(templateId) + .orElseThrow() return ViewItem( templateId = template.templateId, name = template.name, diff --git a/src/main/resources/static/components/optimization.js b/src/main/resources/static/components/optimization.js index 5e499e7..f90e50a 100644 --- a/src/main/resources/static/components/optimization.js +++ b/src/main/resources/static/components/optimization.js @@ -1,8 +1,7 @@ function optimizationTemplateForm() { return { - debug: true, + id: 'optimization-template-form', type: 'form', - name: 'optimization-template-form', ...horizontalFormOptions(), body: [ { @@ -86,16 +85,33 @@ function optimizationTemplateForm() { label: '优化预览', className: 'w-full mb-5', level: 'primary', - actionType: 'ajax', - api: { - method: 'post', - url: '${base}/optimization/execute', - data: { - text: '${text|default:undefined}', - optimizations: '${config|default:undefined}' + onEvent: { + click: { + actions: [ + { + actionType: 'ajax', + api: { + method: 'post', + url: '${base}/optimization/execute', + data: { + text: '${text|default:undefined}', + optimizations: '${config|default:undefined}', + }, + silent: true, + }, + }, + { + actionType: 'setValue', + componentId: 'optimization-template-form', + args: { + value: { + newText: '${event.data.responseResult.responseData.item}' + } + } + } + ] } - }, - reload: 'optimization-template-form?newText=${item}' + } }, { disabled: true, diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 511402e..a3daaeb 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -40,6 +40,147 @@