xiongzhu před 2 roky
rodič
revize
77c953c1b3

+ 35 - 1
src/api/index.ts

@@ -1,5 +1,5 @@
 import type { AxiosProgressEvent, GenericAbortSignal } from 'axios'
-import { post, get } from '@/utils/request'
+import { post, get, put, patch } from '@/utils/request'
 import { useAuthStore, useSettingStore } from '@/store'
 
 export function fetchChatAPI<T = any>(
@@ -228,3 +228,37 @@ export function fetchUserFileds<T>(datas: any) {
         data: datas
     })
 }
+
+export function fetchPaperOrders<T>(data: any) {
+    return post<T>({
+        url: '/paper/orders',
+        data
+    })
+}
+
+export function fetchGenPaper<T>(id: number) {
+    return post<T>({
+        url: `/paper/orders/${id}/gen`
+    })
+}
+
+export function fetchPaperResults<T>(data: any) {
+    return post<T>({
+        url: '/paper/results',
+        data
+    })
+}
+
+export function fetchCreatePaperOrder<T>(data: any) {
+    return put<T>({
+        url: '/paper/orders',
+        data
+    })
+}
+
+export function fetchUpdatePaperOrder<T>(id: number, data: any) {
+    return patch<T>({
+        url: `/paper/orders/${id}`,
+        data
+    })
+}

+ 1 - 1
src/components/common/LoginForm.vue

@@ -91,7 +91,7 @@ import {
     NConfigProvider,
     GlobalThemeOverrides,
     NModal,
-    NCard
+    NCard,
 } from 'naive-ui'
 import { RuleContent } from '@/components/common'
 import { User, ShieldCheck } from '@vicons/tabler'

+ 5 - 0
src/router/index.ts

@@ -119,6 +119,11 @@ const routes: RouteRecordRaw[] = [
         name: 'info',
         component: () => import('@/views/page/InfoView.vue')
     },
