Commit 89492153 by HoMeTown

fix: 修复bug

parent b914ba26
...@@ -16,7 +16,7 @@ const serviceEnvConfig: ServiceEnv = { ...@@ -16,7 +16,7 @@ const serviceEnvConfig: ServiceEnv = {
proxy: '/api' proxy: '/api'
}, },
sit: { sit: {
url: 'https://sit-pet.chonglinzs.com/chonglin-api/manager/api', // 本地调试打开 url: 'http://82.156.138.187:19001/sdream-api/manager/api', // 本地调试打开
proxy: '' proxy: ''
}, },
uat: { uat: {
...@@ -28,7 +28,7 @@ const serviceEnvConfig: ServiceEnv = { ...@@ -28,7 +28,7 @@ const serviceEnvConfig: ServiceEnv = {
proxy: '/api' proxy: '/api'
}, },
prod: { prod: {
url: 'https://pet.chonglinzs.com/chonglin-api/manager/api', // 本地调试打开 url: 'http://82.156.138.187:19001/sdream-api/manager/api', // 本地调试打开
proxy: '' proxy: ''
} }
}; };
......
...@@ -10,7 +10,7 @@ lerna-debug.log* ...@@ -10,7 +10,7 @@ lerna-debug.log*
node_modules node_modules
.DS_Store .DS_Store
dist dist
chonglin-admin sdream-admin-fe
dist-ssr dist-ssr
coverage coverage
*.local *.local
......
...@@ -4,7 +4,7 @@ export function createViteBuild(viteEnv: ImportMetaEnv, viteCommand: string) { ...@@ -4,7 +4,7 @@ export function createViteBuild(viteEnv: ImportMetaEnv, viteCommand: string) {
const isProd = viteEnv.VITE_ENV_TYPE === 'prod'; const isProd = viteEnv.VITE_ENV_TYPE === 'prod';
const isBuild = viteCommand === 'build'; const isBuild = viteCommand === 'build';
const build: Record<string, any | BuildOptions> = { const build: Record<string, any | BuildOptions> = {
outDir: 'chonglin-admin', outDir: 'sdream-admin-fe',
brotliSize: false, brotliSize: false,
sourcemap: false, sourcemap: false,
chunkSizeWarningLimit: 500, chunkSizeWarningLimit: 500,
......
/** 请求超时时间 */ /** 请求超时时间 */
export const REQUEST_TIMEOUT = 60 * 1000; export const REQUEST_TIMEOUT = 60 * 1000 * 5;
/** 错误信息的显示时间 */ /** 错误信息的显示时间 */
export const ERROR_MSG_DURATION = 3 * 1000; export const ERROR_MSG_DURATION = 3 * 1000;
......
...@@ -78,7 +78,9 @@ import { ...@@ -78,7 +78,9 @@ import {
NAvatar, NAvatar,
NTimeline, NTimeline,
NTimelineItem, NTimelineItem,
NAlert NAlert,
NLayout,
NLayoutSider
} from 'naive-ui'; } from 'naive-ui';
/** 按需引入naiveUI */ /** 按需引入naiveUI */
...@@ -162,7 +164,9 @@ export default function setupNaiveUI(app: App) { ...@@ -162,7 +164,9 @@ export default function setupNaiveUI(app: App) {
NTransfer, NTransfer,
NTimeline, NTimeline,
NTimelineItem, NTimelineItem,
NAlert NAlert,
NLayout,
NLayoutSider
] ]
}); });
app.use(naive); app.use(naive);
......
...@@ -5,7 +5,7 @@ import { constantRoutes } from './routes'; ...@@ -5,7 +5,7 @@ import { constantRoutes } from './routes';
import { scrollBehavior } from './helpers'; import { scrollBehavior } from './helpers';
import { createRouterGuard } from './guard'; import { createRouterGuard } from './guard';
const history = createWebHistory('/chonglin-admin'); const history = createWebHistory('/sdream-admin-fe');
export const router = createRouter({ export const router = createRouter({
history, history,
......
...@@ -39,6 +39,13 @@ export function fetchDeactivateProduct<T>(params: T) { ...@@ -39,6 +39,13 @@ export function fetchDeactivateProduct<T>(params: T) {
} }
/** /**
* 更新产品状态 (01-启用 02-停用)
*/
export function fetchUpdateProductStatus<T>(params: T) {
return request.post(`/product/pc/v1/update_product_status`, params)
}
/**
* 删除 产品 * 删除 产品
*/ */
export function fetchDeleteProduct<T>(params: T) { export function fetchDeleteProduct<T>(params: T) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
border-radius: 8px; border-radius: 8px;
/* 设置dialog的圆角 */ /* 设置dialog的圆角 */
} }
.n-popover { .n-popover {
border-radius: 8px !important; border-radius: 8px !important;
/* 设置popover的圆角 */ /* 设置popover的圆角 */
...@@ -10,14 +11,17 @@ ...@@ -10,14 +11,17 @@
.n-image-preview-toolbar .n-base-icon { .n-image-preview-toolbar .n-base-icon {
width: 1.6em !important; width: 1.6em !important;
} }
.n-form-item-blank > div,
.n-form-item-blank > span, .n-form-item-blank>div,
.n-form-item-blank > p { .n-form-item-blank>span,
.n-form-item-blank>p {
width: 100%; width: 100%;
} }
.n-notification { .n-notification {
border-radius: 8px !important; border-radius: 8px !important;
} }
.n-message { .n-message {
border-radius: 24px !important; border-radius: 24px !important;
} }
...@@ -25,3 +29,7 @@ ...@@ -25,3 +29,7 @@
.n-data-table .n-data-table-th { .n-data-table .n-data-table-th {
background-color: #f7f7f8 !important; background-color: #f7f7f8 !important;
} }
.vxe-table--render-default.border--inner .vxe-table--header-wrapper {
background-color: #f9f9fb !important;
}
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { onBeforeRouteLeave } from 'vue-router'
import { PAGINATION_PAGE_SIZES } from '@/const/index' import { PAGINATION_PAGE_SIZES } from '@/const/index'
import { Icon } from '@iconify/vue'; import { Icon } from '@iconify/vue';
import { objectClean } from '@/utils'; import { objectClean } from '@/utils';
...@@ -20,7 +21,8 @@ const docTypeCodeOptions = [ ...@@ -20,7 +21,8 @@ const docTypeCodeOptions = [
{ label: '渠道业务规则文档', value: '01' }, { label: '渠道业务规则文档', value: '01' },
{ label: '产品相关监管规定文档', value: '02' }, { label: '产品相关监管规定文档', value: '02' },
{ label: '产品相关宣传素材文档', value: '03' }, { label: '产品相关宣传素材文档', value: '03' },
{ label: '个养-商养产品信息文档', value: '04' }, { label: '个养产品信息文档', value: '04' },
{ label: '商养产品信息文档', value: '05' },
] ]
const docStatusOptions = [ const docStatusOptions = [
{ label: '草稿', value: '00' }, { label: '草稿', value: '00' },
...@@ -75,6 +77,11 @@ const queryParams = ref(createQueryParams()); ...@@ -75,6 +77,11 @@ const queryParams = ref(createQueryParams());
/** 检索 */ /** 检索 */
function handleQuery() { function handleQuery() {
pagination.value = {
pageSize: 10,
itemCount: 0,
pageNum: 1
}
getListData(); getListData();
} }
/** 重置检索 */ /** 重置检索 */
...@@ -87,9 +94,17 @@ function handleResetQuery() { ...@@ -87,9 +94,17 @@ function handleResetQuery() {
} }
getListData(); getListData();
} }
const timer = ref<any>(null)
function startPolling() {
clearTimeout(timer.value)
timer.value = null
timer.value = setTimeout(() => {
getListData(false)
}, 5000);
}
async function getListData() { async function getListData(showLoading = true) {
loading.value = true; loading.value = showLoading;
const { pageNum, pageSize } = pagination.value; const { pageNum, pageSize } = pagination.value;
const { docName, docTypeCode, docStatus, analyzeStatus, createTime, auditTime } = queryParams.value; const { docName, docTypeCode, docStatus, analyzeStatus, createTime, auditTime } = queryParams.value;
const params = { const params = {
...@@ -108,6 +123,10 @@ async function getListData() { ...@@ -108,6 +123,10 @@ async function getListData() {
if (data?.ok) { if (data?.ok) {
listData.value = data.data.records; listData.value = data.data.records;
pagination.value.itemCount = data.data.total; pagination.value.itemCount = data.data.total;
const hasParsingData = listData.value.some((item: any) => item.analyzeStatus === '01')
if (hasParsingData) {
startPolling()
}
} }
loading.value = false; loading.value = false;
} }
...@@ -159,7 +178,7 @@ function filterDocStatus(status: string) { ...@@ -159,7 +178,7 @@ function filterDocStatus(status: string) {
const isShowAddDocModal = ref(false) const isShowAddDocModal = ref(false)
const addDocForm = ref({ const addDocForm = ref<any>({
docTypeCode: null, docTypeCode: null,
docUrl: '', docUrl: '',
docName: '', docName: '',
...@@ -194,7 +213,7 @@ function onCloseAddDocModal() { ...@@ -194,7 +213,7 @@ function onCloseAddDocModal() {
} }
const addDocLoading = ref(false) const addDocLoading = ref(false)
function handleValidateAddDocForm() { function handleValidateAddDocForm() {
addDocFormRef.value?.validate((errors) => { addDocFormRef.value?.validate((errors: any) => {
if (!errors) { if (!errors) {
submitAddProdcutDoc() submitAddProdcutDoc()
} }
...@@ -204,7 +223,7 @@ function handleValidateAddDocForm() { ...@@ -204,7 +223,7 @@ function handleValidateAddDocForm() {
}) })
} }
const defaultFileList = ref([]) const defaultFileList = ref<any>([])
const operateType = ref('') const operateType = ref('')
function onAddDoc() { function onAddDoc() {
...@@ -285,15 +304,12 @@ async function customRequest({ ...@@ -285,15 +304,12 @@ async function customRequest({
onFinish, onFinish,
onError, onError,
onProgress onProgress
}: UploadCustomRequestOptions) { }: any) {
const fm = new FormData() const fm = new FormData()
fm.append('file', file.file) fm.append('file', file.file)
fm.append('scene', 'product') fm.append('scene', 'product')
const res = await fetchUploadImgFile(fm, { const res = await fetchUploadImgFile(fm, {
withCredentials, withCredentials
onUploadProgress: ({ percent }) => {
onProgress({ percent: Math.ceil(percent) })
}
}) })
if (res.data) { if (res.data) {
addDocForm.value.docUrl = res.data.data.fullUrl addDocForm.value.docUrl = res.data.data.fullUrl
...@@ -372,6 +388,13 @@ function onAuditDoc(data: any) { ...@@ -372,6 +388,13 @@ function onAuditDoc(data: any) {
onMounted(() => { onMounted(() => {
getListData() getListData()
}) })
onBeforeRouteLeave((to, from, next) => {
clearTimeout(timer.value)
timer.value = null
next()
})
</script> </script>
<template> <template>
<div> <div>
...@@ -434,6 +457,7 @@ onMounted(() => { ...@@ -434,6 +457,7 @@ onMounted(() => {
<vxe-column min-width="120" field="analyzeStatus" title="解析状态"> <vxe-column min-width="120" field="analyzeStatus" title="解析状态">
<template #default="{ row }"> <template #default="{ row }">
<span>{{ filterAnalyzeStatus(row.analyzeStatus) }}</span> <span>{{ filterAnalyzeStatus(row.analyzeStatus) }}</span>
<n-spin v-if="row.analyzeStatus === '01'" class="define-mini-size" :stroke-width="22" size="small" />
</template> </template>
</vxe-column> </vxe-column>
<vxe-column min-width="200" field="createBy" title="创建人"></vxe-column> <vxe-column min-width="200" field="createBy" title="创建人"></vxe-column>
...@@ -473,46 +497,13 @@ onMounted(() => { ...@@ -473,46 +497,13 @@ onMounted(() => {
</div> </div>
</n-card> </n-card>
<n-modal v-model:show="showAddProductModal">
<n-card style="max-width: 600px;" title="新增产品" :bordered="false" size="huge" role="dialog" aria-modal="true">
<template #header-extra>
<Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="showAddProductModal = false" />
</template>
<n-form ref="addProductFormRef" :model="addFormModal" :rules="rules" label-placement="left" label-width="auto"
require-mark-placement="right-hanging" :size="size" :style="{
maxWidth: '640px',
}">
<n-form-item label="产品编码" path="productCode">
<n-input show-count maxlength="16" v-model:value="addFormModal.productCode" placeholder="产品编码" />
</n-form-item>
<n-form-item label="产品名称" path="productName">
<n-input show-count maxlength="32" v-model:value="addFormModal.productName" placeholder="产品名称" />
</n-form-item>
<n-form-item label="产品类别" path="productTypeId">
<n-select label-field="typeName" value-field="typeId" v-model:value="addFormModal.productTypeId" clearable
placeholder="产品类别" :options="productTypeList" />
</n-form-item>
<n-form-item label="产品介绍" path="description">
<n-input type="textarea" v-model:value="addFormModal.description" placeholder="产品介绍" />
</n-form-item>
</n-form>
<template #footer>
<n-space justify="center">
<n-button @click="onCloseAddForm">取消</n-button>
<n-button :loading="addProductLoading" type="primary" @click="handleValidateAddForm">确定</n-button>
</n-space>
</template>
</n-card>
</n-modal>
<n-modal v-model:show="isShowAddDocModal"> <n-modal v-model:show="isShowAddDocModal">
<n-card style="max-width: 600px;" title="新增文档" :bordered="false" size="huge" role="dialog" aria-modal="true"> <n-card style="max-width: 600px;" title="新增文档" :bordered="false" size="huge" role="dialog" aria-modal="true">
<template #header-extra> <template #header-extra>
<Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="isShowAddDocModal = false" /> <Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="isShowAddDocModal = false" />
</template> </template>
<n-form ref="addDocFormRef" :model="addDocForm" :rules="addDocRules" label-placement="left" label-width="auto" <n-form ref="addDocFormRef" :model="addDocForm" :rules="addDocRules" label-placement="left" label-width="auto"
require-mark-placement="right-hanging" :size="size" :style="{ require-mark-placement="right-hanging" :style="{
maxWidth: '640px', maxWidth: '640px',
}"> }">
<n-form-item label="文档类型" path="docTypeCode"> <n-form-item label="文档类型" path="docTypeCode">
...@@ -526,8 +517,8 @@ onMounted(() => { ...@@ -526,8 +517,8 @@ onMounted(() => {
</n-alert> </n-alert>
<br /> <br />
<n-upload :disabled="operateType === 'preview'" @preview="handlePreview" <n-upload :disabled="operateType === 'preview'" @preview="handlePreview"
:default-file-list="defaultFileList" accept="'.txt, .docx, .pdf, .doc, .wps, .ett, .xls, .xlsx'" :default-file-list="defaultFileList" accept=".txt,.docx,.pdf,.doc,.wps,.ett,.xls,.xlsx" :max="1"
:max="1" action="https://naive-upload.free.beeceptor.com/" :headers="{ action="https://naive-upload.free.beeceptor.com/" :headers="{
'naive-info': 'hello!', 'naive-info': 'hello!',
}" :data="{ }" :data="{
'naive-data': 'cool! naive!', 'naive-data': 'cool! naive!',
...@@ -545,8 +536,8 @@ onMounted(() => { ...@@ -545,8 +536,8 @@ onMounted(() => {
<n-form-item <n-form-item
v-if="operateType === 'audit' || operateType === 'preview' && (addDocForm.docStatus === '02' || addDocForm.docStatus === '03')" v-if="operateType === 'audit' || operateType === 'preview' && (addDocForm.docStatus === '02' || addDocForm.docStatus === '03')"
label="审核意见" path="auditDesc"> label="审核意见" path="auditDesc">
<n-input :disabled="operateType === 'preview'" type="textarea" v-model:value="addDocForm.auditDesc" <n-input maxlength="200" show-count :disabled="operateType === 'preview'" type="textarea"
placeholder="审核意见" /> v-model:value="addDocForm.auditDesc" placeholder="审核意见" />
</n-form-item> </n-form-item>
</n-form> </n-form>
<template #footer v-if="operateType !== 'preview'"> <template #footer v-if="operateType !== 'preview'">
...@@ -562,3 +553,10 @@ onMounted(() => { ...@@ -562,3 +553,10 @@ onMounted(() => {
</n-modal> </n-modal>
</div> </div>
</template> </template>
<style>
.define-mini-size .n-base-loading {
font-size: 12px !important;
margin-left: 4px;
}
</style>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted } from 'vue'; import { ref, h, onMounted, computed, watch } from 'vue';
import { import {
fetchAnalysisDoc, fetchAnalysisDoc,
fetchBackOffDoc, fetchBackOffDoc,
...@@ -10,7 +10,7 @@ import { ...@@ -10,7 +10,7 @@ import {
fetchDeleteProductDoc, fetchDeleteProductDoc,
fetchAddProductDoc, fetchAddProductDoc,
fetchDeleteProduct, fetchDeleteProduct,
fetchDeactivateProduct, fetchUpdateProductStatus,
fetchAddProduct, fetchAddProduct,
fetchQueryProductTypeList, fetchQueryProductTypeList,
fetchQueryProductList, fetchQueryProductList,
...@@ -21,14 +21,56 @@ import { objectClean } from '@/utils'; ...@@ -21,14 +21,56 @@ import { objectClean } from '@/utils';
import type { UploadCustomRequestOptions } from 'naive-ui' import type { UploadCustomRequestOptions } from 'naive-ui'
import { PAGINATION_PAGE_SIZES } from '@/const/index' import { PAGINATION_PAGE_SIZES } from '@/const/index'
import { fetchUploadImgFile } from '@/service'; import { fetchUploadImgFile } from '@/service';
import { NIcon } from 'naive-ui'
import {
BookOutline as BookIcon
} from '@vicons/ionicons5'
const menuActiveKey = ref('')
const collapsed = ref(false)
function renderIcon(icon: any) {
return () => h(NIcon, null, { default: () => h(icon) })
}
const productStatusOptions = [ const productStatusOptions = [
{ label: '运营规则文档', value: '05' }, { label: '启用', value: '01' },
{ label: '保单服务知识文档', value: '06' }, { label: '停用', value: '02' }
{ label: '产品合同文档', value: '07' }, ]
{ label: '产品说明书文档', value: '08' }, const menuOptions = [
{ label: '产品条款文档', value: '09' }, {
{ label: '产品公告文档', value: '10' }, label: '运营规则文档',
icon: renderIcon(BookIcon),
key: '01'
},
{
label: '保单服务知识文档',
icon: renderIcon(BookIcon),
key: '02'
},
{
label: '产品合同文档',
icon: renderIcon(BookIcon),
key: '03'
},
{
label: '产品说明书文档',
icon: renderIcon(BookIcon),
key: '04'
},
{
label: '产品条款文档',
icon: renderIcon(BookIcon),
key: '05'
},
{
label: '产品公告文档',
icon: renderIcon(BookIcon),
key: '06'
},
] ]
const docStatusOptions = [ const docStatusOptions = [
...@@ -68,6 +110,11 @@ const listData = ref([]); ...@@ -68,6 +110,11 @@ const listData = ref([]);
const queryParams = ref(createQueryParams()); const queryParams = ref(createQueryParams());
/** 检索 */ /** 检索 */
function handleQuery() { function handleQuery() {
pagination.value = {
pageSize: 10,
itemCount: 0,
pageNum: 1
}
getListData(); getListData();
} }
/** 重置检索 */ /** 重置检索 */
...@@ -88,9 +135,8 @@ async function queryProductTypeList() { ...@@ -88,9 +135,8 @@ async function queryProductTypeList() {
} }
} }
async function onDeactivateProduct(data: any) { async function onUpdateProductStatus(data: any, status: string) {
const res = await fetchDeactivateProduct({ productCode: data.productCode }) const res = await fetchUpdateProductStatus({ productCode: data.productCode, productStatus: status })
console.log(res)
if (res.data.data) { if (res.data.data) {
getListData() getListData()
window.$message?.success('操作成功'); window.$message?.success('操作成功');
...@@ -123,14 +169,40 @@ async function onShowDocModal(data: any) { ...@@ -123,14 +169,40 @@ async function onShowDocModal(data: any) {
showModalLoading.value = false showModalLoading.value = false
} }
async function getProductDetail(data: any) { const timer = ref<any>(null)
function startPolling() {
clearTimeout(timer.value)
timer.value = null
timer.value = setTimeout(() => {
getProductDetail(curProductDetail.value)
}, 5000);
}
async function getProductDetail(data: any, key?: string) {
const beforeActiveKey = key || menuActiveKey.value || menuOptions[0].key
const res = await fetchQueryProductDetail({ productCode: data.productCode }) const res = await fetchQueryProductDetail({ productCode: data.productCode })
if (res.data) { if (res.data) {
curProductDetail.value = res.data.data curProductDetail.value = res.data.data
menuActiveKey.value = beforeActiveKey
const hasParsingData = curProductDetail.value.productDocList.some((item: any) => item.analyzeStatus === '01')
if (hasParsingData) {
startPolling()
}
} }
showModalLoading.value = false showModalLoading.value = false
} }
function closeProductDetailModal() {
clearTimeout(timer.value)
timer.value = null
showProductDetailModal.value = false
}
const curProductDetailDocList = computed(() => {
const flag = menuOptions.find(item => item.key === menuActiveKey.value) as any
return curProductDetail.value?.productDocList?.filter((item: any) => item.docTypeCode === flag.key)
})
async function getListData() { async function getListData() {
loading.value = true; loading.value = true;
const { pageNum, pageSize } = pagination.value; const { pageNum, pageSize } = pagination.value;
...@@ -176,7 +248,7 @@ const rules = ref({ ...@@ -176,7 +248,7 @@ const rules = ref({
}) })
const addProductFormRef = ref() const addProductFormRef = ref()
function handleValidateAddForm() { function handleValidateAddForm() {
addProductFormRef.value?.validate((errors) => { addProductFormRef.value?.validate((errors: any) => {
if (!errors) { if (!errors) {
console.log('验证通过') console.log('验证通过')
onSubmitAddForm() onSubmitAddForm()
...@@ -254,11 +326,12 @@ function filterDocStatus(status: string) { ...@@ -254,11 +326,12 @@ function filterDocStatus(status: string) {
} }
const isShowAddDocModal = ref(false) const isShowAddDocModal = ref(false)
const addDocForm = ref({ const addDocForm = ref<any>({
docTypeCode: null, docTypeCode: null,
docUrl: '', docUrl: '',
docName: '', docName: '',
docCode: '' docCode: '',
docStatus: ''
}) })
const addDocRules = ref({ const addDocRules = ref({
docTypeCode: { docTypeCode: {
...@@ -289,7 +362,7 @@ function onCloseAddDocModal() { ...@@ -289,7 +362,7 @@ function onCloseAddDocModal() {
} }
const addDocLoading = ref(false) const addDocLoading = ref(false)
function handleValidateAddDocForm() { function handleValidateAddDocForm() {
addDocFormRef.value?.validate((errors) => { addDocFormRef.value?.validate((errors: any) => {
if (!errors) { if (!errors) {
submitAddProdcutDoc() submitAddProdcutDoc()
} }
...@@ -299,11 +372,13 @@ function handleValidateAddDocForm() { ...@@ -299,11 +372,13 @@ function handleValidateAddDocForm() {
}) })
} }
const defaultFileList = ref([]) const defaultFileList = ref<any>([])
const operateType = ref('') const operateType = ref('')
const operateTitle = ref('')
function onAddDoc() { function onAddDoc() {
operateType.value = 'add' operateType.value = 'add'
operateTitle.value = '新增文档'
defaultFileList.value = [] defaultFileList.value = []
addDocForm.value = { addDocForm.value = {
docTypeCode: null, docTypeCode: null,
...@@ -316,6 +391,7 @@ function onAddDoc() { ...@@ -316,6 +391,7 @@ function onAddDoc() {
function onEditDoc(data: any) { function onEditDoc(data: any) {
operateType.value = 'edit' operateType.value = 'edit'
operateTitle.value = '编辑文档'
addDocForm.value = { addDocForm.value = {
...data ...data
} }
...@@ -330,6 +406,7 @@ function onEditDoc(data: any) { ...@@ -330,6 +406,7 @@ function onEditDoc(data: any) {
} }
function onPreDoc(data: any) { function onPreDoc(data: any) {
operateType.value = 'preview' operateType.value = 'preview'
operateTitle.value = '预览文档'
addDocForm.value = { addDocForm.value = {
...data ...data
} }
...@@ -344,6 +421,7 @@ function onPreDoc(data: any) { ...@@ -344,6 +421,7 @@ function onPreDoc(data: any) {
} }
function onAuditDoc(data: any) { function onAuditDoc(data: any) {
operateType.value = 'audit' operateType.value = 'audit'
operateTitle.value = '审核文档'
addDocForm.value = { addDocForm.value = {
...data, ...data,
docStatus: null, docStatus: null,
...@@ -381,7 +459,7 @@ async function submitAddProdcutDoc() { ...@@ -381,7 +459,7 @@ async function submitAddProdcutDoc() {
} }
const res = await apis[operateType.value](params) const res = await apis[operateType.value](params)
if (res.data) { if (res.data) {
getProductDetail(curProductDetail.value) getProductDetail(curProductDetail.value, operateType.value === 'add' ? params.docTypeCode : null)
onCloseAddDocModal() onCloseAddDocModal()
window.$message?.success('成功'); window.$message?.success('成功');
} }
...@@ -399,13 +477,13 @@ async function customRequest({ ...@@ -399,13 +477,13 @@ async function customRequest({
onProgress onProgress
}: UploadCustomRequestOptions) { }: UploadCustomRequestOptions) {
const fm = new FormData() const fm = new FormData()
fm.append('file', file.file) fm.append('file', file.file as any)
fm.append('scene', 'product') fm.append('scene', 'product')
const res = await fetchUploadImgFile(fm, { const res = await fetchUploadImgFile(fm, {
withCredentials, withCredentials,
onUploadProgress: ({ percent }) => { // onUploadProgress: ({ percent }) => {
onProgress({ percent: Math.ceil(percent) }) // onProgress({ percent: Math.ceil(percent) })
} // }
}) })
if (res.data) { if (res.data) {
addDocForm.value.docUrl = res.data.data.fullUrl addDocForm.value.docUrl = res.data.data.fullUrl
...@@ -467,6 +545,7 @@ async function onAnalysisDoc(data: any) { ...@@ -467,6 +545,7 @@ async function onAnalysisDoc(data: any) {
} }
} }
onMounted(() => { onMounted(() => {
getListData() getListData()
queryProductTypeList() queryProductTypeList()
...@@ -516,13 +595,15 @@ onMounted(() => { ...@@ -516,13 +595,15 @@ onMounted(() => {
<span v-if="row.productStatus === '02'">停用</span> <span v-if="row.productStatus === '02'">停用</span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column min-width="200" field="productName" title="解析成功文档数量"></vxe-column> <vxe-column min-width="200" field="productDocNum" title="解析成功文档数量"></vxe-column>
<vxe-column field="title" title="操作" fixed="right" min-width="120"> <vxe-column field="title" title="操作" fixed="right" min-width="120">
<template #default="{ row }"> <template #default="{ row }">
<n-space> <n-space>
<n-button strong text type="info" @click="onShowDocModal(row)">文档管理</n-button> <n-button strong text type="info" @click="onShowDocModal(row)">文档管理</n-button>
<n-button @click="onDeactivateProduct(row)" v-if="row.productStatus === '01'" strong text <n-button @click="onUpdateProductStatus(row, '02')" v-if="row.productStatus === '01'" strong text
type="info">停用</n-button> type="info">停用</n-button>
<n-button @click="onUpdateProductStatus(row, '01')" v-if="row.productStatus === '02'" strong text
type="info">启用</n-button>
<n-button @click="onDeleteProduct(row)" v-if="row.productStatus === '02'" strong text <n-button @click="onDeleteProduct(row)" v-if="row.productStatus === '02'" strong text
type="info">删除产品</n-button> type="info">删除产品</n-button>
</n-space> </n-space>
...@@ -544,11 +625,11 @@ onMounted(() => { ...@@ -544,11 +625,11 @@ onMounted(() => {
</div> </div>
</n-card> </n-card>
<n-modal v-model:show="showProductDetailModal"> <n-modal :mask-closable="false" :close-on-esc="false" v-model:show="showProductDetailModal">
<n-card style="width: 80%; max-width: 1300px;" title="文档管理" :bordered="false" size="huge" role="dialog" <n-card style="width: 80%; max-width: 1300px;" title="文档管理" :bordered="false" size="huge" role="dialog"
aria-modal="true"> aria-modal="true">
<template #header-extra> <template #header-extra>
<Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="showProductDetailModal = false" /> <Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="closeProductDetailModal" />
</template> </template>
<n-spin :show="showModalLoading"> <n-spin :show="showModalLoading">
<div v-if="!showModalLoading"> <div v-if="!showModalLoading">
...@@ -557,7 +638,7 @@ onMounted(() => { ...@@ -557,7 +638,7 @@ onMounted(() => {
产品信息 产品信息
</n-text> </n-text>
</n-h3> </n-h3>
<n-descriptions bordered column="1" label-placement="left"> <n-descriptions bordered :column="1" label-placement="left">
<n-descriptions-item label="产品编码"> <n-descriptions-item label="产品编码">
{{ curProductDetail.productCode }} {{ curProductDetail.productCode }}
</n-descriptions-item> </n-descriptions-item>
...@@ -577,11 +658,23 @@ onMounted(() => { ...@@ -577,11 +658,23 @@ onMounted(() => {
</n-text> </n-text>
<n-button class="ml-[12px]" strong type="primary" @click="onAddDoc"> 新增文档 </n-button> <n-button class="ml-[12px]" strong type="primary" @click="onAddDoc"> 新增文档 </n-button>
</n-h3> </n-h3>
<vxe-table :column-config="{ resizable: true }" <n-layout has-sider>
<n-layout-sider collapse-mode="width" :collapsed-width="64" :width="200" :collapsed="collapsed"
show-trigger @collapse="collapsed = true" @expand="collapsed = false">
<n-menu v-model:value="menuActiveKey" :collapsed="collapsed" :collapsed-width="64"
:collapsed-icon-size="22" :options="menuOptions" />
</n-layout-sider>
<n-layout class="ml-24px">
<!-- <n-h4>
<n-text>
产品公告文档(共4条)
</n-text>
</n-h4> -->
<vxe-table height="480" :column-config="{ resizable: true }"
:seq-config="{ startIndex: (pagination.pageNum - 1) * pagination.pageSize }" auto-resize :seq-config="{ startIndex: (pagination.pageNum - 1) * pagination.pageSize }" auto-resize
:row-config="{ isHover: true }" stripe border :data="curProductDetail?.productDocList"> :row-config="{ isHover: true }" border="inner" :data="curProductDetailDocList">
<vxe-column fixed="left" type="seq" title="序号" width="60"></vxe-column> <vxe-column fixed="left" type="seq" title="序号" width="60"></vxe-column>
<vxe-column fixed="left" min-width="140" field="docTypeName" title="文档类型"></vxe-column> <!-- <vxe-column fixed="left" min-width="140" field="docTypeName" title="文档类型"></vxe-column> -->
<vxe-column fixed="left" min-width="180" field="docName" title="文档名称"></vxe-column> <vxe-column fixed="left" min-width="180" field="docName" title="文档名称"></vxe-column>
<vxe-column min-width="120" field="docStatus" title="文档状态"> <vxe-column min-width="120" field="docStatus" title="文档状态">
<template #default="{ row }"> <template #default="{ row }">
...@@ -591,30 +684,32 @@ onMounted(() => { ...@@ -591,30 +684,32 @@ onMounted(() => {
<vxe-column min-width="120" field="analyzeStatus" title="解析状态"> <vxe-column min-width="120" field="analyzeStatus" title="解析状态">
<template #default="{ row }"> <template #default="{ row }">
<span>{{ filterAnalyzeStatus(row.analyzeStatus) }}</span> <span>{{ filterAnalyzeStatus(row.analyzeStatus) }}</span>
<n-spin v-if="row.analyzeStatus === '01'" class="define-mini-size" :stroke-width="22"
size="small" />
</template> </template>
</vxe-column> </vxe-column>
<vxe-column min-width="120" field="createBy" title="创建人"></vxe-column> <vxe-column min-width="120" field="createBy" title="创建人"></vxe-column>
<vxe-column min-width="180" field="createTime" title="创建时间"></vxe-column> <vxe-column min-width="180" field="createTime" title="创建时间"></vxe-column>
<vxe-column min-width="120" field="auditBy" title="审核人"></vxe-column> <vxe-column min-width="120" field="auditBy" title="审核人"></vxe-column>
<vxe-column min-width="180" field="auditTime" title="审核时间"></vxe-column> <vxe-column min-width="180" field="auditTime" title="审核时间"></vxe-column>
<vxe-column field="title" title="操作" fixed="right" min-width="120"> <vxe-column field="title" title="操作" fixed="right" min-width="140">
<template #default="{ row }"> <template #default="{ row }">
<n-space> <n-space>
<n-button @click="onEditDoc(row)" v-if="row.docStatus === '00' || row.docStatus === '03'" strong <n-button @click="onEditDoc(row)" v-if="row.docStatus === '00' || row.docStatus === '03'" strong
text type="info">编辑</n-button> text type="info">编辑</n-button>
<n-button @click="onSubmitProductDoc(row)" v-if="row.docStatus === '00' || row.docStatus === '03'" <n-button @click="onSubmitProductDoc(row)"
strong text type="info">提交</n-button> v-if="row.docStatus === '00' || row.docStatus === '03'" strong text type="info">提交</n-button>
<n-button v-if="row.docStatus === '00' || row.docStatus === '03'" strong text type="info" <n-button v-if="row.docStatus === '00' || row.docStatus === '03'" strong text type="info"
@click="onDeleteProductDoc(row)">删除</n-button> @click="onDeleteProductDoc(row)">删除</n-button>
<n-button @click="onPreDoc(row)" v-if="row.docStatus !== '00' && row.docStatus !== '03'" strong text <n-button @click="onPreDoc(row)" v-if="row.docStatus !== '00' && row.docStatus !== '03'" strong
type="info">预览文档</n-button> text type="info">预览文档</n-button>
<n-button @click="onAuditDoc(row)" v-if="row.docStatus === '01'" strong text <n-button @click="onAuditDoc(row)" v-if="row.docStatus === '01'" strong text
type="info">审核</n-button> type="info">审核</n-button>
<n-button @click="onBackOffDoc(row)" v-if="row.analyzeStatus && row.analyzeStatus === '02'" strong <n-button @click="onBackOffDoc(row)" v-if="row.analyzeStatus && row.analyzeStatus === '02'"
text type="info">撤回解析</n-button> strong text type="info">撤回解析</n-button>
<n-button @click="onAnalysisDoc(row)" <n-button @click="onAnalysisDoc(row)"
v-if="row.analyzeStatus && row.analyzeStatus !== '00' && row.analyzeStatus !== '01'" strong text v-if="row.analyzeStatus && row.analyzeStatus !== '00' && row.analyzeStatus !== '01'" strong
type="info">重新解析</n-button> text type="info">重新解析</n-button>
</n-space> </n-space>
</template> </template>
</vxe-column> </vxe-column>
...@@ -622,19 +717,21 @@ onMounted(() => { ...@@ -622,19 +717,21 @@ onMounted(() => {
<icon-custom-empty-data class="text-320px text-primary" /> <icon-custom-empty-data class="text-320px text-primary" />
</template> </template>
</vxe-table> </vxe-table>
</n-layout>
</n-layout>
</div> </div>
</n-spin> </n-spin>
</n-card> </n-card>
</n-modal> </n-modal>
<n-modal v-model:show="showAddProductModal"> <n-modal :mask-closable="false" :close-on-esc="false" v-model:show="showAddProductModal">
<n-card style="max-width: 600px;" title="新增产品" :bordered="false" size="huge" role="dialog" aria-modal="true"> <n-card style="max-width: 600px;" title="新增产品" :bordered="false" size="huge" role="dialog" aria-modal="true">
<template #header-extra> <template #header-extra>
<Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="showAddProductModal = false" /> <Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="showAddProductModal = false" />
</template> </template>
<n-form ref="addProductFormRef" :model="addFormModal" :rules="rules" label-placement="left" label-width="auto" <n-form ref="addProductFormRef" :model="addFormModal" :rules="rules" label-placement="left" label-width="auto"
require-mark-placement="right-hanging" :size="size" :style="{ require-mark-placement="right-hanging" :style="{
maxWidth: '640px', maxWidth: '640px',
}"> }">
<n-form-item label="产品编码" path="productCode"> <n-form-item label="产品编码" path="productCode">
...@@ -661,18 +758,20 @@ onMounted(() => { ...@@ -661,18 +758,20 @@ onMounted(() => {
</n-modal> </n-modal>
<n-modal v-model:show="isShowAddDocModal"> <n-modal :mask-closable="false" :close-on-esc="false" v-model:show="isShowAddDocModal">
<n-card style="max-width: 600px;" title="新增文档" :bordered="false" size="huge" role="dialog" aria-modal="true"> <n-card style="max-width: 600px;" :title="operateTitle" :bordered="false" size="huge" role="dialog"
aria-modal="true">
<template #header-extra> <template #header-extra>
<Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="isShowAddDocModal = false" /> <Icon icon="ic:sharp-close" class="text-size-22px cursor-pointer" @click="isShowAddDocModal = false" />
</template> </template>
<n-form ref="addDocFormRef" :model="addDocForm" :rules="addDocRules" label-placement="left" label-width="auto" <n-form ref="addDocFormRef" :model="addDocForm" :rules="addDocRules" label-placement="left" label-width="auto"
require-mark-placement="right-hanging" :size="size" :style="{ require-mark-placement="right-hanging" :style="{
maxWidth: '640px', maxWidth: '640px',
}"> }">
<n-form-item label="文档类型" path="docTypeCode"> <n-form-item label="文档类型" path="docTypeCode">
<n-select :disabled="operateType === 'preview' || operateType === 'audit'" <n-select label-field="label" value-field="key"
v-model:value="addDocForm.docTypeCode" clearable placeholder="文档类型" :options="productStatusOptions" /> :disabled="operateType === 'preview' || operateType === 'audit'" v-model:value="addDocForm.docTypeCode"
clearable placeholder="文档类型" :options="menuOptions" />
</n-form-item> </n-form-item>
<n-form-item label="上传文档" path="docTypeCode"> <n-form-item label="上传文档" path="docTypeCode">
<div> <div>
...@@ -681,8 +780,8 @@ onMounted(() => { ...@@ -681,8 +780,8 @@ onMounted(() => {
</n-alert> </n-alert>
<br /> <br />
<n-upload :disabled="operateType === 'preview' || operateType === 'audit'" @preview="handlePreview" <n-upload :disabled="operateType === 'preview' || operateType === 'audit'" @preview="handlePreview"
:default-file-list="defaultFileList" accept="'.txt, .docx, .pdf, .doc, .wps, .ett, .xls, .xlsx'" :default-file-list="defaultFileList" accept=".txt,.docx,.pdf,.doc,.wps,.ett,.xls,.xlsx" :max="1"
:max="1" action="https://naive-upload.free.beeceptor.com/" :headers="{ action="https://naive-upload.free.beeceptor.com/" :headers="{
'naive-info': 'hello!', 'naive-info': 'hello!',
}" :data="{ }" :data="{
'naive-data': 'cool! naive!', 'naive-data': 'cool! naive!',
...@@ -700,8 +799,8 @@ onMounted(() => { ...@@ -700,8 +799,8 @@ onMounted(() => {
<n-form-item <n-form-item
v-if="operateType === 'audit' || operateType === 'preview' && (addDocForm.docStatus === '02' || addDocForm.docStatus === '03')" v-if="operateType === 'audit' || operateType === 'preview' && (addDocForm.docStatus === '02' || addDocForm.docStatus === '03')"
label="审核意见" path="auditDesc"> label="审核意见" path="auditDesc">
<n-input :disabled="operateType === 'preview'" type="textarea" v-model:value="addDocForm.auditDesc" <n-input :disabled="operateType === 'preview'" maxlength="200" show-count type="textarea"
placeholder="审核意见" /> v-model:value="addDocForm.auditDesc" placeholder="审核意见" />
</n-form-item> </n-form-item>
</n-form> </n-form>
<template #footer v-if="operateType !== 'preview'"> <template #footer v-if="operateType !== 'preview'">
...@@ -717,4 +816,10 @@ onMounted(() => { ...@@ -717,4 +816,10 @@ onMounted(() => {
</n-modal> </n-modal>
</div> </div>
</template> </template>
·
<style>
.define-mini-size .n-base-loading {
font-size: 12px !important;
margin-left: 4px;
}
</style>
...@@ -14,7 +14,7 @@ export default defineConfig(configEnv => { ...@@ -14,7 +14,7 @@ export default defineConfig(configEnv => {
const viteCommand = configEnv.command; const viteCommand = configEnv.command;
const vitePath = resolvePath('./', import.meta.url); const vitePath = resolvePath('./', import.meta.url);
return { return {
base: '/chonglin-admin/', base: '/sdream-admin-fe/',
resolve: { resolve: {
alias: { alias: {
'~': vitePath.root, '~': vitePath.root,
......
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