Skip to content

Commit

Permalink
feat: swift modify sentence
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat616 committed Sep 9, 2023
1 parent 0a7dbb0 commit cba3c24
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 9 deletions.
10 changes: 9 additions & 1 deletion components/PollDetailModal.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts" setup>
import { filterXSS } from 'xss'
import dayjs from 'dayjs'
import { PollStatus } from '~/enums/poll'
import { CardPropsSentence } from './do/review/Card.vue'
Expand Down Expand Up @@ -108,7 +109,14 @@ const sentence = computed(() => {
convertPollMethod(record.method)
}}
{{ record.point }} 票
{{ record.comment && `,评论到:“${record.comment}”` }}
<!--eslint-disable vue/no-v-html-->
<span
v-if="record.comment"
class=":uno: underline-offset-2"
v-html="
filterXSS(`,评论到:“${formartPollComment(record.comment)}`)
"
/>
</li>
</ul>
</div>
Expand Down
131 changes: 131 additions & 0 deletions components/SentenceModifyModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<script setup lang="ts">
import type { SelectProps } from 'ant-design-vue'
import type { CardPropsSentence } from '@/components/do/review/Card.vue'
import { HitokotoType } from '~/enums/hitokoto'
export type Sentence = Omit<CardPropsSentence, 'creator' | 'createdAt'>
const props = defineProps<{
open: boolean
sentence: Sentence
}>()
const emit = defineEmits<{
'update:open': [value: boolean]
finish: [sentence: Sentence]
}>()
const onOK = () => {
emit('update:open', false)
if (formState.fromWho === '') formState.fromWho = undefined
emit('finish', formState)
}
const formState = reactive<Sentence>({
uuid: '',
hitokoto: '',
type: HitokotoType.Anime,
fromWho: '',
from: ''
})
const labelCol = { span: 5 }
const wrapperCol = { span: 13 }
// 重置表单
watch(
() => props.open,
(val) => {
if (!val) return
formState.uuid = props.sentence.uuid
formState.hitokoto = props.sentence.hitokoto
formState.type = props.sentence.type
formState.fromWho = props.sentence.fromWho
formState.from = props.sentence.from
}
)
const hitokotoTypeOptions = reactive<
Exclude<SelectProps['options'], undefined>
>([
{
label: '动画',
value: HitokotoType.Anime
},
{
label: '漫画',
value: HitokotoType.Comic
},
{
label: '游戏',
value: HitokotoType.Game
},
{
label: '文学',
value: HitokotoType.Novel
},
{
label: '原创',
value: HitokotoType.Original
},
{
label: '网络',
value: HitokotoType.Internet
},
{
label: '其他',
value: HitokotoType.Other
},
{
label: '影视',
value: HitokotoType.Movie
},
{
label: '诗词',
value: HitokotoType.Poem
},
{
label: '网易云',
value: HitokotoType.NCM
},
{
label: '哲学',
value: HitokotoType.Philosophy
},
{
label: '抖机灵',
value: HitokotoType.Joke
}
])
</script>

