Commit 8e774fc8 authored by tyyin lan's avatar tyyin lan

chore: 编辑器优化指令功能完善

parent ad43b680
<script setup lang="ts"> <script setup lang="ts">
import { ref, watchEffect } from 'vue' import { h, ref, shallowRef, useTemplateRef, watch, watchEffect } from 'vue'
import fetchEventStreamSource from './utils/fetch-event-stream-source' import fetchEventStreamSource from './utils/fetch-event-stream-source'
import type { ResponseData } from './utils/fetch-event-stream-source'
import type { Editor } from 'tinymce' import type { Editor } from 'tinymce'
import type { DropdownGroupOption, DropdownOption, NDropdown } from 'naive-ui'
import type { VNode } from 'vue'
import { useI18n } from 'vue-i18n'
interface Props { interface Props {
editor: Editor | null editor: Editor | null
...@@ -13,14 +17,53 @@ const props = defineProps<Props>() ...@@ -13,14 +17,53 @@ const props = defineProps<Props>()
const isShowModal = defineModel<boolean>('isShowModal', { required: true }) const isShowModal = defineModel<boolean>('isShowModal', { required: true })
const toneSelectRef = useTemplateRef<InstanceType<typeof NDropdown>>('toneSelectRef')
const { t } = useI18n()
const containerWrapperStyle = ref<{ top?: string; bottom?: string }>({}) const containerWrapperStyle = ref<{ top?: string; bottom?: string }>({})
const questionContent = ref('') const questionContent = ref('')
const isShowResponseContentEditModal = ref(false) const contentEditStatus = ref<'Normal' | 'Editing' | 'Response'>('Normal')
const isShowEditSelectToolbar = ref(true)
const isShowReplaceToolbar = ref(false) const isShowReplaceToolbar = ref(false)
const editResponseContent = ref('') const editResponseContent = ref('')
const editResponseLoading = ref(false) const editResponseLoading = ref(false)
const controller = shallowRef<AbortController | null>(null)
const toneList = ref([
{ key: 'Colloquial', label: t('editor_module.colloquial') },
{ key: 'Academicization', label: t('editor_module.academicization') },
{ key: 'HumorousAndVivid', label: t('editor_module.humorous_and_vivid') },
{ key: 'SeriousAndFormal', label: t('editor_module.serious_and_formal') },
{ key: 'ConciseAndClear', label: t('editor_module.concise_and_clear') },
{ key: 'ElegantLiteraryStyle', label: t('editor_module.elegant_literary_style') },
])
watch(
() => isShowModal.value,
(newValue) => {
if (newValue) {
contentEditStatus.value = 'Editing'
} else {
contentEditStatus.value = 'Normal'
questionContent.value = ''
if (controller.value) {
controller.value.abort()
controller.value = null
}
}
},
)
watch(questionContent, (newValue) => {
if (newValue) {
isShowEditSelectToolbar.value = false
} else {
isShowEditSelectToolbar.value = true
}
})
watchEffect(() => { watchEffect(() => {
if (props.isSetBottom) { if (props.isSetBottom) {
containerWrapperStyle.value = { bottom: `${props.location}px`, top: 'unset' } containerWrapperStyle.value = { bottom: `${props.location}px`, top: 'unset' }
...@@ -29,33 +72,30 @@ watchEffect(() => { ...@@ -29,33 +72,30 @@ watchEffect(() => {
} }
}) })
function handleQuestionSubmitEnter(event: KeyboardEvent) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault()
}
}
function editResponseStatusReset() { function editResponseStatusReset() {
isShowModal.value = false
editResponseContent.value = '' editResponseContent.value = ''
isShowResponseContentEditModal.value = true
editResponseLoading.value = true editResponseLoading.value = true
isShowReplaceToolbar.value = false isShowReplaceToolbar.value = false
contentEditStatus.value = 'Response'
} }
function handleRetouching() { function fetchContentOptimize(url: string, questionContentStr: string = '') {
const selectContent = props.editor?.selection.getContent() const selectContent = props.editor?.selection.getContent()
editResponseStatusReset() editResponseStatusReset()
fetchEventStreamSource( controller.value = fetchEventStreamSource(
'/aiGcRest/articlePolish.json', url,
{ {
articleContent: selectContent || '', articleContent: selectContent || '',
editorRequired: questionContent.value || '', editorRequired: questionContentStr || '',
}, },
{ {
onResponse: (res) => { onopen: async () => {
questionContent.value = ''
},
onResponse: (res: ResponseData) => {
editResponseContent.value += res.message editResponseContent.value += res.message
}, },
onend: () => { onend: () => {
...@@ -65,18 +105,94 @@ function handleRetouching() { ...@@ -65,18 +105,94 @@ function handleRetouching() {
}, },
) )
} }
function handleQuestionSubmitEnter(event: KeyboardEvent) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault()
fetchContentOptimize('/aiGcRest/articleRewrite.json', questionContent.value)
}
}
function handleRetouching() {
// 润色
fetchContentOptimize('/aiGcRest/articlePolish.json', questionContent.value)
}
function handleExpansion() {
// 扩写
fetchContentOptimize('/aiGcRest/articleExpand.json', questionContent.value)
}
function handleAbbreviation() {
// 缩写
fetchContentOptimize('/aiGcRest/articleRefine.json', questionContent.value)
}
function handleReplaceContent() {
if (props.editor) {
props.editor.selection.setContent(editResponseContent.value)
contentEditStatus.value = 'Normal'
}
}
function handleInsertContent() {
const editor = props.editor
if (editor) {
editor.selection.collapse()
editor.execCommand('mceInsertNewLine')
editor.execCommand('InsertHTML', false, editResponseContent.value)
editor.execCommand('mceInsertNewLine')
contentEditStatus.value = 'Normal'
}
}
function handleEditResponseBreak() {
contentEditStatus.value = 'Editing'
questionContent.value = ''
if (controller.value) {
controller.value.abort()
controller.value = null
}
}
function handleToneSelect(_key: string, option: DropdownOption) {
fetchContentOptimize('/aiGcRest/articleModifyTone.json', option.label as string)
}
function toneSelectMenuRenderOption({ node, option }: { node: VNode; option: DropdownOption | DropdownGroupOption }) {
return h(
'li',
{
class:
'list-none select-none flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]',
onClick: () => {
if (node.children && Array.isArray(node.children) && node.children[0] && (node.children[0] as VNode).props) {
;(node.children[0] as VNode).props?.onClick()
}
},
},
[
h('i', { class: 'iconfont icon-adjust-tone text-[16px] text-[#9ea3ff]' }, ''),
h('span', { class: 'pl-[10px] text-[14px]' }, option.label as string),
],
)
}
</script> </script>
<template> <template>
<Transition mode="out-in"> <Transition mode="out-in">
<div v-if="isShowModal" class="absolute top-0 w-full px-[16px]" :style="containerWrapperStyle"> <div v-if="contentEditStatus === 'Editing'" class="absolute top-0 w-full px-[16px]" :style="containerWrapperStyle">
<div class="relative rounded-[6px] bg-white py-[10px]"> <div class="relative rounded-[6px] bg-white py-[10px]">
<n-input <n-input
v-model:value="questionContent" v-model:value="questionContent"
size="large" size="large"
type="textarea" type="textarea"
placeholder="请输入优化文本的指令" :placeholder="t('editor_module.optimize_input_placeholder')"
:autosize="{ minRows: 1, maxRows: 3 }" :autosize="{ minRows: 1, maxRows: 3 }"
:allow-input="(value: string) => !value.startsWith(' ') && !value.endsWith(' ')"
@keydown="handleQuestionSubmitEnter" @keydown="handleQuestionSubmitEnter"
> >
<template #prefix> <template #prefix>
...@@ -84,43 +200,64 @@ function handleRetouching() { ...@@ -84,43 +200,64 @@ function handleRetouching() {
</template> </template>
<template #suffix> <template #suffix>
<i class="iconfont icon-fasong text-[#d0ceff]"></i> <i
class="iconfont icon-fasong text-[#d0ceff] transition"
:class="{ 'text-theme-color': questionContent }"
></i>
</template> </template>
</n-input> </n-input>
<ul <Transition>
class="absolute w-[142px] select-none overflow-hidden rounded-[5px] border border-[#9EA3FF] bg-white" <ul
:class="isSetBottom ? 'top-[6px] -translate-y-full' : 'bottom-[6px] translate-y-full'" v-show="isShowEditSelectToolbar"
> class="absolute w-[142px] select-none overflow-hidden rounded-[5px] border border-[#9EA3FF] bg-white shadow-md"
<li :class="isSetBottom ? 'top-[6px] -translate-y-full' : 'bottom-[6px] translate-y-full'"
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
@click="handleRetouching"
>
<i class="iconfont icon-retouching text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">润色</span>
</li>
<li
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
>
<i class="iconfont icon-expansion text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">扩写</span>
</li>
<li
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
>
<i class="iconfont icon-suoxie text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">缩写</span>
</li>
<li
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
> >
<i class="iconfont icon-adjust-tone text-[16px] text-[#9ea3ff]"></i> <li
<span class="pl-[10px] text-[14px]">调整语气</span> class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
</li> @click="handleRetouching"
</ul> >
<i class="iconfont icon-retouching text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">{{ t('editor_module.retouching') }}</span>
</li>
<li
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
@click="handleExpansion"
>
<i class="iconfont icon-expansion text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">{{ t('editor_module.expansion') }}</span>
</li>
<li
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
@click="handleAbbreviation"
>
<i class="iconfont icon-suoxie text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">{{ t('editor_module.abbreviation') }}</span>
</li>
<n-dropdown
ref="toneSelectRef"
width="142"
trigger="hover"
class="!ml-[2px] overflow-hidden border border-[#9EA3FF] bg-white !p-0 !shadow-md"
content-style="padding: 0;"
:options="toneList"
placement="right-start"
:render-option="toneSelectMenuRenderOption"
@select="handleToneSelect"
>
<li
class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
>
<i class="iconfont icon-adjust-tone text-[16px] text-[#9ea3ff]"></i>
<span class="pl-[10px] text-[14px]">{{ t('editor_module.adjust_the_tone') }}</span>
</li>
</n-dropdown>
</ul>
</Transition>
</div> </div>
</div> </div>
<div v-else-if="isShowResponseContentEditModal" class="absolute top-1/2 w-full -translate-y-1/2 px-[16px]"> <div v-else-if="contentEditStatus === 'Response'" class="absolute top-1/2 w-full -translate-y-1/2 px-[16px]">
<div class="rounded-[5px] border border-[#9EA3FF] bg-white px-[10px] py-[14px]"> <div class="rounded-[5px] border border-[#9EA3FF] bg-white px-[10px] py-[14px]">
<div class="text-[14px] leading-[18px]"> <div class="text-[14px] leading-[18px]">
{{ editResponseContent }} {{ editResponseContent }}
...@@ -128,14 +265,16 @@ function handleRetouching() { ...@@ -128,14 +265,16 @@ function handleRetouching() {
<Transition> <Transition>
<div v-show="editResponseLoading" class="flex select-none items-center justify-between"> <div v-show="editResponseLoading" class="flex select-none items-center justify-between">
<span v-show="!editResponseContent">生成中...</span> <span>
<i class="iconfont icon-zanting cursor-pointer text-[18px]"></i> <template v-if="!editResponseContent">生成中...</template>
</span>
<i class="iconfont icon-zanting cursor-pointer text-[18px]" @click="handleEditResponseBreak"></i>
</div> </div>
</Transition> </Transition>
<Transition> <Transition>
<div v-show="isShowReplaceToolbar" class="mt-[9px]"> <div v-show="isShowReplaceToolbar" class="mt-[9px]">
<n-button type="primary" size="small" <n-button type="primary" size="small" @click="handleReplaceContent"
>替换 >替换
<template #icon> <template #icon>
...@@ -143,7 +282,7 @@ function handleRetouching() { ...@@ -143,7 +282,7 @@ function handleRetouching() {
</template> </template>
</n-button> </n-button>
<n-button class="!ml-[17px]" size="small" <n-button class="!ml-[17px]" size="small" @click="handleInsertContent"
>插入 >插入
<template #icon> <template #icon>
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import { computed, nextTick, onMounted, ref, shallowRef, useTemplateRef, watch } from 'vue' import { computed, nextTick, onMounted, ref, shallowRef, useTemplateRef, watch } from 'vue'
import { createEditorConfig } from './config/editor-config' import { createEditorConfig } from './config/editor-config'
import EditorToolbar from './editor-toolbar.vue' import EditorToolbar from './editor-toolbar.vue'
import { markdownTransformHtml } from '@/utils/markdown-parse'
import { downloadFile } from '@/utils/download-file' import { downloadFile } from '@/utils/download-file'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { fetchExportFile } from '@/apis/file' import { fetchExportFile } from '@/apis/file'
...@@ -36,19 +35,13 @@ const { t } = useI18n() ...@@ -36,19 +35,13 @@ const { t } = useI18n()
const editorWrapperRef = useTemplateRef('editorWrapperRef') const editorWrapperRef = useTemplateRef('editorWrapperRef')
const { height: editorWrapperRefHeight } = useElementSize(editorWrapperRef) const { height: editorWrapperRefHeight } = useElementSize(editorWrapperRef)
let controller: AbortController | null = null
const editorConfig = createEditorConfig() const editorConfig = createEditorConfig()
const editor = shallowRef<Editor | null>(null) const editor = shallowRef<Editor | null>(null)
const isShowEditor = ref(false) const isShowEditor = ref(false)
const articleContentModifyContainerShow = ref(false) const articleContentModifyContainerShow = ref(false)
const articleContentModifyState = ref<'selection' | 'loading' | 'generating' | 'done'>('selection')
const articleContentModifyResponseText = ref('')
const articleContentModifyResponseTextResource = ref('')
// const contentOptimizationEditContainerTop = ref(300)
const contentOptimizationEditContainerIsSetBottom = ref(false) const contentOptimizationEditContainerIsSetBottom = ref(false)
const contentOptimizationEditContainerLocation = ref(0) const contentOptimizationEditContainerLocation = ref(0)
...@@ -61,15 +54,6 @@ const editorContent = computed({ ...@@ -61,15 +54,6 @@ const editorContent = computed({
}, },
}) })
// const editorTitleText = ref('')
watch(articleContentModifyResponseTextResource, (newVal) => {
if (newVal && editor.value)
articleContentModifyResponseText.value = markdownTransformHtml(
editor.value.dom ? editor.value.dom.decode(newVal) : newVal,
) as string
})
watch( watch(
() => props.content, () => props.content,
(val: string, prevVal: string) => { (val: string, prevVal: string) => {
...@@ -121,15 +105,7 @@ onMounted(() => { ...@@ -121,15 +105,7 @@ onMounted(() => {
if (e.button !== 0) return if (e.button !== 0) return
if (articleContentModifyContainerShow.value) { if (articleContentModifyContainerShow.value) {
if (controller) {
controller.abort()
controller = null
}
articleContentModifyContainerShow.value = false articleContentModifyContainerShow.value = false
articleContentModifyResponseText.value = ''
articleContentModifyResponseTextResource.value = ''
articleContentModifyState.value = 'selection'
} }
editorInstance.selection.collapse() editorInstance.selection.collapse()
...@@ -146,8 +122,6 @@ onMounted(() => { ...@@ -146,8 +122,6 @@ onMounted(() => {
const rects = rng.getClientRects() const rects = rng.getClientRects()
const lastRect = rects[rects.length - 1] const lastRect = rects[rects.length - 1]
// const locationEl = rng.endContainer.parentElement
if (lastRect) { if (lastRect) {
/* 其中 46 是当前编辑器文档HTMl距离 外部挂载容器之间产生的高度 */ /* 其中 46 是当前编辑器文档HTMl距离 外部挂载容器之间产生的高度 */
const locationHeight = lastRect.bottom + 46 + 10 const locationHeight = lastRect.bottom + 46 + 10
...@@ -166,8 +140,12 @@ onMounted(() => { ...@@ -166,8 +140,12 @@ onMounted(() => {
} }
}) })
editorInstance.on('keydown', () => { editorInstance.on('keyup', () => {
// if (articleContentModifyContainerShow.value) articleContentModifyContainerShow.value = false const selectionContent = editorInstance.selection.getContent()
if (!selectionContent && articleContentModifyContainerShow.value) {
articleContentModifyContainerShow.value = false
}
}) })
}, },
}) })
......
...@@ -4,13 +4,14 @@ import { useUserStore } from '@/store/modules/user' ...@@ -4,13 +4,14 @@ import { useUserStore } from '@/store/modules/user'
import { languageKeyTransform } from '@/utils/language-key-transform' import { languageKeyTransform } from '@/utils/language-key-transform'
import { fetchEventSource } from '@microsoft/fetch-event-source' import { fetchEventSource } from '@microsoft/fetch-event-source'
interface ResponseData { export interface ResponseData {
message: string message: string
reasoningContent: string reasoningContent: string
function: { name: string } function: { name: string }
} }
interface Options { interface Options {
onopen?: (response?: Response) => Promise<void>
onResponse?: (data: ResponseData) => void onResponse?: (data: ResponseData) => void
onend?: () => void onend?: () => void
onclose?: () => void onclose?: () => void
...@@ -21,6 +22,7 @@ export default function fetchEventStreamSource( ...@@ -21,6 +22,7 @@ export default function fetchEventStreamSource(
url: string, url: string,
payload: object = {}, payload: object = {},
options: Options = { options: Options = {
onopen: async (_response) => {},
onResponse: (_data: ResponseData) => {}, onResponse: (_data: ResponseData) => {},
onend: () => {}, onend: () => {},
onclose: () => {}, onclose: () => {},
...@@ -43,6 +45,9 @@ export default function fetchEventStreamSource( ...@@ -43,6 +45,9 @@ export default function fetchEventStreamSource(
body: JSON.stringify(payload), body: JSON.stringify(payload),
signal: controller?.signal, signal: controller?.signal,
onopen: async (response) => {
return options.onopen && options.onopen(response)
},
onmessage: (e: { data: string }) => { onmessage: (e: { data: string }) => {
if (e.data === '[DONE]') { if (e.data === '[DONE]') {
options.onend && options.onend() options.onend && options.onend()
......
...@@ -3,22 +3,17 @@ import CustomEditor from '@/components/custom-editor/custom-editor.vue' ...@@ -3,22 +3,17 @@ import CustomEditor from '@/components/custom-editor/custom-editor.vue'
const contentEdit = defineModel<string>('contentEdit', { required: true }) const contentEdit = defineModel<string>('contentEdit', { required: true })
const isShowEditorDrawerDraft = true
const contentEditDraft = `<h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h4>济南的冬天,是一幅独特的画卷。它不同于北方的严寒,也不同于南方的温润。这里的冬天,有着独特的魅力和风情。济南的冬日,天空湛蓝,阳光明媚,尽管寒风凛冽,但总能带给人一份宁静和温馨。济南的泉水在冬天依然潺潺流淌,为这座城市增添了一份生机和活力。济南的冬日,不仅是季节的更迭,更是一种生活的体验,一种对大自然的敬畏和感慨。</h4><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h1>标题</h1><h4>济南的冬天,是一幅独特的画卷。它不同于北方的严寒,也不同于南方的温润。这里的冬天,有着独特的魅力和风情。济南的冬日,天空湛蓝,阳光明媚,尽管寒风凛冽,但总能带给人一份宁静和温馨。济南的泉水在冬天依然潺潺流淌,为这座城市增添了一份生机和活力。济南的冬日,不仅是季节的更迭,更是一种生活的体验,一种对大自然的敬畏和感慨。</h4><h1>标题</h1><h1>标题</h1>`
const isShowEditorDrawer = defineModel<boolean>('isShowEditorDrawer', { required: true }) const isShowEditorDrawer = defineModel<boolean>('isShowEditorDrawer', { required: true })
console.log(isShowEditorDrawer)
function onDrawerAfterLeave() { function onDrawerAfterLeave() {
contentEdit.value = '' contentEdit.value = ''
} }
</script> </script>
<template> <template>
<n-drawer v-model:show="isShowEditorDrawerDraft" :width="800" placement="right" :on-after-leave="onDrawerAfterLeave"> <n-drawer v-model:show="isShowEditorDrawer" :width="800" placement="right" :on-after-leave="onDrawerAfterLeave">
<n-drawer-content> <n-drawer-content>
<CustomEditor :content="contentEditDraft" /> <CustomEditor :content="contentEdit" />
</n-drawer-content> </n-drawer-content>
</n-drawer> </n-drawer>
</template> </template>
export const BASE_URLS: Record<'DEV' | 'PROD', string> = { export const BASE_URLS: Record<'DEV' | 'PROD', string> = {
// DEV: 'https://poc-sit.gsstcloud.com', DEV: 'https://poc-sit.gsstcloud.com',
DEV: 'http://localhost:8848', // DEV: 'http://localhost:8848',
PROD: 'https://model-link.gsstcloud.com', PROD: 'https://model-link.gsstcloud.com',
} }
......
...@@ -799,3 +799,16 @@ editor_module: ...@@ -799,3 +799,16 @@ editor_module:
center_align: 'Center align' center_align: 'Center align'
justify_right: 'Justify right' justify_right: 'Justify right'
align_both_ends: 'Align both ends' align_both_ends: 'Align both ends'
optimize_input_placeholder: 'Please enter the instructions for optimizing the text'
retouching: 'Retouching'
expansion: 'Expansion'
abbreviation: 'Abbreviation'
adjust_the_tone: 'Adjust the tone'
colloquial: 'Colloquial'
academicization: 'Academicization'
humorous_and_vivid: 'Humorous and vivid'
serious_and_formal: 'Serious and formal'
concise_and_clear: 'Concise and clear'
elegant_literary_style: 'Elegant literary style'
...@@ -798,3 +798,16 @@ editor_module: ...@@ -798,3 +798,16 @@ editor_module:
center_align: '居中对齐' center_align: '居中对齐'
justify_right: '右对齐' justify_right: '右对齐'
align_both_ends: '两端对齐' align_both_ends: '两端对齐'
optimize_input_placeholder: '请输入优化文本的指令'
retouching: '润色'
expansion: '扩写'
abbreviation: '缩写'
adjust_the_tone: '调整语气'
colloquial: '口语化'
academicization: '学术化'
humorous_and_vivid: '幽默生动'
serious_and_formal: '严肃正式'
concise_and_clear: '简洁明了'
elegant_literary_style: '文采优美'
...@@ -797,3 +797,16 @@ editor_module: ...@@ -797,3 +797,16 @@ editor_module:
center_align: '居中對齊' center_align: '居中對齊'
justify_right: '右對齊' justify_right: '右對齊'
align_both_ends: '兩端對齊' align_both_ends: '兩端對齊'
optimize_input_placeholder: '請輸入優化文本的指令'
retouching: '潤色'
expansion: '擴寫'
abbreviation: '縮寫'
adjust_the_tone: '調整語氣'
colloquial: '口語化'
academicization: '學術化'
humorous_and_vivid: '幽默生動'
serious_and_formal: '嚴肅正式'
concise_and_clear: '簡潔明了'
elegant_literary_style: '文采優美'
...@@ -820,6 +820,19 @@ declare namespace I18n { ...@@ -820,6 +820,19 @@ declare namespace I18n {
center_align: string center_align: string
justify_right: string justify_right: string
align_both_ends: string align_both_ends: string
optimize_input_placeholder: string
retouching: string
expansion: string
abbreviation: string
adjust_the_tone: string
colloquial: string
academicization: string
humorous_and_vivid: string
serious_and_formal: string
concise_and_clear: string
elegant_literary_style: string
} }
} }
} }
...@@ -27,15 +27,15 @@ export default defineConfig(({ command, mode }) => { ...@@ -27,15 +27,15 @@ export default defineConfig(({ command, mode }) => {
server: { server: {
host: true, host: true,
port: envConf.VITE_PORT, port: envConf.VITE_PORT,
proxy: { // proxy: {
'/api/rest': { // '/api/rest': {
target: 'http://192.168.13.93:5000', // target: 'http://192.168.13.93:5000',
changeOrigin: true, // changeOrigin: true,
rewrite: (path) => { // rewrite: (path) => {
return path // return path
}, // },
}, // },
}, // },
}, },
css: { css: {
preprocessorOptions: { preprocessorOptions: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment