fix: 优化器执行预览后会刷新页面导致草稿丢失
This commit is contained in:
@@ -8,16 +8,39 @@ import com.lanyuanxiaoyao.bookstore.Optimization.ArgumentType.NONE
|
|||||||
|
|
||||||
interface Optimization {
|
interface Optimization {
|
||||||
companion object {
|
companion object {
|
||||||
|
fun listArgument(argument: Any): List<String> {
|
||||||
|
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<String, Any> {
|
||||||
|
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<String, Optimization>): List<String> {
|
fun process(root: JsonNode, optimizationMap: Map<String, Optimization>): List<String> {
|
||||||
val text = root.get("text").asText()
|
val text = root
|
||||||
|
.get("text")
|
||||||
|
.asText()
|
||||||
val nodes = root.get("optimizations") ?: emptyList()
|
val nodes = root.get("optimizations") ?: emptyList()
|
||||||
var lines = listOf(text)
|
var lines = listOf(text)
|
||||||
for (node in nodes) {
|
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")
|
val optimization = optimizationMap[type] ?: throw IllegalArgumentException("Unknown optimization type: $type")
|
||||||
lines = when (optimization.argumentType()) {
|
lines = when (optimization.argumentType()) {
|
||||||
NONE -> optimization.handle(lines, Unit)
|
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,
|
MAP -> optimization.handle(lines,
|
||||||
node
|
node
|
||||||
.get("argument")
|
.get("argument")
|
||||||
@@ -45,13 +68,13 @@ interface Optimization {
|
|||||||
class SliceOptimization() : Optimization {
|
class SliceOptimization() : Optimization {
|
||||||
override fun key(): String = "slice-${argumentType()}"
|
override fun key(): String = "slice-${argumentType()}"
|
||||||
|
|
||||||
override fun name(): String = "切分"
|
override fun name(): String = "正则切分"
|
||||||
|
|
||||||
override fun handle(line: List<String>, argument: Any): List<String> {
|
override fun handle(line: List<String>, argument: Any): List<String> {
|
||||||
val keys = argument as List<String>
|
val keys = Optimization.listArgument(argument)
|
||||||
var result = line
|
var result = line
|
||||||
for (key in keys) {
|
for (key in keys) {
|
||||||
result = result.flatMap { it.split(key) }
|
result = result.flatMap { it.split(Regex(key)) }
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -59,6 +82,19 @@ class SliceOptimization() : Optimization {
|
|||||||
override fun argumentType(): Optimization.ArgumentType = Optimization.ArgumentType.LIST
|
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<String>, argument: Any): List<String> {
|
||||||
|
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 {
|
abstract class AbstractOptimization(private val key: String, private val name: String) : Optimization {
|
||||||
override fun key(): String = "${key}-${argumentType()}"
|
override fun key(): String = "${key}-${argumentType()}"
|
||||||
override fun name(): String = name
|
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
|
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", "移除前后空白") {
|
class TrimOptimization : AbstractOptimization("trim", "移除前后空白") {
|
||||||
override fun handle(line: String, argument: Any): String {
|
override fun handle(line: String, argument: Any): String {
|
||||||
if (line.isBlank()) return line
|
if (line.isBlank()) return line
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import com.fasterxml.jackson.databind.JsonNode
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.lanyuanxiaoyao.bookstore.CharWidthOptimization
|
import com.lanyuanxiaoyao.bookstore.CharWidthOptimization
|
||||||
import com.lanyuanxiaoyao.bookstore.ListResponse
|
import com.lanyuanxiaoyao.bookstore.ListResponse
|
||||||
|
import com.lanyuanxiaoyao.bookstore.MapResponse
|
||||||
import com.lanyuanxiaoyao.bookstore.Optimization
|
import com.lanyuanxiaoyao.bookstore.Optimization
|
||||||
import com.lanyuanxiaoyao.bookstore.OptimizationTemplate
|
import com.lanyuanxiaoyao.bookstore.OptimizationTemplate
|
||||||
import com.lanyuanxiaoyao.bookstore.OptimizationTemplateRepository
|
import com.lanyuanxiaoyao.bookstore.OptimizationTemplateRepository
|
||||||
import com.lanyuanxiaoyao.bookstore.PageResponse
|
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.SliceOptimization
|
||||||
import com.lanyuanxiaoyao.bookstore.TrimOptimization
|
import com.lanyuanxiaoyao.bookstore.TrimOptimization
|
||||||
import jakarta.transaction.Transactional
|
import jakarta.transaction.Transactional
|
||||||
@@ -35,7 +38,10 @@ class OptimizationController(
|
|||||||
private val mapper: ObjectMapper = builder.build()
|
private val mapper: ObjectMapper = builder.build()
|
||||||
private val optimizations: List<Optimization> = listOf(
|
private val optimizations: List<Optimization> = listOf(
|
||||||
SliceOptimization(),
|
SliceOptimization(),
|
||||||
|
RemoveBlankLineOptimization(),
|
||||||
TrimOptimization(),
|
TrimOptimization(),
|
||||||
|
RemoveOptimization(),
|
||||||
|
RegexRemoveOptimization(),
|
||||||
CharWidthOptimization(),
|
CharWidthOptimization(),
|
||||||
)
|
)
|
||||||
private val optimizationMap: Map<String, Optimization> = optimizations.associateBy { it.key() }
|
private val optimizationMap: Map<String, Optimization> = optimizations.associateBy { it.key() }
|
||||||
@@ -46,10 +52,16 @@ class OptimizationController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("execute")
|
@PostMapping("execute")
|
||||||
fun execute(@RequestBody json: String): SingleResponse<String> {
|
fun execute(@RequestBody json: String): MapResponse {
|
||||||
val root = mapper.readTree(json)
|
val root = mapper.readTree(json)
|
||||||
val lines = Optimization.process(root, optimizationMap)
|
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")
|
@GetMapping("list")
|
||||||
@@ -86,7 +98,9 @@ class OptimizationController(
|
|||||||
|
|
||||||
@GetMapping("detail/{templateId}")
|
@GetMapping("detail/{templateId}")
|
||||||
fun detail(@PathVariable("templateId") templateId: String): ViewItem {
|
fun detail(@PathVariable("templateId") templateId: String): ViewItem {
|
||||||
val template = optimizationTemplateRepository.findById(templateId).orElseThrow()
|
val template = optimizationTemplateRepository
|
||||||
|
.findById(templateId)
|
||||||
|
.orElseThrow()
|
||||||
return ViewItem(
|
return ViewItem(
|
||||||
templateId = template.templateId,
|
templateId = template.templateId,
|
||||||
name = template.name,
|
name = template.name,
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
function optimizationTemplateForm() {
|
function optimizationTemplateForm() {
|
||||||
return {
|
return {
|
||||||
debug: true,
|
id: 'optimization-template-form',
|
||||||
type: 'form',
|
type: 'form',
|
||||||
name: 'optimization-template-form',
|
|
||||||
...horizontalFormOptions(),
|
...horizontalFormOptions(),
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
@@ -86,16 +85,33 @@ function optimizationTemplateForm() {
|
|||||||
label: '优化预览',
|
label: '优化预览',
|
||||||
className: 'w-full mb-5',
|
className: 'w-full mb-5',
|
||||||
level: 'primary',
|
level: 'primary',
|
||||||
actionType: 'ajax',
|
onEvent: {
|
||||||
api: {
|
click: {
|
||||||
method: 'post',
|
actions: [
|
||||||
url: '${base}/optimization/execute',
|
{
|
||||||
data: {
|
actionType: 'ajax',
|
||||||
text: '${text|default:undefined}',
|
api: {
|
||||||
optimizations: '${config|default:undefined}'
|
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,
|
disabled: true,
|
||||||
|
|||||||
@@ -40,6 +40,147 @@
|
|||||||
<script src="components/chapter.js"></script>
|
<script src="components/chapter.js"></script>
|
||||||
<script src="components/optimization.js"></script>
|
<script src="components/optimization.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
function bookTab() {
|
||||||
|
return {
|
||||||
|
title: '书架',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
id: 'book-list',
|
||||||
|
type: 'crud',
|
||||||
|
api: {
|
||||||
|
method: 'get',
|
||||||
|
url: '${base}/book/list',
|
||||||
|
data: {
|
||||||
|
page: '${page|default:1}',
|
||||||
|
size: '${size|default:10}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...crudCommonOptions(),
|
||||||
|
headerToolbar: [
|
||||||
|
'reload',
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
icon: 'fa fa-add',
|
||||||
|
...bookAddDialog(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
footerToolbar: [
|
||||||
|
paginationOption(),
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: '名称',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
fixed: 'right',
|
||||||
|
className: 'nowrap',
|
||||||
|
width: 100,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '跳转',
|
||||||
|
actionType: 'url',
|
||||||
|
url: '${source}',
|
||||||
|
blank: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '导出',
|
||||||
|
actionType: 'download',
|
||||||
|
api: '${base}/book/export/${bookId}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '编辑',
|
||||||
|
...bookDetailDialog(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '删除',
|
||||||
|
level: 'danger',
|
||||||
|
confirmTitle: '确认删除',
|
||||||
|
confirmText: '确认删除名称为「${name}」的书籍吗?',
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: 'get:${base}/book/remove/${bookId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function optimizationTab() {
|
||||||
|
return {
|
||||||
|
title: '优化',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'crud',
|
||||||
|
api: {
|
||||||
|
method: 'get',
|
||||||
|
url: '${base}/optimization/list',
|
||||||
|
data: {
|
||||||
|
page: '${page|default:1}',
|
||||||
|
size: '${size|default:10}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...crudCommonOptions(),
|
||||||
|
headerToolbar: [
|
||||||
|
'reload',
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
icon: 'fa fa-add',
|
||||||
|
...optimizationTemplateAddDialog(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: '名称',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
fixed: 'right',
|
||||||
|
className: 'nowrap',
|
||||||
|
width: 100,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '编辑',
|
||||||
|
...optimizationTemplateDetailDialog(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '删除',
|
||||||
|
level: 'danger',
|
||||||
|
confirmTitle: '确认删除',
|
||||||
|
confirmText: '确认删除名称为「${name}」的优化器模板吗?',
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: 'get:${base}/optimization/remove/${templateId}',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
let amis = amisRequire('amis/embed')
|
let amis = amisRequire('amis/embed')
|
||||||
let amisJSON = {
|
let amisJSON = {
|
||||||
@@ -49,141 +190,8 @@
|
|||||||
body: {
|
body: {
|
||||||
type: 'tabs',
|
type: 'tabs',
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
optimizationTab(),
|
||||||
title: '书架',
|
bookTab(),
|
||||||
body: [
|
|
||||||
{
|
|
||||||
id: 'book-list',
|
|
||||||
type: 'crud',
|
|
||||||
api: {
|
|
||||||
method: 'get',
|
|
||||||
url: '${base}/book/list',
|
|
||||||
data: {
|
|
||||||
page: '${page|default:1}',
|
|
||||||
size: '${size|default:10}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...crudCommonOptions(),
|
|
||||||
headerToolbar: [
|
|
||||||
'reload',
|
|
||||||
{
|
|
||||||
label: '',
|
|
||||||
icon: 'fa fa-add',
|
|
||||||
...bookAddDialog(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
footerToolbar: [
|
|
||||||
paginationOption(),
|
|
||||||
],
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
name: 'name',
|
|
||||||
label: '名称',
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'description',
|
|
||||||
label: '描述',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'operation',
|
|
||||||
label: '操作',
|
|
||||||
fixed: 'right',
|
|
||||||
className: 'nowrap',
|
|
||||||
width: 100,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '跳转',
|
|
||||||
actionType: 'url',
|
|
||||||
url: '${source}',
|
|
||||||
blank: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '导出',
|
|
||||||
actionType: 'download',
|
|
||||||
api: '${base}/book/export/${bookId}',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '编辑',
|
|
||||||
...bookDetailDialog(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '删除',
|
|
||||||
level: 'danger',
|
|
||||||
confirmTitle: '确认删除',
|
|
||||||
confirmText: '确认删除名称为「${name}」的书籍吗?',
|
|
||||||
actionType: 'ajax',
|
|
||||||
api: 'get:${base}/book/remove/${bookId}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '优化',
|
|
||||||
body: [
|
|
||||||
{
|
|
||||||
type: 'crud',
|
|
||||||
api: {
|
|
||||||
method: 'get',
|
|
||||||
url: '${base}/optimization/list',
|
|
||||||
data: {
|
|
||||||
page: '${page|default:1}',
|
|
||||||
size: '${size|default:10}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...crudCommonOptions(),
|
|
||||||
headerToolbar: [
|
|
||||||
'reload',
|
|
||||||
{
|
|
||||||
label: '',
|
|
||||||
icon: 'fa fa-add',
|
|
||||||
...optimizationTemplateAddDialog(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
name: 'name',
|
|
||||||
label: '名称',
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'description',
|
|
||||||
label: '描述',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'operation',
|
|
||||||
label: '操作',
|
|
||||||
fixed: 'right',
|
|
||||||
className: 'nowrap',
|
|
||||||
width: 100,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '编辑',
|
|
||||||
...optimizationTemplateDetailDialog(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'action',
|
|
||||||
label: '删除',
|
|
||||||
level: 'danger',
|
|
||||||
confirmTitle: '确认删除',
|
|
||||||
confirmText: '确认删除名称为「${name}」的优化器模板吗?',
|
|
||||||
actionType: 'ajax',
|
|
||||||
api: 'get:${base}/optimization/remove/${templateId}',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user