<template>
<a-modal
:open="props.open"
:title="`修改句子`"
:label-col="labelCol"
:wrapper-col="wrapperCol"
@update:open="emit('update:open', $event)"
@ok="onOK"
>
<a-form :model="formState" name="modify-sentence" class="my-10">
<a-form-item label="标识" name="uuid">
<a-input :value="formState.uuid" disabled />
</a-form-item>
<a-form-item label="来源" name="from">
<a-input v-model:value="formState.from" />
</a-form-item>
<a-form-item label="作者" name="fromWho">
<a-input v-model:value="formState.fromWho" />
</a-form-item>
<a-form-item label="分类" name="type">
<a-select
v-model:value="formState.type"
:options="hitokotoTypeOptions"
/>
</a-form-item>
<a-form-item label="句子" name="hitokoto">
<a-textarea v-model:value="formState.hitokoto" />
</a-form-item>
</a-form>
</a-modal>
</template>
12 changes: 10 additions & 2 deletions components/do/review/Card.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import xss from 'xss'
import dayjs from 'dayjs'
import type { PollMethod } from '@/enums/poll'
import type { HitokotoType } from '~/enums/hitokoto'
import type { Sentence } from '@/components/SentenceModifyModal.vue'
// Props 定义
export type CardPropsPoll = {
Expand Down Expand Up @@ -48,7 +49,10 @@ const emit = defineEmits<{
doLocalSearch: [sentence: SearchParams]
doMasonryRepaint: [] // 传递此事件只是为了让父组件重绘制
viewComments: [index: number]
doSwiftModify: [pollID: number]
doSwiftModify: [
sentence: Sentence,
onModifyFinished: (sentence: Sentence) => void
]
opeartionDone: [event: 'submit' | 'cancel', index: number]
}>()
Expand All @@ -60,6 +64,8 @@ const onOperationDone = (event: 'submit' | 'cancel') => {
const userStore = useUserStore()
const marksSelectedValues = ref<number[]>([])
provide('sentence', props.sentence) // 提供句子数据给子组件
</script>

<template>
Expand Down Expand Up @@ -132,7 +138,9 @@ const marksSelectedValues = ref<number[]>([])
@do-masonry-repaint="emit('doMasonryRepaint')"
@operation-done="onOperationDone"
@view-comments="emit('viewComments', props.index)"
@do-swift-modify="emit('doSwiftModify', props.poll.id)"
@do-swift-modify="
emit('doSwiftModify', props.sentence as Sentence, $event)
"
/>
</a-card>
</template>
Expand Down
22 changes: 20 additions & 2 deletions components/do/review/CardActionsContainer.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script setup lang="ts">
import { snakeCase } from 'lodash-es'
import { PollMethod } from '@/enums/poll'
import type { PollReq } from '@/composables/api'
import type { Sentence } from '@/components/SentenceModifyModal.vue'
import { SnakeSentence } from '~/utils/formatter'
const props = defineProps<{
marksSelectedValues?: number[]
isPolled: boolean
Expand All @@ -13,7 +16,7 @@ const emit = defineEmits<{
doWebSearch: []
doLocalSearch: []
viewComments: []
doSwiftModify: []
doSwiftModify: [onModifyFinished: (sentence: Sentence) => void]
operationDone: [event: 'submit' | 'cancel']
}>()
Expand Down Expand Up @@ -87,6 +90,21 @@ const onCancelPoll = async () => {
onSubmitLoading.value = false
}
}
// 快捷修改
const sentence = inject<Sentence>('sentence') as Sentence
const onSwiftModify = (camel: Sentence) => {
const snake: SnakeSentence = (
Object.keys(camel) as Array<keyof Sentence>
).reduce((acc, cur) => {
if (camel[cur] === sentence[cur]) return acc
const key = snakeCase(cur) as keyof SnakeSentence
acc[key] = camel[cur] as never
return acc
}, {} as SnakeSentence)
if (Object.keys(snake).length === 0) return
comment.value = JSON.stringify(snake)
}
</script>
<template>
<div class="actions-container">
Expand Down Expand Up @@ -144,7 +162,7 @@ const onCancelPoll = async () => {
@do-local-search="emit('doLocalSearch')"
@do-web-search="emit('doWebSearch')"
@view-comments="emit('viewComments')"
@do-swift-modify="emit('doSwiftModify')"
@do-swift-modify="emit('doSwiftModify', onSwiftModify)"
/>
</div>
</div>
Expand Down
9 changes: 6 additions & 3 deletions components/poll/Comments.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import { filterXSS } from 'xss'
import type { PollDetailRes } from '@/composables/api'
import { getAvatarURLByHash } from '~/utils/avatar'
const props = defineProps<{
Expand All @@ -26,9 +27,11 @@ watch(records, (val) => console.log(val))
{{ dayjs(record.created_at).format('YYYY-MM-DD HH:mm:ss') }}
</span>
</div>
<div class=":uno: text-sm">
{{ record.comment }}
</div>
<!-- eslint-disable vue/no-v-html-->
<div
class=":uno: text-sm underline-offset-2"
v-html="filterXSS(formartPollComment(record.comment))"
></div>
</div>
</div>
<a-divider v-if="index < records.length - 1" class=":uno: my-3" />
Expand Down
30 changes: 29 additions & 1 deletion pages/dashboard/do_review.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PlusCircleOutlined } from '@ant-design/icons-vue'
import { PollStatus, PolledFilter } from '@/enums/poll'
import type { SearchParams } from '@/components/do/review/Card.vue'
import type { SegmentedOption } from 'ant-design-vue/es/segmented/src/segmented' // TODO: Antdv 的类型定义有问题,这里需要手动指定路径
import type { Sentence } from '@/components/SentenceModifyModal.vue'
useHead({
title: '句子审核'
})
Expand Down Expand Up @@ -211,6 +211,28 @@ const viewCommentsModal = reactive({
open: false,
index: 0
})
// 快捷修改
const swiftModifyModal = reactive({
open: false,
sentence: {} as Sentence,
onModifyCallback: undefined as ((sentence: Sentence) => void) | undefined
})
const doSwiftModify = (
sentence: Sentence,
fn: (sentence: Sentence) => void
) => {
swiftModifyModal.sentence = { ...sentence }
swiftModifyModal.onModifyCallback = fn
swiftModifyModal.open = true
}
const onModifySentenceFinished = (sentence: Sentence) => {
swiftModifyModal.open = false
swiftModifyModal.onModifyCallback &&
swiftModifyModal.onModifyCallback(sentence)
}
</script>
<template>
<div class="do-review">
Expand All @@ -228,6 +250,11 @@ const viewCommentsModal = reactive({
pollListData?.data.collection[viewCommentsModal.index].records || []
"
/>
<SentenceModifyModal
v-model:open="swiftModifyModal.open"
:sentence="swiftModifyModal.sentence"
@finish="onModifySentenceFinished"
/>
<a-page-header title="句子审核" />
<div class="toolbar">
<a-segmented
Expand Down Expand Up @@ -298,6 +325,7 @@ const viewCommentsModal = reactive({
viewCommentsModal.index = index
}
"
@do-swift-modify="doSwiftModify"
@opeartion-done="onOperationDone"
/>
</div>
Expand Down
38 changes: 38 additions & 0 deletions utils/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,41 @@ export function formatReviewer(reviewerUid: number): string | null | undefined {
? reviewerMap[reviewerUid as keyof typeof reviewerMap]
: null
}

export type SnakeSentence = Omit<
PollListCollectionElement['sentence'],
| 'id'
| 'creator_uid'
| 'creator'
| 'reviewer'
| 'status'
| 'poll_status'
| 'created_at'
>

const SentenceFieldMap: Record<keyof SnakeSentence, string> = {
uuid: '标识',
hitokoto: '句子',
type: '类型',
from: '来源',
from_who: '作者'
}

export function formartPollComment(comment: string): string {
try {
const parsed = JSON.parse(comment) as SnakeSentence
return (
'建议将' +
(Object.keys(parsed) as Array<keyof SnakeSentence>)
.map((key) => {
const target =
key === 'type' ? convertHitokotoType(parsed[key]) : parsed[key]
return ` <b>${SentenceFieldMap[key]}</b> 修改为 “<u>${target}</u>”`
})
.join(',') +
'。'
)
} catch (e) {
return comment
}
}

0 comments on commit cba3c24

Please sign in to comment.