+    {
+        path: '/paperGen',
+        name: 'paperGen',
+        component: () => import('@/views/page/PaperGen.vue')
+    },
     {
         path: '/404',
         name: '404',

+ 46 - 1
src/utils/request/index.ts

@@ -45,7 +45,9 @@ function http<T = any>({
 
     return method === 'GET'
         ? request.get(url, { params, signal, onDownloadProgress }).then(successHandler, failHandler)
-        : request.post(url, params, { headers, signal, onDownloadProgress }).then(successHandler, failHandler)
+        : request
+              .request({ headers, signal, onDownloadProgress, url, method, data: params })
+              .then(successHandler, failHandler)
 }
 
 export function get<T = any>({
@@ -90,4 +92,47 @@ export function post<T = any>({
     })
 }
 
+export function put<T = any>({
+    url,
+    data,
+    method = 'PUT',
+    headers,
+    onDownloadProgress,
+    signal,
+    beforeRequest,
+    afterRequest
+}: HttpOption): Promise<T> {
+    return http<T>({
+        url,
+        method,
+        data,
+        headers,
+        onDownloadProgress,
+        signal,
+        beforeRequest,
+        afterRequest
+    })
+}
+
+export function patch<T = any>({
+    url,
+    data,
+    method = 'PATCH',
+    headers,
+    onDownloadProgress,
+    signal,
+    beforeRequest,
+    afterRequest
+}: HttpOption): Promise<T> {
+    return http<T>({
+        url,
+        method,
+        data,
+        headers,
+        onDownloadProgress,
+        signal,
+        beforeRequest,
+        afterRequest
+    })
+}
 export default post

+ 339 - 0
src/views/page/PaperGen.vue

@@ -0,0 +1,339 @@
+<template>
+    <div class="p-8">
+        <NSpace class="mb-4">
+            <NButton type="primary" @click="onCreate">创建</NButton>
+        </NSpace>
+        <n-data-table
+            remote
+            :columns="columns"
+            :data="tableData"
+            :pagination="paginationReactive"
+            :bordered="false"
+            @update:page="getData"
+        />
+    </div>
+    <n-modal v-model:show="showModal">
+        <n-card style="width: 600px" title="生成结果" :bordered="false" size="huge" role="dialog" aria-modal="true">
+            <n-data-table
+                remote
+                :columns="resultColumns"
+                :data="resultData"
+                :pagination="resultsPagination"
+                :bordered="false"
+                @update:page="getResults"
+            />
+        </n-card>
+    </n-modal>
+
+    <n-modal v-model:show="showForm">
+        <n-card
+            style="width: 600px"
+            :title="orderId ? '编辑' : '创建'"
+            :bordered="false"
+            size="huge"
+            role="dialog"
+            aria-modal="true"
+        >
+            <NForm ref="form" :model="model" :rules="rules">
+                <NFormItem label="标题" path="title">
+                    <NInput v-model:value="model.title" />
+                </NFormItem>
+                <NFormItem label="描述" path="description">
+                    <NInput type="textarea" v-model:value="model.description" />
+                </NFormItem>
+                <NFormItem label="备注" path="remark">
+                    <NInput v-model:value="model.remark" />
+                </NFormItem>
+            </NForm>
+            <NSpace class="text-right" justify="end">
+                <NButton @click="() => (showForm = false)">取消</NButton>
+                <NButton type="primary" @click="submit" :loading="loading">{{ orderId ? '保存' : '创建' }}</NButton>
+            </NSpace>
+        </n-card>
+    </n-modal>
+</template>
+<script lang="ts" setup>
+import { h, defineComponent, ref, reactive, onMounted, Ref } from 'vue'
+import {
+    NButton,
+    NDataTable,
+    NTag,
+    NSpace,
+    useMessage,
+    type DataTableColumn,
+    useDialog,
+    NModal,
+    NCard,
+    NForm,
+    FormInst,
+    NFormItem,
+    NInput
+} from 'naive-ui'
+import { fetchPaperOrders, fetchGenPaper, fetchPaperResults, fetchCreatePaperOrder, fetchUpdatePaperOrder } from '@/api'
+import { format, parseISO } from 'date-fns'
+
+const message = useMessage()
+const tableData = ref([])
+function timeFormatter(rowData: any, rowIndex: number) {
+    return format(parseISO(rowData.createdAt), 'yyyy-MM-dd HH:mm:ss')
+}
+const columns: DataTableColumn[] = [
+    {
+        title: '#',
+        key: 'id',
+        width: 150
+    },
+    {
+        title: '创建时间',
+        key: 'createdAt',
+        render: timeFormatter
+    },
+    {
+        title: '标题',
+        key: 'title'
+    },
+    {
+        title: '描述',
+        key: 'description',
+        ellipsis: {
+            tooltip: true
+        }
+    },
+    {
+        title: '备注',
+        key: 'remark'
+    },
+    {
+        title: '状态',
+        key: 'length',
+        align: 'center',
+        render(rowData: any, rowIndex: number) {
+            switch (rowData.status) {
+                case 'pending':
+                    return h(NTag, null, { default: () => '待生成' })
+                case 'generating':
+                    return h(NTag, { type: 'info' }, { default: () => '生成中' })
+                case 'complete':
+                    return h(NTag, { type: 'success' }, { default: () => '已生成' })
+                default:
+                    return '未知'
+            }
+        }
+    },
+    {
+        title: '操作',
+        key: 'actions',
+        align: 'center',
+        width: '250px',
+        render(row: any) {
+            return h(NSpace, { justify: 'center' }, () => [
+                h(
+                    NButton,
+                    {
+                        type: 'primary',
+                        size: 'small',
+                        onClick: () => gen(row)
+                    },
+                    () => '生成'
+                ),
+                h(
+                    NButton,
+                    {
+                        strong: true,
+                        size: 'small',
+                        onClick: () => showResults(row)
+                    },
+                    { default: () => '查看' }
+                ),
+                h(
+                    NButton,
+                    {
+                        strong: true,
+                        tertiary: true,
+                        size: 'small',
+                        onClick: () => editRow(row)
+                    },
+                    { default: () => '编辑' }
+                )
+            ])
+        }
+    }
+]
+
+const paginationReactive = reactive({
+    page: 1,
+    pageSize: 10,
+    showSizePicker: false,
+    pageSizes: [10],
+    pageCount: 1,
+    onChange: (page: number) => {
+        paginationReactive.page = page
+    },
+    onUpdatePageSize: (pageSize: number) => {
+        paginationReactive.pageSize = pageSize
+        paginationReactive.page = 1
+    }
+})
+
+async function getData() {
+    const res: any = await fetchPaperOrders({
+        page: {
+            page: paginationReactive.page,
+            limit: paginationReactive.pageSize
+        },
+        search: {
+            order: {
+                createdAt: 'desc'
+            }
+        }
+    })
+    tableData.value = res.items
+    paginationReactive.pageCount = res.meta.totalPages
+}
+
+onMounted(() => {
+    getData()
+    getResults()
+})
+const dialog = useDialog()
+async function gen(row: any) {
+    const d = dialog.success({
+        title: '生成',
+        content: '确认开始生成吗?',
+        positiveText: '确认',
+        negativeText: '取消',
+        onPositiveClick: () => {
+            d.loading = true
+            return fetchGenPaper(row.id)
+                .then(() => {
+                    message.success('已开始生成')
+                    getData()
+                })
+                .catch((e: any) => {
+                    message.error(e.message)
+                })
+                .finally(() => {
+                    d.loading = false
+                })
+        }
+    })
+}
+
+const orderId = ref<any>(null)
+const showModal = ref(false)
+const resultData = ref([])
+const resultsPagination = reactive({
+    page: 1,
+    pageSize: 10,
+    showSizePicker: false,
+    pageSizes: [10],
+    pageCount: 1,
+    onChange: (page: number) => {
+        resultsPagination.page = page
+    },
+    onUpdatePageSize: (pageSize: number) => {
+        resultsPagination.pageSize = pageSize
+        resultsPagination.page = 1
+    }
+})
+async function showResults(row: any) {
+    orderId.value = row.id
+    showModal.value = true
+    resultData.value = []
+    getResults()
+}
+function getResults() {
+    fetchPaperResults({
+        page: {
+            page: resultsPagination.page,
+            limit: resultsPagination.pageSize
+        },
+        search: {
+            order: {
+                createdAt: 'desc'
+            },
+            where: {
+                orderId: orderId.value
+            }
+        }
+    }).then((res: any) => {
+        console.log(res)
+        resultData.value = res.items
+        resultsPagination.pageCount = res.meta.totalPages
+    })
+}
+const resultColumns: DataTableColumn[] = [
+    { title: '#', key: 'id' },
+    { title: '生成时间', key: 'createdAt', render: timeFormatter },
+    {
+        title: '操作',
+        key: 'action',
+        align: 'center',
+        width: '150px',
+        render(row: any) {
+            return h(
+                NButton,
+                {
+                    size: 'small',
+                    onClick: () => {
+                        window.open(row.fileUrl, '_blank')
+                    }
+                },
+                { default: () => '下载' }
+            )
+        }
+    }
+]
+
+const showForm = ref(false)
+const form: Ref<FormInst | null> = ref(null)
+const model = ref({
+    title: '',
+    description: '',
+    remark: ''
+})
+const rules = {
+    title: [{ required: true, message: '请输入标题' }],
+    description: [{ required: true, message: '请输入描述' }]
+}
+const loading = ref(false)
+function onCreate() {
+    orderId.value = null
+    model.value = {
+        title: '',
+        description: '',
+        remark: ''
+    }
+    form.value?.restoreValidation()
+    showForm.value = true
+}
+async function submit() {
+    try {
+        await form.value?.validate()
+    } catch (e: any) {
+        return
+    }
+    try {
+        loading.value = true
+        await (orderId.value
+            ? fetchUpdatePaperOrder(orderId.value, { ...model.value })
+            : fetchCreatePaperOrder({ ...model.value }))
+        loading.value = false
+        showForm.value = false
+        getData()
+    } catch (e: any) {
+        message.error(e.message)
+        loading.value = false
+    }
+}
+function editRow(row: any) {
+    model.value = {
+        title: row.title,
+        description: row.description,
+        remark: row.remark
+    }
+    orderId.value = row.id
+    form.value?.restoreValidation()
+    showForm.value = true
+}
+</script>