|
|
@@ -45,8 +45,18 @@
|
|
|
</NLayoutContent>
|
|
|
</NLayout>
|
|
|
<n-modal v-model:show="showModal">
|
|
|
- <n-card style="width: 800px" title="生成结果" :bordered="false" size="huge" role="dialog" aria-modal="true">
|
|
|
+ <n-card style="width: 800px" :bordered="false" role="dialog" aria-modal="true">
|
|
|
+ <NSpace class="mb-4 flex items-center">
|
|
|
+ <n-radio-group v-model:value="showResultType" name="radiobuttongroup2" size="small">
|
|
|
+ <n-radio-button value="doc"> 生成结果 </n-radio-button>
|
|
|
+ <n-radio-button value="attachment"> 附件 </n-radio-button>
|
|
|
+ </n-radio-group>
|
|
|
+ <NUpload :action="uploadUrl" :headers="uploadHeaders" :show-file-list="false" @finish="onUploaded">
|
|
|
+ <NButton size="small" type="primary">上传附件</NButton>
|
|
|
+ </NUpload>
|
|
|
+ </NSpace>
|
|
|
<n-data-table
|
|
|
+ v-if="showResultType === 'doc'"
|
|
|
remote
|
|
|
:columns="resultColumns"
|
|
|
:data="resultData"
|
|
|
@@ -55,6 +65,16 @@
|
|
|
@update:page="getResults"
|
|
|
@update:page-size="getResults"
|
|
|
/>
|
|
|
+ <n-data-table
|
|
|
+ v-else
|
|
|
+ remote
|
|
|
+ :columns="attachmentColumns"
|
|
|
+ :data="attachmentData"
|
|
|
+ :pagination="attachmentsPagination"
|
|
|
+ :bordered="false"
|
|
|
+ @update:page="getAttachments"
|
|
|
+ @update:page-size="getAttachments"
|
|
|
+ />
|
|
|
</n-card>
|
|
|
</n-modal>
|
|
|
<n-modal v-model:show="showForm" :mask-closable="false">
|
|
|
@@ -120,7 +140,7 @@
|
|
|
<NInput v-model:value="model.paymentMethod" />
|
|
|
</NFormItem>
|
|
|
<NFormItem label="是否结稿费" path="paymentStatus">
|
|
|
- <NInput v-model:value="model.paymentStatus" />
|
|
|
+ <NCheckbox v-model:checked="model.paymentStatus">已结</NCheckbox>
|
|
|
</NFormItem>
|
|
|
<div class="w-3/4"></div>
|
|
|
<NFormItem style="width: calc(100% - 18px)" label="备注" path="remark">
|
|
|
@@ -202,7 +222,7 @@
|
|
|
</n-modal>
|
|
|
</template>
|
|
|
<script lang="ts" setup>
|
|
|
-import { h, defineComponent, ref, reactive, onMounted, Ref, computed } from 'vue'
|
|
|
+import { h, defineComponent, ref, reactive, onMounted, Ref, computed, VNode } from 'vue'
|
|
|
import {
|
|
|
NButton,
|
|
|
NDataTable,
|
|
|
@@ -230,17 +250,26 @@ import {
|
|
|
NSelect,
|
|
|
NCheckbox,
|
|
|
NRadio,
|
|
|
- NDatePicker
|
|
|
+ NDatePicker,
|
|
|
+ NRadioGroup,
|
|
|
+ NRadioButton,
|
|
|
+ NIcon,
|
|
|
+ NUpload,
|
|
|
+ UploadFileInfo,
|
|
|
+ DropdownOption,
|
|
|
+ DropdownGroupOption
|
|
|
} from 'naive-ui'
|
|
|
import {
|
|
|
fetchPaperOrders,
|
|
|
fetchGenPaper,
|
|
|
fetchPaperResults,
|
|
|
+ fetchPaperAttachments,
|
|
|
fetchCreatePaperOrder,
|
|
|
fetchUpdatePaperOrder,
|
|
|
fetchGenChapters,
|
|
|
fetchSearchReference
|
|
|
} from '@/api'
|
|
|
+import { post, put, del } from '@/utils/request'
|
|
|
import { format, parseISO } from 'date-fns'
|
|
|
import { UserAvatar } from '@/components/common'
|
|
|
import { LoginForm } from '@/components/common'
|
|
|
@@ -257,6 +286,9 @@ import OutlineEditor from '@/components/common/OutlineEditor.vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
|
import { useClipboard } from '@vueuse/core'
|
|
|
import { copyText } from '@/utils/format'
|
|
|
+import { Dots } from '@vicons/tabler'
|
|
|
+import resolveUrl from 'resolve-url'
|
|
|
+import { useAuthStore } from '@/store'
|
|
|
const router = useRouter()
|
|
|
const message = useMessage()
|
|
|
const showLogin = ref(false)
|
|
|
@@ -375,15 +407,16 @@ const columns: DataTableColumn[] = [
|
|
|
width: 180
|
|
|
},
|
|
|
{
|
|
|
- title: '标题',
|
|
|
- key: 'title'
|
|
|
+ title: '接单渠道',
|
|
|
+ key: 'orderChannel'
|
|
|
},
|
|
|
{
|
|
|
- title: '描述',
|
|
|
- key: 'description',
|
|
|
- ellipsis: {
|
|
|
- tooltip: true
|
|
|
- }
|
|
|
+ title: '订单号',
|
|
|
+ key: 'orderNumber'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '标题',
|
|
|
+ key: 'title'
|
|
|
},
|
|
|
{
|
|
|
title: '备注',
|
|
|
@@ -443,18 +476,16 @@ const columns: DataTableColumn[] = [
|
|
|
},
|
|
|
{ default: () => '查看' }
|
|
|
),
|
|
|
- roles.value.includes('paperGen')
|
|
|
- ? h(
|
|
|
- NButton,
|
|
|
- {
|
|
|
- strong: true,
|
|
|
- tertiary: true,
|
|
|
- size: 'small',
|
|
|
- onClick: () => editRow(row)
|
|
|
- },
|
|
|
- { default: () => '编辑' }
|
|
|
- )
|
|
|
- : null
|
|
|
+ h(
|
|
|
+ NButton,
|
|
|
+ {
|
|
|
+ strong: true,
|
|
|
+ tertiary: true,
|
|
|
+ size: 'small',
|
|
|
+ onClick: () => editRow(row)
|
|
|
+ },
|
|
|
+ { default: () => '编辑' }
|
|
|
+ )
|
|
|
])
|
|
|
}
|
|
|
}
|
|
|
@@ -530,7 +561,9 @@ async function gen() {
|
|
|
|
|
|
const orderId = ref<any>(null)
|
|
|
const showModal = ref(false)
|
|
|
+const showResultType = ref('doc')
|
|
|
const resultData = ref([])
|
|
|
+const attachmentData = ref([])
|
|
|
const resultsPagination = reactive({
|
|
|
page: 1,
|
|
|
pageSize: 10,
|
|
|
@@ -545,11 +578,26 @@ const resultsPagination = reactive({
|
|
|
resultsPagination.page = 1
|
|
|
}
|
|
|
})
|
|
|
+const attachmentsPagination = reactive({
|
|
|
+ page: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ showSizePicker: false,
|
|
|
+ pageSizes: [10],
|
|
|
+ pageCount: 1,
|
|
|
+ onChange: (page: number) => {
|
|
|
+ attachmentsPagination.page = page
|
|
|
+ },
|
|
|
+ onUpdatePageSize: (pageSize: number) => {
|
|
|
+ attachmentsPagination.pageSize = pageSize
|
|
|
+ attachmentsPagination.page = 1
|
|
|
+ }
|
|
|
+})
|
|
|
async function showResults(row: any) {
|
|
|
orderId.value = row.id
|
|
|
showModal.value = true
|
|
|
resultData.value = []
|
|
|
getResults()
|
|
|
+ getAttachments()
|
|
|
}
|
|
|
function getResults() {
|
|
|
fetchPaperResults({
|
|
|
@@ -571,6 +619,26 @@ function getResults() {
|
|
|
resultsPagination.pageCount = res.meta.totalPages
|
|
|
})
|
|
|
}
|
|
|
+function getAttachments() {
|
|
|
+ fetchPaperAttachments({
|
|
|
+ page: {
|
|
|
+ page: attachmentsPagination.page,
|
|
|
+ limit: attachmentsPagination.pageSize
|
|
|
+ },
|
|
|
+ search: {
|
|
|
+ order: {
|
|
|
+ createdAt: 'desc'
|
|
|
+ },
|
|
|
+ where: {
|
|
|
+ orderId: orderId.value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).then((res: any) => {
|
|
|
+ console.log(res)
|
|
|
+ attachmentData.value = res.items
|
|
|
+ attachmentsPagination.pageCount = res.meta.totalPages
|
|
|
+ })
|
|
|
+}
|
|
|
const resultColumns: DataTableColumn[] = [
|
|
|
{ title: '#', key: 'id' },
|
|
|
{ title: '生成时间', key: 'createdAt', render: timeFormatter },
|
|
|
@@ -636,6 +704,69 @@ const resultColumns: DataTableColumn[] = [
|
|
|
}
|
|
|
}
|
|
|
]
|
|
|
+const attachmentColumns: DataTableColumn[] = [
|
|
|
+ { title: '#', key: 'id' },
|
|
|
+ { title: '上传时间', key: 'createdAt', render: timeFormatter },
|
|
|
+ { title: '文件名', key: 'name' },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ key: 'action',
|
|
|
+ align: 'center',
|
|
|
+ width: '150px',
|
|
|
+ render(row: any) {
|
|
|
+ return h(
|
|
|
+ NDropdown,
|
|
|
+ {
|
|
|
+ size: 'small',
|
|
|
+ options: [
|
|
|
+ {
|
|
|
+ label: '下载',
|
|
|
+ key: 'download'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '删除',
|
|
|
+ key: 'delete'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ trigger: 'click',
|
|
|
+ renderLabel: (option: DropdownOption) =>
|
|
|
+ option.key === 'delete'
|
|
|
+ ? h('span', { style: 'color: red' }, option.label as string)
|
|
|
+ : h('span', {}, option.label as string),
|
|
|
+ onSelect(key: string | number) {
|
|
|
+ console.log(key)
|
|
|
+ if (key === 'delete') {
|
|
|
+ dialog.warning({
|
|
|
+ title: 'Confirm',
|
|
|
+ content: '确认删除?',
|
|
|
+ positiveText: '确认',
|
|
|
+ negativeText: '取消',
|
|
|
+ onPositiveClick: async () => {
|
|
|
+ await del({
|
|
|
+ url: `/paper/attachments/${row.id}`
|
|
|
+ })
|
|
|
+ getAttachments()
|
|
|
+ },
|
|
|
+ onNegativeClick: () => {}
|
|
|
+ })
|
|
|
+ } else if (key === 'download') {
|
|
|
+ const link = document.createElement('a')
|
|
|
+ link.href = row.url
|
|
|
+ link.download = encodeURIComponent(row.name)
|
|
|
+ console.log(row.name)
|
|
|
+ link.click()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ () =>
|
|
|
+ h(NButton, {
|
|
|
+ size: 'small',
|
|
|
+ renderIcon: () => h(NIcon, null, () => h(Dots))
|
|
|
+ })
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+]
|
|
|
|
|
|
const showForm = ref(false)
|
|
|
const genForm: Ref<FormInst | null> = ref(null)
|
|
|
@@ -699,10 +830,7 @@ async function submit(gen = false) {
|
|
|
}
|
|
|
function editRow(row: any) {
|
|
|
model.value = {
|
|
|
- major: row.major,
|
|
|
- title: row.title,
|
|
|
- description: row.description,
|
|
|
- remark: row.remark,
|
|
|
+ ...row,
|
|
|
chapters: row.chapters || []
|
|
|
}
|
|
|
orderId.value = row.id
|
|
|
@@ -892,6 +1020,28 @@ async function copyReference() {
|
|
|
const { copy } = useClipboard({ legacy: true })
|
|
|
await copy(text)
|
|
|
}
|
|
|
+
|
|
|
+const uploadUrl = resolveUrl(import.meta.env.VITE_APP_API_BASE_URL, '/api/file/upload')
|
|
|
+const authStore = storeToRefs(useAuthStore())
|
|
|
+const uploadHeaders = computed(() => {
|
|
|
+ return {
|
|
|
+ Authorization: `Bearer ${authStore.token.value}`
|
|
|
+ }
|
|
|
+})
|
|
|
+function onUploaded(options: { file: UploadFileInfo; event?: ProgressEvent }) {
|
|
|
+ const res = (event?.target as XMLHttpRequest).response
|
|
|
+ console.log(JSON.parse(res).url)
|
|
|
+ put({
|
|
|
+ url: '/paper/attachments',
|
|
|
+ data: {
|
|
|
+ orderId: orderId.value,
|
|
|
+ name: options.file.name,
|
|
|
+ url: JSON.parse(res).url
|
|
|
+ }
|
|
|
+ }).then(() => {
|
|
|
+ getAttachments()
|
|
|
+ })
|
|
|
+}
|
|
|
</script>
|
|
|
<style lang="less" scoped>
|
|
|
:deep(.edit-form) {
|