|
@@ -1,88 +1,30 @@
|
|
|
-<template>
|
|
|
|
|
- <t-dialog
|
|
|
|
|
- width="60%"
|
|
|
|
|
- :header="header"
|
|
|
|
|
- :confirmBtn="confirmBtn"
|
|
|
|
|
- :closeOnOverlayClick="false"
|
|
|
|
|
- @close="handleCloseDialog"
|
|
|
|
|
- @confirm="saveArticleData"
|
|
|
|
|
- >
|
|
|
|
|
- <t-space direction="vertical" style="width: 100%">
|
|
|
|
|
- <TForm ref="form" :data="articleData" :rules="rules" resetType="initial">
|
|
|
|
|
- <TFormItem label="咨询标题:" name="title" help="名称长度大于2个汉字,小于120个汉字">
|
|
|
|
|
- <t-input v-model.trim="articleData.title" clearable placeholder="请输入咨询标题" />
|
|
|
|
|
- </TFormItem>
|
|
|
|
|
- <TFormItem label="咨询分类:" name="categoryId">
|
|
|
|
|
- <t-select-input
|
|
|
|
|
- :value="articleData.categoryName"
|
|
|
|
|
- placeholder="请选择咨询分类"
|
|
|
|
|
- :popup-visible="popupVisible"
|
|
|
|
|
- :popup-props="{ overlayInnerStyle: { padding: '6px' } }"
|
|
|
|
|
- clearable
|
|
|
|
|
- allow-input
|
|
|
|
|
- @popup-visible-change="onPopupVisibleChange"
|
|
|
|
|
- @clear="onClear"
|
|
|
|
|
- @input-change="onInputChange"
|
|
|
|
|
- >
|
|
|
|
|
- <template #panel>
|
|
|
|
|
- <ul class="flex flex-col gap-1 p-0">
|
|
|
|
|
- <li
|
|
|
|
|
- v-for="item in categoryList"
|
|
|
|
|
- :key="item.id"
|
|
|
|
|
- class="block rounded-sm cursor-pointer px-2 py-0.5 text-gray-900 transition-colors duration-200 whitespace-nowrap overflow-hidden text-ellipsis hover:bg-gray-200"
|
|
|
|
|
- @click="() => onOptionClick({ id: item.id, value: item.name })"
|
|
|
|
|
- >
|
|
|
|
|
- {{ item.name }}
|
|
|
|
|
- </li>
|
|
|
|
|
- </ul>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #suffixIcon>
|
|
|
|
|
- <chevron-down-icon />
|
|
|
|
|
- </template>
|
|
|
|
|
- </t-select-input>
|
|
|
|
|
- </TFormItem>
|
|
|
|
|
- <TFormItem label="内容:" name="content"> </TFormItem>
|
|
|
|
|
- </TForm>
|
|
|
|
|
- </t-space>
|
|
|
|
|
- </t-dialog>
|
|
|
|
|
-</template>
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
|
import type { Category } from '@/model/category'
|
|
import type { Category } from '@/model/category'
|
|
|
import type { Article } from '@/model/article'
|
|
import type { Article } from '@/model/article'
|
|
|
import { computed, ref, reactive, watch } from 'vue'
|
|
import { computed, ref, reactive, watch } from 'vue'
|
|
|
-import type { FormInstanceFunctions, FormProps, SelectInputProps } from 'tdesign-vue-next'
|
|
|
|
|
|
|
+import type {
|
|
|
|
|
+ FormInstanceFunctions,
|
|
|
|
|
+ FormProps,
|
|
|
|
|
+ SelectInputProps,
|
|
|
|
|
+ TdSelectProps
|
|
|
|
|
+} from 'tdesign-vue-next'
|
|
|
import { MessagePlugin } from 'tdesign-vue-next'
|
|
import { MessagePlugin } from 'tdesign-vue-next'
|
|
|
-import { ChevronDownIcon } from 'tdesign-icons-vue-next'
|
|
|
|
|
import { updateArticlesByIdRequest, createArticlesRequest } from '@/api/article'
|
|
import { updateArticlesByIdRequest, createArticlesRequest } from '@/api/article'
|
|
|
|
|
+import { searchCategories } from '@/api/category'
|
|
|
const props = defineProps<{
|
|
const props = defineProps<{
|
|
|
isEdit?: Boolean | null
|
|
isEdit?: Boolean | null
|
|
|
headerTitle?: String | null
|
|
headerTitle?: String | null
|
|
|
- article?: Article | {}
|
|
|
|
|
|
|
+ article: Article | null
|
|
|
categoryList: Category[] | []
|
|
categoryList: Category[] | []
|
|
|
}>()
|
|
}>()
|
|
|
const formRef = ref<FormInstanceFunctions | null>(null)
|
|
const formRef = ref<FormInstanceFunctions | null>(null)
|
|
|
const headerText = computed(() => `${props.isEdit ? '编辑' : '创建'}${props.headerTitle || ''}`)
|
|
const headerText = computed(() => `${props.isEdit ? '编辑' : '创建'}${props.headerTitle || ''}`)
|
|
|
const confirmBtnText = computed(() => (props.isEdit ? '保存' : '确定'))
|
|
const confirmBtnText = computed(() => (props.isEdit ? '保存' : '确定'))
|
|
|
-const articleData: FormProps['data'] = reactive({ categoryName: '' })
|
|
|
|
|
|
|
+const articleData = reactive<{
|
|
|
|
|
+ categoryName: string,
|
|
|
|
|
+ title: string
|
|
|
|
|
+}>({ categoryName: '', title: '' })
|
|
|
|
|
|
|
|
-const popupVisible = ref(false)
|
|
|
|
|
-const onOptionClick = (item: { id: string; value: string }) => {
|
|
|
|
|
- articleData.categoryName = item.value
|
|
|
|
|
- articleData.categoryId = item.id
|
|
|
|
|
- // 选中后立即关闭浮层
|
|
|
|
|
- popupVisible.value = false
|
|
|
|
|
-}
|
|
|
|
|
-const onClear: SelectInputProps['onClear'] = () => {
|
|
|
|
|
- articleData.categoryId = ''
|
|
|
|
|
- articleData.categoryName = undefined
|
|
|
|
|
-}
|
|
|
|
|
-const onPopupVisibleChange: SelectInputProps['onPopupVisibleChange'] = (val) => {
|
|
|
|
|
- popupVisible.value = val
|
|
|
|
|
-}
|
|
|
|
|
-const onInputChange: SelectInputProps['onInputChange'] = (val, context) => {
|
|
|
|
|
- // 过滤功能
|
|
|
|
|
- console.log(val, context)
|
|
|
|
|
-}
|
|
|
|
|
const rules: FormProps['rules'] = {
|
|
const rules: FormProps['rules'] = {
|
|
|
name: [
|
|
name: [
|
|
|
{
|
|
{
|
|
@@ -153,8 +95,8 @@ const emit = defineEmits<{
|
|
|
onInputChange: [void]
|
|
onInputChange: [void]
|
|
|
}>()
|
|
}>()
|
|
|
const saveArticleData = async () => {
|
|
const saveArticleData = async () => {
|
|
|
- if (form.value) {
|
|
|
|
|
- const valid = await form.value.validate()
|
|
|
|
|
|
|
+ if (formRef.value) {
|
|
|
|
|
+ const valid = await formRef.value.validate()
|
|
|
if (valid && typeof valid === 'boolean') {
|
|
if (valid && typeof valid === 'boolean') {
|
|
|
const { title, categoryId, content, id } = articleData
|
|
const { title, categoryId, content, id } = articleData
|
|
|
if (!props.isEdit) {
|
|
if (!props.isEdit) {
|
|
@@ -170,9 +112,54 @@ const saveArticleData = async () => {
|
|
|
}
|
|
}
|
|
|
const handleCloseDialog = () => {
|
|
const handleCloseDialog = () => {
|
|
|
// 数据&&规则校验结果重置
|
|
// 数据&&规则校验结果重置
|
|
|
- if (form.value) {
|
|
|
|
|
- form.value.reset()
|
|
|
|
|
- form.value.clearValidate()
|
|
|
|
|
|
|
+ if (formRef.value) {
|
|
|
|
|
+ formRef.value.reset()
|
|
|
|
|
+ formRef.value.clearValidate()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+const categoryOptions = ref<TdSelectProps['options']>([])
|
|
|
|
|
+const categoryName = ref('')
|
|
|
|
|
+
|
|
|
|
|
+const fetchCategories = async () => {
|
|
|
|
|
+ const { data } = await searchCategories({ name: categoryName.value })
|
|
|
|
|
+ categoryOptions.value = data.map((category) => {
|
|
|
|
|
+ return {
|
|
|
|
|
+ label: category.name,
|
|
|
|
|
+ value: category.id
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+fetchCategories()
|
|
|
|
|
+
|
|
|
</script>
|
|
</script>
|
|
|
|
|
+<template>
|
|
|
|
|
+ <t-dialog
|
|
|
|
|
+ width="60%"
|
|
|
|
|
+ :header="headerText"
|
|
|
|
|
+ :confirmBtn="confirmBtnText"
|
|
|
|
|
+ :closeOnOverlayClick="false"
|
|
|
|
|
+ @close="handleCloseDialog"
|
|
|
|
|
+ @confirm="saveArticleData"
|
|
|
|
|
+ >
|
|
|
|
|
+ <t-space direction="vertical" style="width: 100%">
|
|
|
|
|
+ <TForm ref="formRef" :data="articleData" :rules="rules" resetType="initial">
|
|
|
|
|
+ <TFormItem label="咨询标题:" name="title" help="名称长度大于2个汉字,小于120个汉字">
|
|
|
|
|
+ <t-input v-model.trim="articleData.title" clearable placeholder="请输入咨询标题" />
|
|
|
|
|
+ </TFormItem>
|
|
|
|
|
+ <TFormItem label="咨询分类:" name="categoryId">
|
|
|
|
|
+ <TSelect
|
|
|
|
|
+ v-model="categoryName"
|
|
|
|
|
+ :options="categoryOptions"
|
|
|
|
|
+ placeholder="请选择咨询分类"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ filterable
|
|
|
|
|
+ @search="fetchCategories"
|
|
|
|
|
+ />
|
|
|
|
|
+ </TFormItem>
|
|
|
|
|
+ <TFormItem label="内容:" name="content"> </TFormItem>
|
|
|
|
|
+ </TForm>
|
|
|
|
|
+ </t-space>
|
|
|
|
|
+ </t-dialog>
|
|
|
|
|
+</template>
|