第一版业务完成初始化(余下 物种性状-植物,分子信息,损失数据,疫情截获) 待开发
This commit is contained in:
parent
a5a74a2ead
commit
c988bf05d2
@ -13,7 +13,7 @@
|
||||
content="vue-next-admin,基于 vue3 + CompositionAPI + typescript + vite + element plus,适配手机、平板、pc 的后台开源免费管理系统模板!vue-prev-admin,基于 vue2 + element ui,适配手机、平板、pc 的后台开源免费管理系统模板!"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<title>gfast3.2后台管理系统</title>
|
||||
<title>外来入侵物种智能决策可视化模拟后台管理系统</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
41
package-lock.json
generated
41
package-lock.json
generated
@ -34,6 +34,8 @@
|
||||
"sortablejs": "^1.15.2",
|
||||
"spark-md5": "^3.0.2",
|
||||
"splitpanes": "^3.1.5",
|
||||
"v-viewer": "^3.0.22",
|
||||
"viewerjs": "^1.11.7",
|
||||
"vue": "^3.4.21",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
@ -1391,10 +1393,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"name": "@sxzz/popperjs-es",
|
||||
"version": "2.11.7",
|
||||
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
|
||||
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
|
||||
"resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.7.tgz",
|
||||
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.2.0",
|
||||
@ -1686,10 +1691,8 @@
|
||||
},
|
||||
"node_modules/@types/js-cookie": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmmirror.com/@types/js-cookie/-/js-cookie-3.0.6.tgz",
|
||||
"integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.20",
|
||||
@ -1719,10 +1722,8 @@
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.14.0.tgz",
|
||||
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/sortablejs": {
|
||||
"version": "1.15.8",
|
||||
@ -3515,7 +3516,6 @@
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
@ -3749,7 +3749,6 @@
|
||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -4413,6 +4412,26 @@
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/v-viewer": {
|
||||
"version": "3.0.22",
|
||||
"resolved": "https://registry.npmmirror.com/v-viewer/-/v-viewer-3.0.22.tgz",
|
||||
"integrity": "sha512-uYyP5FPT4K/Sd5D1mhB2HMVV8jnf6zYy2HD1PHCNAO6s2Iway+Wls60pwh7y4F3e2Nlc9549Pvy2HXaq8PKrAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.21",
|
||||
"viewerjs": "^1.11.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"viewerjs": "^1.11.0",
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/viewerjs": {
|
||||
"version": "1.11.7",
|
||||
"resolved": "https://registry.npmmirror.com/viewerjs/-/viewerjs-1.11.7.tgz",
|
||||
"integrity": "sha512-0JuVqOmL5v1jmEAlG5EBDR3XquxY8DWFQbFMprOXgaBB0F7Q/X9xWdEaQc59D8xzwkdUgXEMSSknTpriq95igg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "6.3.4",
|
||||
"integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==",
|
||||
|
@ -36,6 +36,8 @@
|
||||
"sortablejs": "^1.15.2",
|
||||
"spark-md5": "^3.0.2",
|
||||
"splitpanes": "^3.1.5",
|
||||
"v-viewer": "^3.0.22",
|
||||
"viewerjs": "^1.11.7",
|
||||
"vue": "^3.4.21",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
|
23
pnpm-lock.yaml
generated
23
pnpm-lock.yaml
generated
@ -83,6 +83,12 @@ importers:
|
||||
splitpanes:
|
||||
specifier: ^3.1.5
|
||||
version: 3.2.0(vue@3.5.18(typescript@5.9.2))
|
||||
v-viewer:
|
||||
specifier: ^3.0.22
|
||||
version: 3.0.22(viewerjs@1.11.7)(vue@3.5.18(typescript@5.9.2))
|
||||
viewerjs:
|
||||
specifier: ^1.11.7
|
||||
version: 1.11.7
|
||||
vue:
|
||||
specifier: ^3.4.21
|
||||
version: 3.5.18(typescript@5.9.2)
|
||||
@ -1725,6 +1731,15 @@ packages:
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
v-viewer@3.0.22:
|
||||
resolution: {integrity: sha512-uYyP5FPT4K/Sd5D1mhB2HMVV8jnf6zYy2HD1PHCNAO6s2Iway+Wls60pwh7y4F3e2Nlc9549Pvy2HXaq8PKrAg==}
|
||||
peerDependencies:
|
||||
viewerjs: ^1.11.0
|
||||
vue: ^3.0.0
|
||||
|
||||
viewerjs@1.11.7:
|
||||
resolution: {integrity: sha512-0JuVqOmL5v1jmEAlG5EBDR3XquxY8DWFQbFMprOXgaBB0F7Q/X9xWdEaQc59D8xzwkdUgXEMSSknTpriq95igg==}
|
||||
|
||||
vite-plugin-cdn-import@1.0.1:
|
||||
resolution: {integrity: sha512-lgjLxgwFSKvJLbqjVBirUZ0rQo00GpUGJzRpgQu8RyBw9LA7jaqG6fUMQzBC9qWmTGabPC3iOzwCcoi7PseRAQ==}
|
||||
|
||||
@ -3389,6 +3404,14 @@ snapshots:
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
v-viewer@3.0.22(viewerjs@1.11.7)(vue@3.5.18(typescript@5.9.2)):
|
||||
dependencies:
|
||||
lodash-es: 4.17.21
|
||||
viewerjs: 1.11.7
|
||||
vue: 3.5.18(typescript@5.9.2)
|
||||
|
||||
viewerjs@1.11.7: {}
|
||||
|
||||
vite-plugin-cdn-import@1.0.1(rollup@4.46.2)(vite@6.3.4(@types/node@20.19.9)(sass@1.89.2)):
|
||||
dependencies:
|
||||
rollup-plugin-external-globals: 0.10.0(rollup@4.46.2)
|
||||
|
@ -1,70 +1,77 @@
|
||||
import request from '/@/utils/request';
|
||||
import {ref ,toRefs,ToRefs} from 'vue'
|
||||
import { ref, toRefs, ToRefs } from 'vue';
|
||||
// 根据字典类型查询字典数据信息
|
||||
export function getDicts(dictType :string,defaultValue?:string):Promise<any> {
|
||||
let dv = defaultValue??''
|
||||
let params ={
|
||||
dictType:dictType,
|
||||
defaultValue:dv
|
||||
}
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/getDictData',
|
||||
method: 'get',
|
||||
params:params
|
||||
})
|
||||
export function getDicts(dictType: string, defaultValue?: string): Promise<any> {
|
||||
let dv = defaultValue ?? '';
|
||||
let params = {
|
||||
dictType: dictType,
|
||||
defaultValue: dv,
|
||||
};
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/getDictData',
|
||||
method: 'get',
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典数据
|
||||
*/
|
||||
export function useDict(...args:string[]):ToRefs<any>{
|
||||
const res:any = ref({});
|
||||
args.forEach((d:string) => {
|
||||
res.value[d] = [];
|
||||
getDicts(d).then(resp => {
|
||||
res.value[d] = resp.data.values.map((p:any) => ({ label: p.value, value: p.key, isDefault: p.isDefault }))
|
||||
})
|
||||
})
|
||||
return toRefs(res.value);
|
||||
export function useDict(...args: string[]): ToRefs<any> {
|
||||
const res: any = ref({});
|
||||
args.forEach((d: string) => {
|
||||
res.value[d] = [];
|
||||
getDicts(d).then((resp) => {
|
||||
res.value[d] = resp.data.values.map((p: any) => ({
|
||||
label: p.value,
|
||||
value: p.key,
|
||||
isDefault: p.isDefault,
|
||||
}));
|
||||
});
|
||||
});
|
||||
return toRefs(res.value);
|
||||
}
|
||||
|
||||
|
||||
export function getDataList(query:Object) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/list',
|
||||
method: 'get',
|
||||
params:query
|
||||
})
|
||||
export function getDataList(query: Object) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
export function getData(dictCode:number) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/get',
|
||||
method: 'get',
|
||||
params:{dictCode}
|
||||
})
|
||||
export function getData(dictCode: number) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/get',
|
||||
method: 'get',
|
||||
params: { dictCode },
|
||||
});
|
||||
}
|
||||
|
||||
export function addData(data:any) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/add',
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
export function addData(data: any) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/add',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function editData(data:any) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/edit',
|
||||
method: 'put',
|
||||
data:data
|
||||
})
|
||||
export function editData(data: any) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/edit',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteData(ids:number[]) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/delete',
|
||||
method: 'delete',
|
||||
data:{ids}
|
||||
})
|
||||
export function deleteData(ids: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/system/dict/data/delete',
|
||||
method: 'delete',
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
export function formatGetDicts(data: any) {
|
||||
return data.data.values;
|
||||
}
|
||||
|
495
src/components/FilePreview/index.vue
Normal file
495
src/components/FilePreview/index.vue
Normal file
@ -0,0 +1,495 @@
|
||||
<!-- <template>
|
||||
<div>
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
fullscreen
|
||||
append-to-body
|
||||
:destroy-on-close="true"
|
||||
class="file-preview-dialog"
|
||||
>
|
||||
<div class="file-preview-container">
|
||||
<div class="file-preview-left">
|
||||
<div class="file-list-header">
|
||||
<h3>文件列表</h3>
|
||||
</div>
|
||||
<div
|
||||
v-for="(files, groupName) in groupedFiles"
|
||||
:key="groupName"
|
||||
class="file-group"
|
||||
>
|
||||
<div class="group-header" v-if="groupName !== '__ungrouped'">
|
||||
{{ groupName }}
|
||||
</div>
|
||||
<div
|
||||
v-for="(file, index) in files"
|
||||
:key="file.uid || index"
|
||||
:class="[
|
||||
'file-item',
|
||||
{ active: currentFile && currentFile.uid === file.uid }
|
||||
]"
|
||||
@click="changePreviewFile(file)"
|
||||
>
|
||||
<div class="file-item-indicator"></div>
|
||||
<span class="file-item-text">{{ file.name }}</span>
|
||||
<i
|
||||
v-if="showDownloadIcon"
|
||||
class="el-icon-download"
|
||||
@click.stop="downloadFile(file)"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file-preview-right" v-loading="loading">
|
||||
<div v-if="!currentFile" class="file-item-content">
|
||||
<el-empty description="请选择要预览的文件"></el-empty>
|
||||
</div>
|
||||
<div v-else-if="previewError" class="file-item-content">
|
||||
<el-empty description="无法预览此文件格式"></el-empty>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="downloadFile(currentFile)"
|
||||
>
|
||||
下载文件
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-else class="file-item-content">
|
||||
<img v-if="isImage" :src="currentFile.url" class="image-preview" />
|
||||
<iframe
|
||||
v-else-if="isPdf"
|
||||
:src="currentFile.url"
|
||||
class="pdf-preview"
|
||||
></iframe>
|
||||
|
||||
<vue-office-docx
|
||||
v-else-if="isOffice"
|
||||
:src="currentFile.url"
|
||||
:config="docxConfig"
|
||||
class="docx-preview"
|
||||
@rendered="docxRendered"
|
||||
/>
|
||||
<div v-else-if="isXlsx" class="file-item-content">
|
||||
<VueOfficeExcel
|
||||
:src="currentFile.url"
|
||||
:config="docxConfig"
|
||||
class="docx-preview"
|
||||
@rendered="docxRendered"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="isHtml"
|
||||
class="html-preview"
|
||||
v-html="htmlContent"
|
||||
></div>
|
||||
|
||||
<pre v-else-if="isText" class="text-preview">{{ textContent }}</pre>
|
||||
|
||||
<div v-else class="unsupported-format">
|
||||
<el-empty description="此文件格式暂不支持预览"></el-empty>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="downloadFile(currentFile)"
|
||||
>
|
||||
下载文件
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import VueOfficeDocx from '@vue-office/docx'
|
||||
import '@vue-office/docx/lib/index.css'
|
||||
import VueOfficeExcel from '@vue-office/excel'
|
||||
import '@vue-office/excel/lib/index.css'
|
||||
export default {
|
||||
name: 'FilePreview',
|
||||
components: {
|
||||
VueOfficeDocx,
|
||||
VueOfficeExcel
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
files: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
showDownloadIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
xlsxData: [], // 存储解析后的表格数据
|
||||
xlsxColumns: [], // 存储表格列信息
|
||||
dialogVisible: false,
|
||||
fileList: [],
|
||||
activeIndex: 0,
|
||||
currentFile: null,
|
||||
loading: false,
|
||||
previewError: false,
|
||||
htmlContent: '',
|
||||
textContent: '',
|
||||
docxConfig: {
|
||||
className: 'docx-preview',
|
||||
useBase64URL: true,
|
||||
useMathMLPolyfill: true,
|
||||
inWrapper: false,
|
||||
ignoreWidth: false,
|
||||
ignoreHeight: false,
|
||||
ignoreFonts: false,
|
||||
breakPages: true,
|
||||
ignoreLastRenderedPageBreak: true,
|
||||
debug: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isImage() {
|
||||
return (
|
||||
this.currentFile &&
|
||||
/\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(this.currentFile.name)
|
||||
)
|
||||
},
|
||||
isPdf() {
|
||||
return this.currentFile && /\.pdf$/i.test(this.currentFile.name)
|
||||
},
|
||||
isHtml() {
|
||||
return this.currentFile && /\.(html|htm)$/i.test(this.currentFile.name)
|
||||
},
|
||||
isText() {
|
||||
return (
|
||||
this.currentFile &&
|
||||
/\.(txt|md|json|xml|css|js)$/i.test(this.currentFile.name)
|
||||
)
|
||||
},
|
||||
isOffice() {
|
||||
return (
|
||||
// this.currentFile && /\.(docx|xlsx|pptx)$/i.test(this.currentFile.name)
|
||||
this.currentFile && /\.(docx)$/i.test(this.currentFile.name)
|
||||
)
|
||||
},
|
||||
isXlsx() {
|
||||
return (
|
||||
this.currentFile &&
|
||||
(/\.xlsx$/i.test(this.currentFile.name) ||
|
||||
/\.xls$/i.test(this.currentFile.name))
|
||||
)
|
||||
},
|
||||
// Group files by the 'group' property
|
||||
groupedFiles() {
|
||||
const groups = {}
|
||||
|
||||
this.fileList.forEach(file => {
|
||||
const groupName = file.group || '__ungrouped'
|
||||
if (!groups[groupName]) {
|
||||
groups[groupName] = []
|
||||
}
|
||||
groups[groupName].push(file)
|
||||
})
|
||||
|
||||
return groups
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.dialogVisible = val
|
||||
},
|
||||
dialogVisible(val) {
|
||||
this.$emit('input', val)
|
||||
if (!val) {
|
||||
this.$emit('close')
|
||||
}
|
||||
},
|
||||
files: {
|
||||
handler(val) {
|
||||
this.fileList = val
|
||||
if (val.length > 0 && !this.currentFile) {
|
||||
this.changePreviewFile(val[this.index || 0])
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
index: {
|
||||
handler(val) {
|
||||
if (this.fileList.length > 0) {
|
||||
const index = Math.min(val, this.fileList.length - 1)
|
||||
if (index !== this.activeIndex) {
|
||||
this.changePreviewFile(this.fileList[index])
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openDialog(files, initialIndex = 0) {
|
||||
if (files) {
|
||||
this.fileList = Array.isArray(files) ? files : [files]
|
||||
}
|
||||
this.dialogVisible = true
|
||||
if (this.fileList.length > 0) {
|
||||
const index = Math.min(initialIndex, this.fileList.length - 1)
|
||||
this.changePreviewFile(this.fileList[index])
|
||||
}
|
||||
},
|
||||
closeDialog() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
async changePreviewFile(file) {
|
||||
if (!file) return
|
||||
this.currentFile = file
|
||||
this.loading = true
|
||||
this.previewError = false
|
||||
this.htmlContent = ''
|
||||
this.textContent = ''
|
||||
|
||||
try {
|
||||
if (this.isHtml) {
|
||||
await this.loadHtmlContent(file)
|
||||
} else if (this.isText) {
|
||||
await this.loadTextContent(file)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Preview error:', error)
|
||||
this.previewError = true
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async loadHtmlContent(file) {
|
||||
try {
|
||||
const response = await axios.get(file.url)
|
||||
this.htmlContent = response.data
|
||||
} catch (error) {
|
||||
this.previewError = true
|
||||
console.error('Failed to load HTML content:', error)
|
||||
}
|
||||
},
|
||||
async loadTextContent(file) {
|
||||
try {
|
||||
const response = await axios.get(file.url)
|
||||
this.textContent = response.data
|
||||
} catch (error) {
|
||||
this.previewError = true
|
||||
console.error('Failed to load text content:', error)
|
||||
}
|
||||
},
|
||||
docxRendered() {
|
||||
this.loading = false
|
||||
console.log('DOCX file rendered successfully')
|
||||
},
|
||||
downloadFile(file) {
|
||||
if (!file || !file.url) return
|
||||
const link = document.createElement('a')
|
||||
link.href = file.url
|
||||
link.setAttribute('download', file.name)
|
||||
link.setAttribute('target', '_blank')
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.file-preview-dialog {
|
||||
.el-dialog__header {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
height: calc(100vh - 50px);
|
||||
}
|
||||
}
|
||||
|
||||
.file-preview-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.file-preview-left {
|
||||
width: 20%;
|
||||
padding: 20px;
|
||||
background: #ffffff;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-list-header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.file-list-header h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.file-group {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.group-header {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
padding: 5px 0;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
position: relative;
|
||||
padding: 0.8rem 1rem;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #f8f9fa;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
background: #f1f3f5;
|
||||
}
|
||||
|
||||
.file-item.active {
|
||||
background: #ecf5ff;
|
||||
}
|
||||
|
||||
.file-item-indicator {
|
||||
width: 2px;
|
||||
height: 16px;
|
||||
background: #c0c4cc;
|
||||
border-radius: 2px;
|
||||
margin-right: 12px;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.file-item.active .file-item-indicator {
|
||||
background: #409eff;
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.file-item-text {
|
||||
color: #606266;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.file-preview-right {
|
||||
flex: 1;
|
||||
background: #f5f7f9;
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.file-item-content {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.file-preview-right::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.file-preview-right::-webkit-scrollbar-track {
|
||||
background: #f1f3f5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.file-preview-right::-webkit-scrollbar-thumb {
|
||||
background: #c0c4cc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.file-preview-right::-webkit-scrollbar-thumb:hover {
|
||||
background: #909399;
|
||||
}
|
||||
|
||||
.image-preview {
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.pdf-preview {
|
||||
width: 100%;
|
||||
height: 80vh;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.docx-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.html-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.text-preview {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.unsupported-format {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.unsupported-format .el-button {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.file-item-content .el-table {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
-->
|
@ -13,6 +13,7 @@
|
||||
@row-dblclick="onRowDblClick"
|
||||
@selection-change="onSelectionChange"
|
||||
@sort-change="onSortChange"
|
||||
@cell-dblclick="onCellClick"
|
||||
v-bind="tableProps"
|
||||
>
|
||||
<!-- 展开行 -->
|
||||
@ -133,6 +134,7 @@ const emit = defineEmits<{
|
||||
(e: 'row-dblclick', row: any): void;
|
||||
(e: 'selection-change', selection: any[]): void;
|
||||
(e: 'sort-change', col: TableColumnCtx<any>): void;
|
||||
(e: 'cell-click',row:any,col:any):void
|
||||
}>();
|
||||
|
||||
// 表格高度
|
||||
@ -157,7 +159,7 @@ onBeforeUnmount(() => {
|
||||
const onRowDblClick = (row: any) => emit('row-dblclick', row);
|
||||
const onSelectionChange = (selection: any[]) => emit('selection-change', selection);
|
||||
const onSortChange = (col: TableColumnCtx<any>) => emit('sort-change', col);
|
||||
|
||||
const onCellClick=(row:any,col:any)=>emit('cell-click',row,col);
|
||||
// 暴露 Element Plus Table API
|
||||
const tableRef = ref();
|
||||
const clearSelection = () => tableRef.value?.clearSelection();
|
||||
|
@ -82,7 +82,7 @@ const form = ref<AuditFormModel>({
|
||||
});
|
||||
const open = (row: AuditFormModel, userOptions: UserItem[]) => {
|
||||
visible.value = true;
|
||||
row.auditStatus='1'
|
||||
row.auditStatus = '1';
|
||||
form.value = row;
|
||||
userList.value = userOptions;
|
||||
};
|
||||
@ -92,6 +92,11 @@ defineExpose({
|
||||
const handleSubmit = () => {
|
||||
formRef.value.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
for (const key in form.value) {
|
||||
if (key=='auditDate' && (form.value.auditDate as any) instanceof Date) {
|
||||
form.value.auditDate = form.value.auditDate.toLocaleString();
|
||||
}
|
||||
}
|
||||
emit('submit', form.value);
|
||||
handleCancel();
|
||||
} else {
|
||||
|
@ -1,90 +1,104 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="localVisible"
|
||||
:title="title"
|
||||
:width="width"
|
||||
:close-on-click-modal="false"
|
||||
@closed="handleCancel"
|
||||
@open="handleOpen"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="modelValue"
|
||||
:rules="rules"
|
||||
:label-width="labelWidth"
|
||||
:label-position="labelPosition"
|
||||
>
|
||||
<el-row :gutter="gutter">
|
||||
<template v-for="(item, index) in fields" :key="item.prop">
|
||||
<el-col :span="item.span||24">
|
||||
<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
|
||||
<!-- 插槽优先 -->
|
||||
<slot :name="item.prop" :item="item" :form="modelValue">
|
||||
<component
|
||||
:is="getComponent(item.type)"
|
||||
v-model="modelValue[item.prop]"
|
||||
v-bind="getProps(item)"
|
||||
>
|
||||
<!-- 下拉选项 -->
|
||||
<template v-if="item.type === 'select'" #default>
|
||||
<el-option
|
||||
v-for="opt in item.options || []"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</template>
|
||||
</component>
|
||||
</slot>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-dialog
|
||||
v-model="localVisible"
|
||||
:title="title"
|
||||
:width="width"
|
||||
:close-on-click-modal="false"
|
||||
@closed="handleCancel"
|
||||
@open="handleOpen"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="modelValue"
|
||||
:rules="rules"
|
||||
:label-width="labelWidth"
|
||||
:label-position="labelPosition"
|
||||
>
|
||||
<el-row :gutter="gutter">
|
||||
<template v-for="(item, index) in fields" :key="item.prop">
|
||||
<el-col :span="item.span || 24">
|
||||
<el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
|
||||
<!-- 插槽优先 -->
|
||||
<slot :name="item.prop" :item="item" :form="modelValue">
|
||||
<component
|
||||
:is="getComponent(item.type)"
|
||||
v-model="modelValue[item.prop]"
|
||||
v-bind="getProps(item)"
|
||||
>
|
||||
<!-- 下拉选项 -->
|
||||
<template v-if="item.type === 'select'" #default>
|
||||
<el-option
|
||||
v-for="opt in item.options || []"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="item.type === 'radio'">
|
||||
<el-radio
|
||||
v-model="modelValue[item.prop]"
|
||||
v-for="opt in item.options"
|
||||
:key="opt.value"
|
||||
:value="opt.value"
|
||||
v-bind="getProps(item)"
|
||||
>
|
||||
{{ opt.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</component>
|
||||
</slot>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<template #footer v-if="showFooter">
|
||||
<slot name="footer">
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</slot>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 操作按钮 -->
|
||||
<template #footer v-if="showFooter">
|
||||
<slot name="footer">
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</slot>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import {PopupFormField} from '../type'
|
||||
|
||||
import { PopupFormField } from '../type';
|
||||
import UploadImg from '/@/components/uploadImg/index.vue'
|
||||
defineOptions({ name: 'ModalForm' });
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
title?: string;
|
||||
width?: string;
|
||||
modelValue: Record<string, any>;
|
||||
fields: PopupFormField[];
|
||||
labelWidth?: string;
|
||||
labelPosition?: 'left' | 'right' | 'top';
|
||||
gutter?: number;
|
||||
showFooter?: boolean;
|
||||
visible: boolean;
|
||||
title?: string;
|
||||
width?: string;
|
||||
modelValue: Record<string, any>;
|
||||
fields: PopupFormField[];
|
||||
labelWidth?: string;
|
||||
labelPosition?: 'left' | 'right' | 'top';
|
||||
gutter?: number;
|
||||
showFooter?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
(e: 'update:modelValue', val: Record<string, any>): void;
|
||||
(e: 'submit', val:any): void;
|
||||
(e: 'cancel'): void;
|
||||
(e: 'open'): void;
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
(e: 'update:modelValue', val: Record<string, any>): void;
|
||||
(e: 'submit', val: any): void;
|
||||
(e: 'cancel'): void;
|
||||
(e: 'open'): void;
|
||||
}>();
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const localVisible = ref(props.visible);
|
||||
|
||||
watch(() => props.visible, val => localVisible.value = val);
|
||||
watch(localVisible, val => emit('update:visible', val));
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => (localVisible.value = val)
|
||||
);
|
||||
watch(localVisible, (val) => emit('update:visible', val));
|
||||
|
||||
const labelWidth = computed(() => props.labelWidth || '100px');
|
||||
const labelPosition = computed(() => props.labelPosition || 'right');
|
||||
@ -92,78 +106,90 @@ const gutter = computed(() => props.gutter || 10);
|
||||
const showFooter = computed(() => props.showFooter !== false);
|
||||
|
||||
const rules = computed<FormRules>(() => {
|
||||
const map: FormRules = {};
|
||||
props.fields.forEach(field => {
|
||||
if (field.rules) map[field.prop] = field.rules;
|
||||
});
|
||||
return map;
|
||||
const map: FormRules = {};
|
||||
props.fields.forEach((field) => {
|
||||
if (field.rules) map[field.prop] = field.rules;
|
||||
});
|
||||
return map;
|
||||
});
|
||||
|
||||
const componentMap: Record<string, any> = {
|
||||
input: 'el-input',
|
||||
select: 'el-select',
|
||||
date: 'el-date-picker',
|
||||
dateTime: 'el-date-picker',
|
||||
daterange: 'el-date-picker',
|
||||
datetimerange: 'el-date-picker',
|
||||
switch: 'el-switch',
|
||||
radio: 'el-radio-group',
|
||||
checkbox: 'el-checkbox-group',
|
||||
upload: 'el-upload',
|
||||
cascader: 'el-cascader',
|
||||
rate: 'el-rate',
|
||||
slider: 'el-slider',
|
||||
timePicker: 'el-time-picker',
|
||||
inputNumber: 'el-input-number',
|
||||
colorPicker: 'el-color-picker',
|
||||
treeSelect: 'el-tree-select',
|
||||
input: 'el-input',
|
||||
select: 'el-select',
|
||||
date: 'el-date-picker',
|
||||
dateTime: 'el-date-picker',
|
||||
daterange: 'el-date-picker',
|
||||
datetimerange: 'el-date-picker',
|
||||
switch: 'el-switch',
|
||||
radio: 'el-radio-group',
|
||||
checkbox: 'el-checkbox-group',
|
||||
upload: UploadImg,
|
||||
cascader: 'el-cascader',
|
||||
rate: 'el-rate',
|
||||
slider: 'el-slider',
|
||||
colorPicker: 'el-color-picker',
|
||||
};
|
||||
|
||||
const getComponent = (type?: string) => componentMap[type || 'input'] || 'el-input';
|
||||
|
||||
const getProps = (item: PopupFormField) => {
|
||||
const props = item.componentProps || {};
|
||||
if (item.type === 'select') {
|
||||
return { ...props, filterable: true };
|
||||
}
|
||||
if (item.type === 'daterange' || item.type === 'datetimerange') {
|
||||
return {
|
||||
...props,
|
||||
type: item.type,
|
||||
'value-format': 'YYYY-MM-DD',
|
||||
'range-separator': '至',
|
||||
'start-placeholder': '开始日期',
|
||||
'end-placeholder': '结束日期',
|
||||
};
|
||||
}
|
||||
return props;
|
||||
const props = item.componentProps || {};
|
||||
if (item.type === 'select') {
|
||||
return { ...props, filterable: true };
|
||||
}
|
||||
if (item.type === 'daterange' || item.type === 'datetimerange') {
|
||||
return {
|
||||
...props,
|
||||
type: item.type,
|
||||
'value-format': 'YYYY-MM-DD',
|
||||
'range-separator': '至',
|
||||
'start-placeholder': '开始日期',
|
||||
'end-placeholder': '结束日期',
|
||||
};
|
||||
}
|
||||
if (item.type === 'radio') {
|
||||
return {
|
||||
...props,
|
||||
size: props.size || 'default',
|
||||
disabled: props.disabled || false,
|
||||
type: props.button ? 'button' : props.type,
|
||||
};
|
||||
}
|
||||
|
||||
return props;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
await formRef.value.validate((valid) => {
|
||||
if (valid) emit('submit', props.modelValue);
|
||||
});
|
||||
if (!formRef.value) return;
|
||||
await formRef.value.validate((valid) => {
|
||||
const model = { ...props.modelValue };
|
||||
for (const key in model) {
|
||||
if (model[key] instanceof Date) {
|
||||
model[key] = model[key].toLocaleString();
|
||||
}
|
||||
}
|
||||
if (valid) emit('submit', model);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('cancel');
|
||||
localVisible.value = false;
|
||||
formRef.value?.resetFields();
|
||||
emit('cancel');
|
||||
localVisible.value = false;
|
||||
formRef.value?.resetFields();
|
||||
};
|
||||
|
||||
const handleOpen = () => {
|
||||
emit('open');
|
||||
emit('open');
|
||||
};
|
||||
|
||||
const loadOptions = async () => {
|
||||
const loaded = new Set();
|
||||
for (const field of props.fields) {
|
||||
if (field.fetchOptions && !loaded.has(field.fetchOptions)) {
|
||||
field.options = await field.fetchOptions();
|
||||
loaded.add(field.fetchOptions);
|
||||
}
|
||||
}
|
||||
const loaded = new Set();
|
||||
for (const field of props.fields) {
|
||||
if (field.fetchOptions && !loaded.has(field.fetchOptions)) {
|
||||
field.options = await field.fetchOptions();
|
||||
loaded.add(field.fetchOptions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(loadOptions);
|
||||
@ -171,6 +197,6 @@ onMounted(loadOptions);
|
||||
|
||||
<style scoped>
|
||||
.form-item-wrapper {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
224
src/components/imgsPreview/index.vue
Normal file
224
src/components/imgsPreview/index.vue
Normal file
@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
fullscreen
|
||||
append-to-body
|
||||
:destroy-on-close="true"
|
||||
class="file-preview-dialog"
|
||||
>
|
||||
<div class="file-preview-container">
|
||||
<!-- 左侧文件列表 -->
|
||||
<div class="file-preview-left">
|
||||
<div class="file-list-header">
|
||||
<h3>图片列表</h3>
|
||||
</div>
|
||||
<div
|
||||
v-for="(file, index) in fileList"
|
||||
:key="file.uid || index"
|
||||
:class="['file-item', { active: currentFile && currentFile.uid === file.uid }]"
|
||||
@click="changePreviewFile(file)"
|
||||
>
|
||||
<div class="file-item-indicator"></div>
|
||||
<span class="file-item-text">{{ file.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧图片预览 -->
|
||||
<div class="file-preview-right" v-loading="loading">
|
||||
<div v-if="!currentFile" class="file-item-content">
|
||||
<el-empty description="请选择要预览的图片" />
|
||||
</div>
|
||||
<div v-else class="file-item-content">
|
||||
<img :src="currentFile.url" class="image-preview" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, watch } from 'vue';
|
||||
import { ElDialog, ElEmpty } from 'element-plus';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ImgsPreview',
|
||||
components: {
|
||||
ElDialog,
|
||||
ElEmpty,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
files: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'close'],
|
||||
setup(props, { emit }) {
|
||||
const dialogVisible = ref(false);
|
||||
const fileList = ref([]);
|
||||
const currentFile = ref(null);
|
||||
const loading = ref(false);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
dialogVisible.value = val;
|
||||
}
|
||||
);
|
||||
|
||||
watch(dialogVisible, (val) => {
|
||||
emit('update:modelValue', val);
|
||||
if (!val) {
|
||||
emit('close');
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.files,
|
||||
(val) => {
|
||||
fileList.value = val;
|
||||
if (val.length > 0 && !currentFile.value) {
|
||||
changePreviewFile(val[props.index || 0]);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const openDialog = (files, initialIndex = 0) => {
|
||||
if (files) {
|
||||
fileList.value = Array.isArray(files) ? files : [files];
|
||||
}
|
||||
dialogVisible.value = true;
|
||||
if (fileList.value.length > 0) {
|
||||
const index = Math.min(initialIndex, fileList.value.length - 1);
|
||||
changePreviewFile(fileList.value[index]);
|
||||
}
|
||||
};
|
||||
|
||||
const changePreviewFile = (file) => {
|
||||
if (!file) return;
|
||||
currentFile.value = file;
|
||||
};
|
||||
|
||||
return {
|
||||
dialogVisible,
|
||||
fileList,
|
||||
currentFile,
|
||||
loading,
|
||||
openDialog,
|
||||
changePreviewFile,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.file-preview-dialog {
|
||||
|
||||
.el-dialog__header {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
height: calc(100vh - 60px);
|
||||
}
|
||||
}
|
||||
|
||||
.file-preview-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
min-height: calc(80vh - 60px);
|
||||
}
|
||||
|
||||
.file-preview-left {
|
||||
width: 20%;
|
||||
padding: 20px;
|
||||
background: #ffffff;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-list-header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
position: relative;
|
||||
padding: 0.8rem 1rem;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
background: #f1f3f5;
|
||||
}
|
||||
|
||||
.file-item.active {
|
||||
background: #ecf5ff;
|
||||
}
|
||||
|
||||
.file-item-indicator {
|
||||
width: 2px;
|
||||
height: 16px;
|
||||
background: #c0c4cc;
|
||||
border-radius: 2px;
|
||||
margin-right: 12px;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.file-item.active .file-item-indicator {
|
||||
background: #409eff;
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.file-item-text {
|
||||
color: #606266;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.file-preview-right {
|
||||
flex: 1;
|
||||
background: #f5f7f9;
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.file-item-content {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.image-preview {
|
||||
max-width: 100%;
|
||||
max-height: 80vh;
|
||||
object-fit: contain;
|
||||
}
|
||||
</style>
|
@ -1,160 +1,151 @@
|
||||
<template>
|
||||
<el-upload
|
||||
v-model:file-list="dataFileList"
|
||||
class="upload-demo"
|
||||
:action="action"
|
||||
:multiple="multiple"
|
||||
:drag="drag"
|
||||
:on-remove="handleRemove"
|
||||
:before-remove="beforeRemove"
|
||||
:limit="limit"
|
||||
:on-exceed="handleExceed"
|
||||
:before-upload="beforeUpload"
|
||||
:on-change="handleChange"
|
||||
:on-success="handleSuccess"
|
||||
:data="dataParam"
|
||||
:on-preview="handlePreview"
|
||||
ref="upFileRef"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
拖拽文件至此 或<em>点击上传</em>
|
||||
</div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
请上传{{uploadSize}} M 以内
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<el-upload
|
||||
v-model:file-list="dataFileList"
|
||||
class="upload-demo"
|
||||
:action="action"
|
||||
:multiple="multiple"
|
||||
:drag="drag"
|
||||
:on-remove="handleRemove"
|
||||
:before-remove="beforeRemove"
|
||||
:limit="limit"
|
||||
:on-exceed="handleExceed"
|
||||
:before-upload="beforeUpload"
|
||||
:on-change="handleChange"
|
||||
:on-success="handleSuccess"
|
||||
:data="dataParam"
|
||||
:on-preview="handlePreview"
|
||||
ref="upFileRef"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
||||
<div class="el-upload__text">拖拽文件至此 或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">请上传{{ uploadSize }} M 以内</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {computed, defineComponent, getCurrentInstance, reactive, ref} from "vue";
|
||||
import type { UploadProps, UploadUserFile } from 'element-plus'
|
||||
import { ElMessage ,ElMessageBox} from 'element-plus'
|
||||
import {getToken} from "/@/utils/gfast";
|
||||
import _ from 'lodash'
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, getCurrentInstance, reactive, ref } from 'vue';
|
||||
import type { UploadProps, UploadUserFile } from 'element-plus';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { getToken } from '/@/utils/gfast';
|
||||
import _ from 'lodash';
|
||||
export default defineComponent({
|
||||
name: 'uploadFile',
|
||||
props: {
|
||||
action: { type : String, default : '' },//上传地址
|
||||
name: { type : String, default : 'file' },//上传文件类型
|
||||
method: { type : String, default : 'post' },//设置上传请求方法
|
||||
multiple: { type : Boolean, default : true },//是否支持多选文件
|
||||
showFileList: { type : Boolean, default : true },//是否显示已上传文件列表
|
||||
drag: { type : Boolean, default : true },//是否启用拖拽上传
|
||||
accept: { type : String, default : '.txt,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar' },//上传文件格式
|
||||
disabled: { type : Boolean, default : false },//是否禁止
|
||||
listType: { type : String, default : 'picture-card' },//
|
||||
uploadSize: { type : Number, default : 200 },//上传文件大小M
|
||||
limit: { type : Number, default : 5 },//上传最大数量
|
||||
modelValue:{
|
||||
type:Array,
|
||||
default:function(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
emits:['update:modelValue'],
|
||||
setup(props,{ emit }) {
|
||||
let uploadedFile:Array<any> = [] ;
|
||||
const {proxy} = <any>getCurrentInstance();
|
||||
const upFileRef = ref()
|
||||
const dataParam = reactive({
|
||||
token:getToken(),
|
||||
})
|
||||
const dataFileList = computed({
|
||||
get: () => {
|
||||
let value:Array<UploadUserFile> = props.modelValue as UploadUserFile[]|| [];
|
||||
value.map((item: UploadUserFile)=>{
|
||||
if(item.url){
|
||||
item.url = proxy.getUpFileUrl(item.url)
|
||||
}
|
||||
return item
|
||||
})
|
||||
uploadedFile = _.cloneDeep(value)
|
||||
return value
|
||||
},
|
||||
set: val => {
|
||||
emit('update:modelValue', val)
|
||||
}
|
||||
});
|
||||
const beforeUpload: UploadProps['beforeUpload'] = () => {
|
||||
return true
|
||||
};
|
||||
const handleChange: UploadProps['onChange'] = () => {
|
||||
|
||||
};
|
||||
const handleExceed = () => {
|
||||
ElMessage.error('最多可上传'+props.limit+'个文件,已超出最大限制数。');
|
||||
}
|
||||
const handleSuccess: UploadProps['onSuccess'] = (
|
||||
response,
|
||||
uploadFile
|
||||
) => {
|
||||
uploadedFile=uploadedFile.filter((item:UploadUserFile)=>{
|
||||
return item.raw?.uid != uploadFile.raw?.uid
|
||||
})
|
||||
if(response.code===0){
|
||||
uploadedFile.push({
|
||||
name:response.data.name,
|
||||
url:response.data.path,
|
||||
fullUrl:response.data.fullPath,
|
||||
fileType:response.data.type,
|
||||
size:response.data.size
|
||||
})
|
||||
}else{
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
setDataFileList();
|
||||
|
||||
};
|
||||
const beforeRemove: UploadProps['beforeRemove'] = (uploadFile) => {
|
||||
return ElMessageBox.confirm(
|
||||
`您确定要删除 ${uploadFile.name} ?`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
).then(
|
||||
() => true,
|
||||
() => false
|
||||
)
|
||||
};
|
||||
const handleRemove: UploadProps['onRemove'] = (file) => {//移除后
|
||||
uploadedFile.splice(uploadedFile.findIndex((item: any) => item.name === file.name),1)
|
||||
setDataFileList()
|
||||
};
|
||||
const setDataFileList = () => {
|
||||
dataFileList.value = uploadedFile
|
||||
};
|
||||
const handlePreview = (file:UploadUserFile)=>{
|
||||
window.open(file.url)
|
||||
}
|
||||
const stopUpFile = ()=>{
|
||||
upFileRef.value.abort()
|
||||
}
|
||||
return {
|
||||
dataFileList,
|
||||
handleSuccess,
|
||||
beforeRemove,
|
||||
handleRemove,
|
||||
beforeUpload,
|
||||
handleChange,
|
||||
handleExceed,
|
||||
handlePreview,
|
||||
upFileRef,
|
||||
stopUpFile,
|
||||
dataParam
|
||||
};
|
||||
},
|
||||
name: 'uploadFile',
|
||||
props: {
|
||||
action: { type: String, default: '' }, //上传地址
|
||||
name: { type: String, default: 'file' }, //上传文件类型
|
||||
method: { type: String, default: 'post' }, //设置上传请求方法
|
||||
multiple: { type: Boolean, default: true }, //是否支持多选文件
|
||||
showFileList: { type: Boolean, default: true }, //是否显示已上传文件列表
|
||||
drag: { type: Boolean, default: true }, //是否启用拖拽上传
|
||||
accept: { type: String, default: '.txt,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar' }, //上传文件格式
|
||||
disabled: { type: Boolean, default: false }, //是否禁止
|
||||
listType: { type: String, default: 'picture-card' }, //
|
||||
uploadSize: { type: Number, default: 200 }, //上传文件大小M
|
||||
limit: { type: Number, default: 5 }, //上传最大数量
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, { emit }) {
|
||||
let uploadedFile: Array<any> = [];
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const upFileRef = ref();
|
||||
const dataParam = reactive({
|
||||
token: getToken(),
|
||||
});
|
||||
const dataFileList = computed({
|
||||
get: () => {
|
||||
let value: Array<UploadUserFile> = (props.modelValue as UploadUserFile[]) || [];
|
||||
value.map((item: UploadUserFile) => {
|
||||
if (item.url) {
|
||||
item.url = proxy.getUpFileUrl(item.url);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
uploadedFile = _.cloneDeep(value);
|
||||
return value;
|
||||
},
|
||||
set: (val) => {
|
||||
emit('update:modelValue', val);
|
||||
},
|
||||
});
|
||||
const beforeUpload: UploadProps['beforeUpload'] = () => {
|
||||
return true;
|
||||
};
|
||||
const handleChange: UploadProps['onChange'] = () => {};
|
||||
const handleExceed = () => {
|
||||
ElMessage.error('最多可上传' + props.limit + '个文件,已超出最大限制数。');
|
||||
};
|
||||
const handleSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
|
||||
uploadedFile = uploadedFile.filter((item: UploadUserFile) => {
|
||||
return item.raw?.uid != uploadFile.raw?.uid;
|
||||
});
|
||||
if (response.code === 0) {
|
||||
uploadedFile.push({
|
||||
name: response.data.name,
|
||||
url: response.data.path,
|
||||
fullUrl: response.data.fullPath,
|
||||
fileType: response.data.type,
|
||||
size: response.data.size,
|
||||
});
|
||||
} else {
|
||||
ElMessage.error(response.message);
|
||||
}
|
||||
setDataFileList();
|
||||
};
|
||||
const beforeRemove: UploadProps['beforeRemove'] = (uploadFile) => {
|
||||
return ElMessageBox.confirm(`您确定要删除 ${uploadFile.name} ?`, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(
|
||||
() => true,
|
||||
() => false
|
||||
);
|
||||
};
|
||||
const handleRemove: UploadProps['onRemove'] = (file) => {
|
||||
//移除后
|
||||
uploadedFile.splice(
|
||||
uploadedFile.findIndex((item: any) => item.name === file.name),
|
||||
1
|
||||
);
|
||||
setDataFileList();
|
||||
};
|
||||
const setDataFileList = () => {
|
||||
dataFileList.value = uploadedFile;
|
||||
};
|
||||
const handlePreview = (file: UploadUserFile) => {
|
||||
window.open(file.url);
|
||||
};
|
||||
const stopUpFile = () => {
|
||||
upFileRef.value.abort();
|
||||
};
|
||||
return {
|
||||
dataFileList,
|
||||
handleSuccess,
|
||||
beforeRemove,
|
||||
handleRemove,
|
||||
beforeUpload,
|
||||
handleChange,
|
||||
handleExceed,
|
||||
handlePreview,
|
||||
upFileRef,
|
||||
stopUpFile,
|
||||
dataParam,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.el-upload.is-drag {
|
||||
display: block;
|
||||
width: 200px;height: 200px;
|
||||
display: block;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,199 +1,199 @@
|
||||
<template>
|
||||
<div class="up-img" v-if="limit > 1">
|
||||
<el-upload
|
||||
v-model:file-list="dataFileList"
|
||||
:limit="limit"
|
||||
:action="action"
|
||||
:multiple="multiple"
|
||||
:list-type="listType"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:on-exceed = "handleExceed"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:data="dataParam"
|
||||
ref="upImageRef"
|
||||
>
|
||||
<el-icon><ele-Plus /></el-icon>
|
||||
</el-upload>
|
||||
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<el-image :src="dialogImageUrl" fit="contain" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
<div class="up-img" v-else>
|
||||
<el-upload
|
||||
v-model:file-list="dataFileList"
|
||||
class="avatar-uploader"
|
||||
:action="action"
|
||||
:show-file-list="false"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:data="dataParam"
|
||||
>
|
||||
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
|
||||
<el-icon v-else class="avatar-uploader-icon"><ele-Plus /></el-icon>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="up-img" v-if="limit > 1">
|
||||
<el-upload
|
||||
v-model:file-list="dataFileList"
|
||||
:limit="limit"
|
||||
:action="action"
|
||||
:multiple="multiple"
|
||||
:list-type="listType"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:on-exceed="handleExceed"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:data="dataParam"
|
||||
:accept="accept"
|
||||
ref="upImageRef"
|
||||
>
|
||||
<el-icon><ele-Plus /></el-icon>
|
||||
</el-upload>
|
||||
|
||||
<el-dialog v-model="dialogVisible">
|
||||
<el-image :src="dialogImageUrl" fit="contain" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
<div class="up-img" v-else>
|
||||
<el-upload
|
||||
v-model:file-list="dataFileList"
|
||||
class="avatar-uploader"
|
||||
:action="action"
|
||||
:show-file-list="false"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:accept="accept"
|
||||
:data="dataParam"
|
||||
>
|
||||
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
|
||||
<el-icon v-else class="avatar-uploader-icon"><ele-Plus /></el-icon>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent, ref, computed, getCurrentInstance, reactive} from 'vue';
|
||||
import type {UploadProps,UploadUserFile} from 'element-plus'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {getToken} from "/@/utils/gfast";
|
||||
import _ from 'lodash'
|
||||
import { defineComponent, ref, computed, getCurrentInstance, reactive } from 'vue';
|
||||
import type { UploadProps, UploadUserFile } from 'element-plus';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { getToken } from '/@/utils/gfast';
|
||||
import _ from 'lodash';
|
||||
export default defineComponent({
|
||||
name: 'uploadImg',
|
||||
props: {
|
||||
action: { type : String, default : '' },//上传地址
|
||||
name: { type : String, default : 'file' },//上传文件类型
|
||||
limit: { type : Number, default : 1 },//上传最大数量
|
||||
method: { type : String, default : 'post' },//设置上传请求方法
|
||||
multiple: { type : Boolean, default : true },//是否支持多选文件
|
||||
showFileList: { type : Boolean, default : true },//是否显示已上传文件列表
|
||||
drag: { type : Boolean, default : false },//是否启用拖拽上传
|
||||
// accept: { type : String, default : '.jpg,.jpeg,.png,.gif' },//接受上传的文件类型格式
|
||||
disabled: { type : Boolean, default : false },//是否是否禁止上传
|
||||
listType: { type : String, default : 'picture-card' },//是否启用拖拽上传
|
||||
uploadSize: { type : Number, default : 10 },//上传文件大小
|
||||
modelValue:{
|
||||
type:Array,
|
||||
default:function(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
emits:['update:modelValue'],
|
||||
setup(props,{ emit }) {
|
||||
const upImageRef = ref()
|
||||
const baseURL:string|undefined|boolean = import.meta.env.VITE_API_URL
|
||||
const {proxy} = <any>getCurrentInstance();
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false)
|
||||
const imageUrl = ref('')
|
||||
const dataParam = reactive({
|
||||
token:getToken(),
|
||||
})
|
||||
let uploadedFile:Array<any>=[];
|
||||
const dataFileList = computed({
|
||||
get: () => {
|
||||
let value:Array<UploadUserFile> = props.modelValue as UploadUserFile[]|| [];
|
||||
value.map((item: UploadUserFile)=>{
|
||||
if(item.url){
|
||||
item.url = proxy.getUpFileUrl(item.url)
|
||||
}
|
||||
return item
|
||||
})
|
||||
uploadedFile = _.cloneDeep(value)
|
||||
if(props.limit == 1){
|
||||
uploadedFile = [];
|
||||
imageUrl.value = (value[0]?value[0].url:'') as string;
|
||||
}
|
||||
return value
|
||||
},
|
||||
set: val => {
|
||||
emit('update:modelValue', val)
|
||||
}
|
||||
});
|
||||
name: 'uploadImg',
|
||||
props: {
|
||||
action: { type: String, default: '' }, //上传地址
|
||||
name: { type: String, default: 'file' }, //上传文件类型
|
||||
limit: { type: Number, default: 1 }, //上传最大数量
|
||||
method: { type: String, default: 'post' }, //设置上传请求方法
|
||||
multiple: { type: Boolean, default: true }, //是否支持多选文件
|
||||
showFileList: { type: Boolean, default: true }, //是否显示已上传文件列表
|
||||
drag: { type: Boolean, default: false }, //是否启用拖拽上传
|
||||
accept: { type: String, default: '.jpg,.jpeg,.png,.gif' }, //接受上传的文件类型格式
|
||||
disabled: { type: Boolean, default: false }, //是否是否禁止上传
|
||||
listType: { type: String, default: 'picture-card' }, //是否启用拖拽上传
|
||||
uploadSize: { type: Number, default: 10 }, //上传文件大小
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, { emit }) {
|
||||
const upImageRef = ref();
|
||||
const baseURL: string | undefined | boolean = import.meta.env.VITE_API_URL;
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
const dialogImageUrl = ref('');
|
||||
const dialogVisible = ref(false);
|
||||
const imageUrl = ref('');
|
||||
const dataParam = reactive({
|
||||
token: getToken(),
|
||||
});
|
||||
let uploadedFile: Array<any> = [];
|
||||
const dataFileList = computed({
|
||||
get: () => {
|
||||
let value: Array<UploadUserFile> = (props.modelValue as UploadUserFile[]) || [];
|
||||
value.map((item: UploadUserFile) => {
|
||||
if (item.url) {
|
||||
item.url = proxy.getUpFileUrl(item.url);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
uploadedFile = _.cloneDeep(value);
|
||||
if (props.limit == 1) {
|
||||
uploadedFile = [];
|
||||
imageUrl.value = (value[0] ? value[0].url : '') as string;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
set: (val) => {
|
||||
emit('update:modelValue', val);
|
||||
},
|
||||
});
|
||||
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
if (rawFile.type.substring(0, 5) !== 'image') {
|
||||
ElMessage.error('请上传图片文件')
|
||||
return false
|
||||
} else if (rawFile.size / 1024 / 1024 > props.uploadSize) {
|
||||
ElMessage.error('上传文件超过'+props.uploadSize+'M');
|
||||
return false
|
||||
}
|
||||
return true
|
||||
};
|
||||
const handleRemove: UploadProps['onRemove'] = (file) => {
|
||||
uploadedFile.splice(uploadedFile.findIndex((item: any) => item.name === file.name),1)
|
||||
setDataFileList()
|
||||
};
|
||||
const handleExceed=() => {
|
||||
ElMessage.error('最多可上传'+props.limit+'个文件,已超出最大限制数。');
|
||||
};
|
||||
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
dialogImageUrl.value = uploadFile.url!
|
||||
dialogVisible.value = true
|
||||
};
|
||||
const handleAvatarSuccess: UploadProps['onSuccess'] = (
|
||||
response,
|
||||
uploadFile
|
||||
) => {
|
||||
if(props.limit == 1){
|
||||
uploadedFile = [];
|
||||
imageUrl.value = URL.createObjectURL(uploadFile.raw!)
|
||||
}
|
||||
uploadedFile=uploadedFile.filter((item:UploadUserFile)=>{
|
||||
return item.raw?.uid != uploadFile.raw?.uid
|
||||
})
|
||||
if(response.code===0){
|
||||
uploadedFile.push({
|
||||
name:response.data.name,
|
||||
url:response.data.path,
|
||||
fileType:response.data.type,
|
||||
size:response.data.size
|
||||
})
|
||||
}else{
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
setDataFileList();
|
||||
};
|
||||
const setDataFileList = () => {
|
||||
dataFileList.value = uploadedFile
|
||||
};
|
||||
const stopUpImage = ()=>{
|
||||
upImageRef.value.abort()
|
||||
}
|
||||
return {
|
||||
upImageRef,
|
||||
dataFileList,
|
||||
imageUrl,
|
||||
baseURL,
|
||||
dialogVisible,
|
||||
dialogImageUrl,
|
||||
handleExceed,
|
||||
beforeAvatarUpload,
|
||||
handleRemove,
|
||||
handlePictureCardPreview,
|
||||
handleAvatarSuccess,
|
||||
stopUpImage,
|
||||
dataParam
|
||||
};
|
||||
},
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
if (rawFile.type.substring(0, 5) !== 'image') {
|
||||
ElMessage.error('请上传图片文件');
|
||||
return false;
|
||||
} else if (rawFile.size / 1024 / 1024 > props.uploadSize) {
|
||||
ElMessage.error('上传文件超过' + props.uploadSize + 'M');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const handleRemove: UploadProps['onRemove'] = (file) => {
|
||||
uploadedFile.splice(
|
||||
uploadedFile.findIndex((item: any) => item.name === file.name),
|
||||
1
|
||||
);
|
||||
setDataFileList();
|
||||
};
|
||||
const handleExceed = () => {
|
||||
ElMessage.error('最多可上传' + props.limit + '个文件,已超出最大限制数。');
|
||||
};
|
||||
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
dialogImageUrl.value = uploadFile.url!;
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
|
||||
if (props.limit == 1) {
|
||||
uploadedFile = [];
|
||||
imageUrl.value = URL.createObjectURL(uploadFile.raw!);
|
||||
}
|
||||
uploadedFile = uploadedFile.filter((item: UploadUserFile) => {
|
||||
return item.raw?.uid != uploadFile.raw?.uid;
|
||||
});
|
||||
if (response.code === 0) {
|
||||
uploadedFile.push({
|
||||
name: response.data.name,
|
||||
url: response.data.path,
|
||||
fileType: response.data.type,
|
||||
size: response.data.size,
|
||||
});
|
||||
} else {
|
||||
ElMessage.error(response.message);
|
||||
}
|
||||
setDataFileList();
|
||||
};
|
||||
const setDataFileList = () => {
|
||||
dataFileList.value = uploadedFile;
|
||||
};
|
||||
const stopUpImage = () => {
|
||||
upImageRef.value.abort();
|
||||
};
|
||||
return {
|
||||
upImageRef,
|
||||
dataFileList,
|
||||
imageUrl,
|
||||
baseURL,
|
||||
dialogVisible,
|
||||
dialogImageUrl,
|
||||
handleExceed,
|
||||
beforeAvatarUpload,
|
||||
handleRemove,
|
||||
handlePictureCardPreview,
|
||||
handleAvatarSuccess,
|
||||
stopUpImage,
|
||||
dataParam,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.up-img :deep(.avatar-uploader .avatar) {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
.up-img :deep(.avatar-uploader .el-upload) {
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
border: 1px dashed var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
|
||||
.up-img :deep(.avatar-uploader .el-upload:hover) {
|
||||
border-color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.up-img :deep(.el-icon.avatar-uploader-icon) {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
text-align: center;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
@ -38,11 +38,11 @@ const onThemeConfigChange = () => {
|
||||
justify-content: center;
|
||||
box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
|
||||
color: var(--el-color-primary);
|
||||
font-size: 16px;
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
animation: logoAnimation 0.3s ease-in-out;
|
||||
span {
|
||||
white-space: nowrap;
|
||||
// white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
&:hover {
|
||||
|
@ -12,7 +12,7 @@ import 'element-plus/dist/index.css';
|
||||
import '/@/theme/index.scss';
|
||||
import mitt from 'mitt';
|
||||
import {findChildrenByPid, flattenTree, getUpFileUrl, handleTree, parseTime, selectDictLabel} from '/@/utils/gfast';
|
||||
import {useDict} from '/@/api/system/dict/data';
|
||||
import {useDict,getDicts,formatGetDicts} from '/@/api/system/dict/data';
|
||||
import {getItems, setItems, getOptionValue, isEmpty} from '/@/api/items'
|
||||
// 分页组件
|
||||
import pagination from '/@/components/pagination/index.vue'
|
||||
@ -42,6 +42,9 @@ app.config.globalProperties.handleTree=handleTree
|
||||
app.config.globalProperties.flattenTree=flattenTree
|
||||
app.config.globalProperties.findChildrenByPid=findChildrenByPid
|
||||
app.config.globalProperties.useDict=useDict
|
||||
app.config.globalProperties.getDicts=getDicts
|
||||
app.config.globalProperties.formatGetDicts=formatGetDicts
|
||||
|
||||
app.config.globalProperties.selectDictLabel=selectDictLabel
|
||||
|
||||
app.config.globalProperties.getItems=getItems
|
||||
|
@ -96,7 +96,7 @@ export const useThemeConfig = defineStore('themeConfig', {
|
||||
// 是否开启水印
|
||||
isWartermark: false,
|
||||
// 水印文案
|
||||
wartermarkText: 'GFastV3',
|
||||
wartermarkText: '外来入侵物种智能决策可视化模拟后台管理系统',
|
||||
|
||||
/**
|
||||
* 其它设置
|
||||
@ -129,9 +129,9 @@ export const useThemeConfig = defineStore('themeConfig', {
|
||||
* 全局网站标题 / 副标题
|
||||
*/
|
||||
// 网站主标题(菜单导航、浏览器当前网页标题)
|
||||
globalTitle: 'gfast3.2后台管理系统',
|
||||
globalTitle: '外来入侵物种智能决策可视化模拟后台管理系统',
|
||||
// 网站副标题(登录页顶部文字)
|
||||
globalViceTitle: 'gfast3.2后台管理系统',
|
||||
globalViceTitle: '外来入侵物种智能决策可视化模拟后台管理系统',
|
||||
// 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn
|
||||
globalI18n: 'zh-cn',
|
||||
// 默认全局组件大小,可选值"<large|'default'|small>",默认 'large'
|
||||
|
@ -45,4 +45,8 @@ export interface UserItem {
|
||||
|
||||
export interface VersionMap{
|
||||
[key: string]: number
|
||||
}
|
||||
export interface AuditStatusOptions {
|
||||
value: string;
|
||||
key: string;
|
||||
}
|
54
src/views/businesses/biocontrolResource/api.ts
Normal file
54
src/views/businesses/biocontrolResource/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询天敌昆虫列表
|
||||
export function reqList(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biocontrolResource/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询天敌昆虫详细
|
||||
export function reqGet(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biocontrolResource/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增天敌昆虫
|
||||
export function reqAdd(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biocontrolResource/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改天敌昆虫
|
||||
export function reqEdit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biocontrolResource/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除天敌昆虫
|
||||
export function reqDel(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biocontrolResource/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reqAudit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biocontrolResource/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
616
src/views/businesses/biocontrolResource/index.vue
Normal file
616
src/views/businesses/biocontrolResource/index.vue
Normal file
@ -0,0 +1,616 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
:label-width="'130px'"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
v-auth="'api/v1/businesses/biocontrolResource/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/biocontrolResource/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/biocontrolResource/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/biocontrolResource/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/biocontrolResource/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'140px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed, getCurrentInstance } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { reqAdd, reqAudit, reqDel, reqEdit, reqList } from './api';
|
||||
import { Columns, InfoData, State } from './type';
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesDefinitenessList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
const { proxy } = <any>getCurrentInstance();
|
||||
|
||||
const state = reactive<State>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
|
||||
interface BiocontrolOptions {
|
||||
value: string;
|
||||
key: string;
|
||||
}
|
||||
const biocontrolOptions = ref<BiocontrolOptions[]>([]);
|
||||
const reqGetbiocontrolType = async () => {
|
||||
biocontrolOptions.value = proxy.formatGetDicts(await proxy.getDicts('biocontrol_type'));
|
||||
};
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode', minWidth: 140 },
|
||||
{ label: '中文学名', prop: 'zhName', minWidth: 140 },
|
||||
{ label: '中文异名', prop: 'zhSynonym', minWidth: 140 },
|
||||
{ label: '英文学名', prop: 'enName', minWidth: 100 },
|
||||
{ label: '拉丁学名', prop: 'latinName', minWidth: 100 },
|
||||
{ label: '拉丁异名', prop: 'latinSynonym', minWidth: 100 },
|
||||
{
|
||||
label: '生防物类型',
|
||||
prop: 'biocontrolType',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const data = biocontrolOptions.value.find((i) => i.key == cellValue);
|
||||
return data ? data.value : '';
|
||||
},
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<InfoData>>({
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
zhSynonym: undefined,
|
||||
enName: undefined,
|
||||
latinName: undefined,
|
||||
latinSynonym: undefined,
|
||||
biocontrolType: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入物种编码',
|
||||
},
|
||||
{
|
||||
label: '中文学名',
|
||||
prop: 'zhName',
|
||||
type: 'input',
|
||||
placeholder: '请输入中文学名',
|
||||
},
|
||||
{
|
||||
label: '中文异名',
|
||||
prop: 'zhSynonym',
|
||||
type: 'input',
|
||||
placeholder: '请输入中文异名',
|
||||
},
|
||||
{ label: '英文学名', prop: 'enName', type: 'input', placeholder: '请输入英文学名' },
|
||||
{ label: '拉丁学名', prop: 'latinName', type: 'input', placeholder: '请输入拉丁学名' },
|
||||
{ label: '拉丁异名', prop: 'latinSynonym', type: 'input', placeholder: '请输入拉丁异名' },
|
||||
{
|
||||
label: '生防物类型',
|
||||
prop: 'biocontrolType',
|
||||
type: 'select',
|
||||
placeholder: '请输入生防物类型',
|
||||
options: biocontrolOptions.value.map((i) => {
|
||||
return {
|
||||
value: i.key,
|
||||
label: i.value,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
reqGetbiocontrolType();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await reqList(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<InfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'select',
|
||||
options: specieslist.value.map((i) => {
|
||||
return {
|
||||
value: i.speciesCode,
|
||||
label: i.speciesCode,
|
||||
};
|
||||
}),
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入物种编码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择物种编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '中文学名',
|
||||
prop: 'zhName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入中文学名', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入中文学名',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '中文异名',
|
||||
prop: 'zhSynonym',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入中文异名', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入中文异名',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '英文学名',
|
||||
prop: 'enName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入英文学名', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入英文学名',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '拉丁学名',
|
||||
prop: 'latinName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入拉丁学名', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入拉丁学名',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '拉丁异名',
|
||||
prop: 'latinSynonym',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入拉丁异名', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入拉丁异名',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '生防物类型',
|
||||
prop: 'biocontrolType',
|
||||
type: 'select',
|
||||
options: biocontrolOptions.value.map((i) => {
|
||||
return {
|
||||
value: i.key,
|
||||
label: i.value,
|
||||
};
|
||||
}),
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入生防物类型', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入生防物类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
style: 'width: 100%',
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const resetForm = <T,>(old: T) => {
|
||||
for (const v in old) {
|
||||
old[v] = undefined as T[Extract<keyof T, string>];
|
||||
}
|
||||
};
|
||||
const formData = ref<InfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
zhSynonym: undefined,
|
||||
enName: undefined,
|
||||
latinName: undefined,
|
||||
latinSynonym: undefined,
|
||||
biocontrolType: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: InfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
reqAdd(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
reqEdit(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
zhSynonym: undefined,
|
||||
enName: undefined,
|
||||
latinName: undefined,
|
||||
latinSynonym: undefined,
|
||||
biocontrolType: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增生防资源';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: InfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑生防资源';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
const handleDelete = (row: Columns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
reqDel(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: Columns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: Columns) => {
|
||||
reqAudit(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
59
src/views/businesses/biocontrolResource/type.ts
Normal file
59
src/views/businesses/biocontrolResource/type.ts
Normal file
@ -0,0 +1,59 @@
|
||||
export interface Columns {
|
||||
id:number; //
|
||||
speciesCode:string; // 物种编码
|
||||
zhName:string; // 中文学名
|
||||
zhSynonym:string; // 中文异名
|
||||
enName:string; // 英文学名
|
||||
latinName:string; // 拉丁学名
|
||||
latinSynonym:string; // 拉丁异名
|
||||
biocontrolType:number; // 生防物类型
|
||||
sourcesData:string; // 数据来源
|
||||
createUser:number; // 数据采集人
|
||||
createDate:string; // 数据采集日期
|
||||
auditUser:string; // 数据核查人
|
||||
auditDate:string; // 数据核查日期
|
||||
auditStatus:number; // 核查
|
||||
auditView:string; // 核查意见
|
||||
remark:string; // 备注
|
||||
version:number; // 版本
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
id:number|undefined; //
|
||||
speciesCode:string|undefined; // 物种编码
|
||||
zhName:string|undefined; // 中文学名
|
||||
zhSynonym:string|undefined; // 中文异名
|
||||
enName:string|undefined; // 英文学名
|
||||
latinName:string|undefined; // 拉丁学名
|
||||
latinSynonym:string|undefined; // 拉丁异名
|
||||
biocontrolType:number|undefined; // 生防物类型
|
||||
sourcesData:string|undefined; // 数据来源
|
||||
createUser:number|undefined; // 数据采集人
|
||||
createDate:string|undefined; // 数据采集日期
|
||||
auditUser:string|undefined; // 数据核查人
|
||||
auditDate:string|undefined; // 数据核查日期
|
||||
auditStatus:number|undefined; // 核查
|
||||
auditView:string|undefined; // 核查意见
|
||||
remark:string|undefined; // 备注
|
||||
version:number|undefined; // 版本
|
||||
}
|
||||
|
||||
export interface State {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<Columns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: InfoData;
|
||||
rules: object;
|
||||
}
|
54
src/views/businesses/biologyEcology/api.ts
Normal file
54
src/views/businesses/biologyEcology/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询天敌昆虫列表
|
||||
export function reqList(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biologyEcology/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询天敌昆虫详细
|
||||
export function reqGet(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biologyEcology/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增天敌昆虫
|
||||
export function reqAdd(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biologyEcology/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改天敌昆虫
|
||||
export function reqEdit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biologyEcology/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除天敌昆虫
|
||||
export function reqDel(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biologyEcology/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reqAudit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/biologyEcology/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
661
src/views/businesses/biologyEcology/index.vue
Normal file
661
src/views/businesses/biologyEcology/index.vue
Normal file
@ -0,0 +1,661 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
:label-width="'200px'"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
v-auth="'api/v1/businesses/biologyEcology/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/biologyEcology/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/biologyEcology/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/biologyEcology/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/biologyEcology/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'140px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { reqAdd, reqAudit, reqDel, reqEdit, reqList } from './api';
|
||||
import { Columns, InfoData, State } from '/@/views/businesses/biologyEcology/type';
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesDefinitenessList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<State>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
label: '生活史/侵染循环',
|
||||
prop: 'lifeHistory',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
label: '发生与危害特性',
|
||||
prop: 'character',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
label: '生境类型',
|
||||
prop: 'habitatType',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
label: '生态、经济和社会影响描述',
|
||||
prop: 'zoologyDescribe',
|
||||
minWidth: 200,
|
||||
},
|
||||
{
|
||||
label: '模式标本采集地',
|
||||
prop: 'specimenGather',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
label: '模式标本保存地',
|
||||
prop: 'specimenSave',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
label: '首次发现或引入的地点及时间',
|
||||
prop: 'introduceDesc',
|
||||
minWidth: 220,
|
||||
},
|
||||
{
|
||||
label: '传播与扩散途径',
|
||||
prop: 'diffuse',
|
||||
minWidth: 140,
|
||||
},
|
||||
{
|
||||
label: '风险评估结果',
|
||||
prop: 'riskAssessment',
|
||||
minWidth: 140,
|
||||
},
|
||||
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<InfoData>>({
|
||||
lifeHistory: undefined,
|
||||
habitatType: undefined,
|
||||
specimenGather: undefined,
|
||||
specimenSave: undefined,
|
||||
introduceDesc: undefined,
|
||||
diffuse: undefined,
|
||||
riskAssessment: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{
|
||||
label: '生活史/侵染循环',
|
||||
prop: 'lifeHistory',
|
||||
type: 'input',
|
||||
placeholder: '请输入生活史/侵染循环',
|
||||
},
|
||||
{
|
||||
label: '生境类型',
|
||||
prop: 'habitatType',
|
||||
type: 'input',
|
||||
placeholder: '请输入生境类型',
|
||||
},
|
||||
{
|
||||
label: '模式标本采集地',
|
||||
prop: 'specimenGather',
|
||||
type: 'input',
|
||||
placeholder: '请输入模式标本采集地',
|
||||
},
|
||||
{
|
||||
label: '模式标本保存地',
|
||||
prop: 'specimenSave',
|
||||
type: 'input',
|
||||
placeholder: '请输入模式标本保存地',
|
||||
},
|
||||
{
|
||||
label: '首次发现或引入的地点及时间',
|
||||
prop: 'introduceDesc',
|
||||
type: 'input',
|
||||
placeholder: '请输入首次发现或引入的地点及时间',
|
||||
},
|
||||
{
|
||||
label: '传播与扩散途径',
|
||||
prop: 'diffuse',
|
||||
type: 'input',
|
||||
placeholder: '请输入传播与扩散途径',
|
||||
},
|
||||
|
||||
{
|
||||
label: '风险评估结果',
|
||||
prop: 'riskAssessment',
|
||||
type: 'input',
|
||||
placeholder: '请输入风险评估结果',
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await reqList(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<InfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '生活史/侵染循环',
|
||||
prop: 'lifeHistory',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入生活史/侵染循环', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入生活史/侵染循环',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '发生与危害特性',
|
||||
prop: 'character',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入发生与危害特性', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
type: 'textarea',
|
||||
placeholder: '请输入发生与危害特性',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '生态、经济和社会影响描述',
|
||||
prop: 'zoologyDescribe',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入生态、经济和社会影响描述', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入生态、经济和社会影响描述',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '模式标本采集地',
|
||||
prop: 'specimenGather',
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入模式标本采集地', trigger: 'blur' }],
|
||||
span: 24,
|
||||
componentProps: {
|
||||
placeholder: '请输入模式标本采集地',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '模式标本保存地',
|
||||
prop: 'specimenSave',
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入模式标本保存地', trigger: 'blur' }],
|
||||
span: 24,
|
||||
componentProps: {
|
||||
placeholder: '请输入模式标本保存地',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '首次发现或引入的地点及时间',
|
||||
prop: 'introduceDesc',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入首次发现或引入的地点及时间', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入首次发现或引入的地点及时间',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '传播与扩散途径',
|
||||
prop: 'diffuse',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入传播与扩散途径', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入传播与扩散途径',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '风险评估结果',
|
||||
prop: 'riskAssessment',
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入风险评估结果', trigger: 'blur' }],
|
||||
span: 24,
|
||||
componentProps: {
|
||||
placeholder: '请输入风险评估结果',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '生境类型',
|
||||
prop: 'habitatType',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入生境类型', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入生境类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
style: 'width: 100%',
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const resetForm = <T,>(old: T) => {
|
||||
for (const v in old) {
|
||||
old[v] = undefined as T[Extract<keyof T, string>];
|
||||
}
|
||||
};
|
||||
const formData = ref<InfoData>({
|
||||
id: undefined,
|
||||
lifeHistory: undefined,
|
||||
character: undefined,
|
||||
habitatType: undefined,
|
||||
zoologyDescribe: undefined,
|
||||
specimenGather: undefined,
|
||||
specimenSave: undefined,
|
||||
introduceDesc: undefined,
|
||||
diffuse: undefined,
|
||||
riskAssessment: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
remark: undefined,
|
||||
speciesCode: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditStatus: undefined,
|
||||
auditView: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: InfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
reqAdd(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
reqEdit(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
lifeHistory: undefined,
|
||||
character: undefined,
|
||||
habitatType: undefined,
|
||||
zoologyDescribe: undefined,
|
||||
specimenGather: undefined,
|
||||
specimenSave: undefined,
|
||||
introduceDesc: undefined,
|
||||
diffuse: undefined,
|
||||
riskAssessment: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
remark: undefined,
|
||||
speciesCode: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditStatus: undefined,
|
||||
auditView: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增基本生物学与生态学';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: InfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑基本生物学与生态学';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
const handleDelete = (row: Columns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
reqDel(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: Columns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: Columns) => {
|
||||
reqAudit(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
65
src/views/businesses/biologyEcology/type.ts
Normal file
65
src/views/businesses/biologyEcology/type.ts
Normal file
@ -0,0 +1,65 @@
|
||||
export interface Columns {
|
||||
id:number; //
|
||||
speciesCode:string; // 编码
|
||||
lifeHistory:string; // 生活史/侵染循环
|
||||
character:string; // 发生与危害特性
|
||||
habitatType:string; // 生境类型
|
||||
zoologyDescribe:string; // 生态、经济和社会影响描述
|
||||
specimenGather:string; // 模式标本采集地
|
||||
specimenSave:string; // 模式标本保存地
|
||||
introduceDesc:string; // 首次发现或引入的地点及时间
|
||||
diffuse:string; // 传播与扩散途径
|
||||
riskAssessment:string; // 风险评估结果
|
||||
sourcesData:string; // 数据来源
|
||||
createUser:number; // 数据采集人
|
||||
createDate:string; // 数据采集日期
|
||||
auditUser:string; // 数据核查人
|
||||
auditDate:string; // 数据核查日期
|
||||
auditStatus:number; // 核查
|
||||
auditView:string; // 核查意见
|
||||
remark:string; // 备注
|
||||
version:number; // 版本
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
id:number|undefined; //
|
||||
speciesCode:string|undefined; // 编码
|
||||
lifeHistory:string|undefined; // 生活史/侵染循环
|
||||
character:string|undefined; // 发生与危害特性
|
||||
habitatType:string|undefined; // 生境类型
|
||||
zoologyDescribe:string|undefined; // 生态、经济和社会影响描述
|
||||
specimenGather:string|undefined; // 模式标本采集地
|
||||
specimenSave:string|undefined; // 模式标本保存地
|
||||
introduceDesc:string|undefined; // 首次发现或引入的地点及时间
|
||||
diffuse:string|undefined; // 传播与扩散途径
|
||||
riskAssessment:string|undefined; // 风险评估结果
|
||||
sourcesData:string|undefined; // 数据来源
|
||||
createUser:number|undefined; // 数据采集人
|
||||
createDate:string|undefined; // 数据采集日期
|
||||
auditUser:string|undefined; // 数据核查人
|
||||
auditDate:string|undefined; // 数据核查日期
|
||||
auditStatus:number|undefined; // 核查
|
||||
auditView:string|undefined; // 核查意见
|
||||
remark:string|undefined; // 备注
|
||||
version:number|undefined; // 版本
|
||||
}
|
||||
|
||||
export interface State {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<Columns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: InfoData;
|
||||
rules: object;
|
||||
}
|
@ -447,12 +447,12 @@ const handleCancel = () => {
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增分类地位';
|
||||
formTitle.value = '新增识别特征';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: CharacteristicInfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑分类地位';
|
||||
formTitle.value = '编辑识别特征';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
@ -489,7 +489,9 @@ const handleDelete = (row: CharacteristicTableColumns | null) => {
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: CharacteristicTableColumns) => {
|
||||
auditFormRef.value.open(cloneDeep(row), userOptions.value);
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: CharacteristicTableColumns) => {
|
||||
auditCharacteristic(val).then(() => {
|
||||
|
@ -6,7 +6,7 @@ export interface CharacteristicTableColumns {
|
||||
sourcesData:string; // 数据来源
|
||||
createUser:number; // 数据采集人
|
||||
createDate:string; // 数据采集日期
|
||||
auditUser:number; // 数据核查人
|
||||
auditUser:string; // 数据核查人
|
||||
auditDate:string; // 数据核查日期
|
||||
auditStatus:number; //
|
||||
auditView:string; //
|
||||
@ -23,7 +23,7 @@ export interface CharacteristicInfoData {
|
||||
sourcesData:string|undefined; // 数据来源
|
||||
createUser:number|undefined; // 数据采集人
|
||||
createDate:string|undefined; // 数据采集日期
|
||||
auditUser:number|undefined; // 数据核查人
|
||||
auditUser:string|undefined; // 数据核查人
|
||||
auditDate:string|undefined; // 数据核查日期
|
||||
auditStatus:number|undefined; //
|
||||
auditView:string|undefined; //
|
||||
|
@ -659,7 +659,9 @@ const handleDelete = (row: ClassifyStatuseTableColumns | null) => {
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: ClassifyStatuseTableColumns) => {
|
||||
auditFormRef.value.open(cloneDeep(row), userOptions.value);
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: ClassifyStatuseTableColumns) => {
|
||||
auditSpeciesName(val).then(() => {
|
||||
|
@ -19,7 +19,7 @@ export interface ClassifyStatuseTableColumns {
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: number; // 数据核查人
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; // 核查
|
||||
auditView: string; // 核查意见
|
||||
@ -49,7 +49,7 @@ export interface ClassifyStatuseInfoData {
|
||||
sourcesData: string | undefined; // 数据来源
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集日期
|
||||
auditUser: number | undefined; // 数据核查人
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
auditStatus: number | undefined; // 核查
|
||||
auditView: string | undefined; // 核查意见
|
||||
|
54
src/views/businesses/definiteness/api.ts
Normal file
54
src/views/businesses/definiteness/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询天敌昆虫列表
|
||||
export function reqList(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/definiteness/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询天敌昆虫详细
|
||||
export function reqGet(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/definiteness/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增天敌昆虫
|
||||
export function reqAdd(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/definiteness/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改天敌昆虫
|
||||
export function reqEdit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/definiteness/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除天敌昆虫
|
||||
export function reqDel(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/definiteness/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reqAudit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/definiteness/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
533
src/views/businesses/definiteness/index.vue
Normal file
533
src/views/businesses/definiteness/index.vue
Normal file
@ -0,0 +1,533 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
:label-width="'130px'"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" @click="handleAdd" v-auth="'api/v1/businesses/definiteness/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/definiteness/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/definiteness/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/definiteness/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/definiteness/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'140px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { reqAdd, reqAudit, reqDel, reqEdit, reqList } from './api';
|
||||
import { Columns, InfoData, State } from './type';
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesDefinitenessList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<State>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode', minWidth: 140 },
|
||||
{ label: '国家名称', prop: 'countryName', minWidth: 140 },
|
||||
{ label: '限定性情况', prop: 'definiteness', minWidth: 140 },
|
||||
{ label: '制定年份', prop: 'year', minWidth: 100 },
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<InfoData>>({
|
||||
speciesCode: undefined,
|
||||
countryName: undefined,
|
||||
definiteness: undefined,
|
||||
year: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入物种编码',
|
||||
},
|
||||
{
|
||||
label: '国家名称',
|
||||
prop: 'countryName',
|
||||
type: 'input',
|
||||
placeholder: '请输入国家名称',
|
||||
},
|
||||
{
|
||||
label: '限定性情况',
|
||||
prop: 'definiteness',
|
||||
type: 'input',
|
||||
placeholder: '请输入限定性情况',
|
||||
},
|
||||
{ label: '制定年份', prop: 'year', type: 'input', placeholder: '请输入制定年份' },
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
{ label: '数据核查日期', prop: 'auditDate', type: 'daterange', valueFormat: 'YYYY-MM-DD' },
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await reqList(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<InfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'select',
|
||||
options: specieslist.value.map((i) => {
|
||||
return {
|
||||
value: i.speciesCode,
|
||||
label: i.speciesCode,
|
||||
};
|
||||
}),
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入物种编码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择物种编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label:"国家名称",
|
||||
prop:"countryName",
|
||||
type:"input",
|
||||
span:24,
|
||||
rules:[{required:true,message:"请输入国家名称",trigger:"blur"}],
|
||||
componentProps:{
|
||||
placeholder:"请输入国家名称",
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
label: '限定性情况',
|
||||
prop: 'definiteness',
|
||||
type: 'input',
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入限定性情况', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入限定性情况',
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '制定年份',
|
||||
prop: 'year',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入制定年份', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入制定年份',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
style: 'width: 100%',
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const resetForm = <T,>(old: T) => {
|
||||
for (const v in old) {
|
||||
old[v] = undefined as T[Extract<keyof T, string>];
|
||||
}
|
||||
};
|
||||
const formData = ref<InfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
countryName: undefined,
|
||||
definiteness: undefined,
|
||||
year: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: InfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
reqAdd(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
reqEdit(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
countryName: undefined,
|
||||
definiteness: undefined,
|
||||
year: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增限定性情况';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: InfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑限定性情况';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
const handleDelete = (row: Columns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
reqDel(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: Columns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: Columns) => {
|
||||
reqAudit(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
54
src/views/businesses/definiteness/type.ts
Normal file
54
src/views/businesses/definiteness/type.ts
Normal file
@ -0,0 +1,54 @@
|
||||
export interface Columns {
|
||||
id:number; //
|
||||
speciesCode:string; // 物种编码
|
||||
countryName:string; // 国家名称
|
||||
definiteness:string; // 限定性情况
|
||||
year:string; // 制定年份
|
||||
sourcesData:string; // 数据来源
|
||||
createUser:number; // 数据采集人
|
||||
createDate:string; // 数据采集日期
|
||||
auditUser:string; // 数据核查人
|
||||
auditDate:string; // 数据核查日期
|
||||
auditStatus:number; // 核查
|
||||
auditView:string; // 核查意见
|
||||
remark:string; // 备注
|
||||
version:number; // 版本
|
||||
createdAt:string; //
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
id:number|undefined; //
|
||||
speciesCode:string|undefined; // 物种编码
|
||||
countryName:string|undefined; // 国家名称
|
||||
definiteness:string|undefined; // 限定性情况
|
||||
year:string|undefined; // 制定年份
|
||||
sourcesData:string|undefined; // 数据来源
|
||||
createUser:number|undefined; // 数据采集人
|
||||
createDate:string|undefined; // 数据采集日期
|
||||
auditUser:string|undefined; // 数据核查人
|
||||
auditDate:string|undefined; // 数据核查日期
|
||||
auditStatus:number|undefined; // 核查
|
||||
auditView:string|undefined; // 核查意见
|
||||
remark:string|undefined; // 备注
|
||||
version:number|undefined; // 版本
|
||||
}
|
||||
|
||||
export interface State {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<Columns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: InfoData;
|
||||
rules: object;
|
||||
}
|
@ -454,12 +454,12 @@ const handleCancel = () => {
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增分类地位';
|
||||
formTitle.value = '新增国内分布';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: DomestiDistribuionInfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑分类地位';
|
||||
formTitle.value = '编辑国内分布';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
@ -496,7 +496,9 @@ const handleDelete = (row: DomestiDistribuionTableColumns | null) => {
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: DomestiDistribuionTableColumns) => {
|
||||
auditFormRef.value.open(cloneDeep(row), userOptions.value);
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: DomestiDistribuionTableColumns) => {
|
||||
auditDomestiDistribuion(val).then(() => {
|
||||
|
@ -8,7 +8,7 @@ export interface DomestiDistribuionTableColumns {
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: number; // 数据核查人
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; //
|
||||
auditView: string; //
|
||||
|
@ -455,12 +455,12 @@ const handleCancel = () => {
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增分类地位';
|
||||
formTitle.value = '新增国外分布';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: ForeignDistributionInfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑分类地位';
|
||||
formTitle.value = '编辑国外分布';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
@ -497,7 +497,9 @@ const handleDelete = (row: ForeignDistributionTableColumns | null) => {
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: ForeignDistributionTableColumns) => {
|
||||
auditFormRef.value.open(cloneDeep(row), userOptions.value);
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: ForeignDistributionTableColumns) => {
|
||||
auditForeignDistribution(val).then(() => {
|
||||
|
@ -8,7 +8,7 @@ export interface ForeignDistributionTableColumns {
|
||||
references: string; // 参考文献
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: number; // 数据核查人
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; //
|
||||
auditView: string; //
|
||||
@ -26,7 +26,7 @@ export interface ForeignDistributionInfoData {
|
||||
references: string | undefined; // 参考文献
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集日期
|
||||
auditUser: number | undefined; // 数据核查人
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
auditStatus: number | undefined; //
|
||||
auditView: string | undefined; //
|
||||
|
@ -24,7 +24,7 @@
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
@ -447,12 +447,12 @@ const handleCancel = () => {
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增分类地位';
|
||||
formTitle.value = '新增地理分布';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: GeographyInfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑分类地位';
|
||||
formTitle.value = '编辑地理分布';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
@ -489,7 +489,9 @@ const handleDelete = (row: GeographyTableColumns | null) => {
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: GeographyTableColumns) => {
|
||||
auditFormRef.value.open(cloneDeep(row), userOptions.value);
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: GeographyTableColumns) => {
|
||||
auditGeography(val).then(() => {
|
||||
|
@ -7,7 +7,7 @@ export interface GeographyTableColumns {
|
||||
domesticInfo: string; // 国内分布描述
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: number; // 数据核查人
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; // 核查状态
|
||||
auditView: string; // 核查意见
|
||||
@ -25,7 +25,7 @@ export interface GeographyInfoData {
|
||||
domesticInfo: string | undefined; // 国内分布描述
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集日期
|
||||
auditUser: number | undefined; // 数据核查人
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
auditStatus: number | undefined; // 核查状态
|
||||
auditView: string | undefined; // 核查意见
|
||||
|
54
src/views/businesses/hostBotany/api.ts
Normal file
54
src/views/businesses/hostBotany/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询寄主生物列表
|
||||
export function listHostBotany(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/hostBotany/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询寄主生物详细
|
||||
export function getHostBotany(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/hostBotany/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
// 新增寄主生物
|
||||
export function addHostBotany(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/hostBotany/add',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
// 修改寄主生物
|
||||
export function updateHostBotany(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/hostBotany/edit',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
// 删除寄主生物
|
||||
export function delHostBotany(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/hostBotany/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function auditHostBotany(data:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/hostBotany/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
678
src/views/businesses/hostBotany/index.vue
Normal file
678
src/views/businesses/hostBotany/index.vue
Normal file
@ -0,0 +1,678 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" @click="handleAdd" v-auth="'api/v1/businesses/hostBotany/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/hostBotany/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/hostBotany/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/hostBotany/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/hostBotany/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'120px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import {
|
||||
listHostBotany,
|
||||
delHostBotany,
|
||||
addHostBotany,
|
||||
updateHostBotany,
|
||||
auditHostBotany,
|
||||
} from './api';
|
||||
import { HostBotanyTableColumns, HostBotanyInfoData, HostBotanyTableDataState } from './type';
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesHostBotanyList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<HostBotanyTableDataState>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode', minWidth: 100 },
|
||||
{ label: '中文学名', prop: 'zhName', minWidth: 100 },
|
||||
{ label: '中文异名', prop: 'zhSynonym', minWidth: 100 },
|
||||
{ label: '英文学名', prop: 'enName', minWidth: 100 },
|
||||
{ label: '拉丁学名', prop: 'latinName', minWidth: 100 },
|
||||
{ label: '拉丁异名', prop: 'latinSynonym', minWidth: 100 },
|
||||
{ label: '目', prop: 'mu', minWidth: 100 },
|
||||
{ label: 'Order', prop: 'orderTitle', minWidth: 100 },
|
||||
{ label: '科', prop: 'ke', minWidth: 100 },
|
||||
{ label: 'Family', prop: 'family', minWidth: 100 },
|
||||
{ label: '属', prop: 'shu', minWidth: 100 },
|
||||
{ label: 'Genus', prop: 'genus', minWidth: 100 },
|
||||
{ label: '种', prop: 'zhong', minWidth: 100 },
|
||||
{ label: 'Species', prop: 'species', minWidth: 100 },
|
||||
{ label: '寄主类型', prop: 'hostType', minWidth: 100 },
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<HostBotanyInfoData>>({
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
zhSynonym: undefined,
|
||||
enName: undefined,
|
||||
latinName: undefined,
|
||||
latinSynonym: undefined,
|
||||
mu: undefined,
|
||||
orderTitle: undefined,
|
||||
ke: undefined,
|
||||
family: undefined,
|
||||
shu: undefined,
|
||||
genus: undefined,
|
||||
zhong: undefined,
|
||||
species: undefined,
|
||||
hostType: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{ label: '物种编码', prop: 'speciesCode', type: 'input', placeholder: '请输入物种编码' },
|
||||
{ label: '中文学名', prop: 'zhName', type: 'input', placeholder: '请输入中文学名' },
|
||||
{ label: '中文异名', prop: 'zhSynonym', type: 'input', placeholder: '请输入中文异名' },
|
||||
{ label: '英文学名', prop: 'enName', type: 'input', placeholder: '请输入英文学名' },
|
||||
{ label: '拉丁学名', prop: 'latinName', type: 'input', placeholder: '请输入拉丁学名' },
|
||||
{ label: '拉丁异名', prop: 'latinSynonym', type: 'input', placeholder: '请输入拉丁异名' },
|
||||
{ label: '目', prop: 'mu', type: 'input', placeholder: '请输入目' },
|
||||
{ label: 'Order', prop: 'orderTitle', type: 'input', placeholder: '请输入Order' },
|
||||
{ label: '科', prop: 'ke', type: 'input', placeholder: '请输入科' },
|
||||
{ label: 'Family', prop: 'family', type: 'input', placeholder: '请输入Family' },
|
||||
{ label: '属', prop: 'shu', type: 'input', placeholder: '请输入属' },
|
||||
{ label: 'Genus', prop: 'genus', type: 'input', placeholder: '请输入Genus' },
|
||||
{ label: '种', prop: 'zhong', type: 'input', placeholder: '请输入种' },
|
||||
{ label: 'Species', prop: 'species', type: 'input', placeholder: '请输入Species' },
|
||||
{ label: '寄主类型', prop: 'hostType', type: 'input', placeholder: '请输入寄主类型' },
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName()
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listHostBotany(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<HostBotanyInfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'select',
|
||||
options: specieslist.value.map((i) => {
|
||||
return {
|
||||
value: i.speciesCode,
|
||||
label: i.speciesCode,
|
||||
};
|
||||
}),
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入物种编码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择物种编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '中文学名',
|
||||
prop: 'zhName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入中文学名', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入中文学名',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '中文异名',
|
||||
prop: 'zhSynonym',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入中文异名',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入中文异名', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '英文学名',
|
||||
prop: 'enName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入英文学名',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入英文学名', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '拉丁学名',
|
||||
prop: 'latinName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入拉丁学名',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入拉丁学名', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '拉丁异名',
|
||||
prop: 'latinSynonym',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
|
||||
componentProps:{
|
||||
placeholder: '请输入拉丁异名',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入拉丁异名', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '目',
|
||||
prop: 'mu',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入目',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入目', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Order',
|
||||
prop: 'orderTitle',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Order',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Order', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '科',
|
||||
prop: 'ke',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入科',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入科', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Family',
|
||||
prop: 'family',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Family',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Family', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '属',
|
||||
prop: 'shu',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入属',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入属', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Genus',
|
||||
prop: 'genus',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Genus',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Genus', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '种',
|
||||
prop: 'zhong',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入种',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入种', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Species',
|
||||
prop: 'species',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Species',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Species', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '寄主类型',
|
||||
prop: 'hostType',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入寄主类型',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入寄主类型', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
const formData = ref<HostBotanyInfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
zhSynonym: undefined,
|
||||
enName: undefined,
|
||||
latinName: undefined,
|
||||
latinSynonym: undefined,
|
||||
mu: undefined,
|
||||
orderTitle: undefined,
|
||||
ke: undefined,
|
||||
family: undefined,
|
||||
shu: undefined,
|
||||
genus: undefined,
|
||||
zhong: undefined,
|
||||
species: undefined,
|
||||
hostType: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
auditStatus: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
remark: undefined,
|
||||
auditView: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: HostBotanyInfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
addHostBotany(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
updateHostBotany(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
zhSynonym: undefined,
|
||||
enName: undefined,
|
||||
latinName: undefined,
|
||||
latinSynonym: undefined,
|
||||
mu: undefined,
|
||||
orderTitle: undefined,
|
||||
ke: undefined,
|
||||
family: undefined,
|
||||
shu: undefined,
|
||||
genus: undefined,
|
||||
zhong: undefined,
|
||||
species: undefined,
|
||||
hostType: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
auditStatus: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
remark: undefined,
|
||||
auditView: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增寄主植物';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: HostBotanyInfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑寄主植物';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
const handleDelete = (row: HostBotanyTableColumns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
delHostBotany(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: HostBotanyTableColumns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: HostBotanyTableColumns) => {
|
||||
auditHostBotany(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
76
src/views/businesses/hostBotany/type.ts
Normal file
76
src/views/businesses/hostBotany/type.ts
Normal file
@ -0,0 +1,76 @@
|
||||
export interface HostBotanyTableColumns {
|
||||
id: number; //
|
||||
speciesCode: string; // 物种编码
|
||||
zhName: string; // 中文学名
|
||||
zhSynonym: string; // 中文异名
|
||||
enName: string; // 英文学名
|
||||
latinName: string; // 拉丁学名
|
||||
latinSynonym: string; // 拉丁异名
|
||||
mu: string; // 目
|
||||
orderTitle: string; // Order
|
||||
ke: string; // 科
|
||||
family: string; // Family
|
||||
shu: string; // 属
|
||||
genus: string; // Genus
|
||||
zhong: string; // 种
|
||||
species: string; // Species
|
||||
hostType: string; // 寄主类型
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; // 核查
|
||||
auditView: string; // 核查意见
|
||||
remark: string; // 备注
|
||||
version: number; // 版本
|
||||
createdAt: string; //
|
||||
}
|
||||
|
||||
export interface HostBotanyInfoData {
|
||||
id: number | undefined; //
|
||||
speciesCode: string | undefined; // 物种编码
|
||||
zhName: string | undefined; // 中文学名
|
||||
zhSynonym: string | undefined; // 中文异名
|
||||
enName: string | undefined; // 英文学名
|
||||
latinName: string | undefined; // 拉丁学名
|
||||
latinSynonym: string | undefined; // 拉丁异名
|
||||
mu: string | undefined; // 目
|
||||
orderTitle: string | undefined; // Order
|
||||
ke: string | undefined; // 科
|
||||
family: string | undefined; // Family
|
||||
shu: string | undefined; // 属
|
||||
genus: string | undefined; // Genus
|
||||
zhong: string | undefined; // 种
|
||||
species: string | undefined; // Species
|
||||
hostType: string | undefined; // 寄主类型
|
||||
sourcesData: string | undefined; // 数据来源
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集日期
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
auditStatus: number | undefined; // 核查
|
||||
auditView: string | undefined; // 核查意见
|
||||
remark: string | undefined; // 备注
|
||||
version: number | undefined; // 版本
|
||||
}
|
||||
|
||||
export interface HostBotanyTableDataState {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<HostBotanyTableColumns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface HostBotanyEditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: HostBotanyInfoData;
|
||||
rules: object;
|
||||
}
|
54
src/views/businesses/naturalEnemyInsect/api.ts
Normal file
54
src/views/businesses/naturalEnemyInsect/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询天敌昆虫列表
|
||||
export function reqList(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/naturalEnemyInsect/list',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询天敌昆虫详细
|
||||
export function reqGet(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/naturalEnemyInsect/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
// 新增天敌昆虫
|
||||
export function reqAdd(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/naturalEnemyInsect/add',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
// 修改天敌昆虫
|
||||
export function reqEdit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/naturalEnemyInsect/edit',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
// 删除天敌昆虫
|
||||
export function reqDel(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/naturalEnemyInsect/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reqAudit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/naturalEnemyInsect/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
826
src/views/businesses/naturalEnemyInsect/index.vue
Normal file
826
src/views/businesses/naturalEnemyInsect/index.vue
Normal file
@ -0,0 +1,826 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
:label-width="'130px'"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
v-auth="'api/v1/businesses/naturalEnemyInsect/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/naturalEnemyInsect/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/naturalEnemyInsect/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/naturalEnemyInsect/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/naturalEnemyInsect/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'140px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { reqAdd, reqAudit, reqDel, reqEdit, reqGet, reqList } from './api';
|
||||
import { Columns, InfoData, State } from '/@/views/businesses/naturalEnemyInsect/type';
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesNaturalEnemyInsectList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<State>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码(入侵种)', prop: 'speciesCode', minWidth: 140 },
|
||||
{ label: '中文名称(天敌)', prop: 'zhName', minWidth: 140 },
|
||||
{ label: '拉丁学名(天敌)', prop: 'latinName', minWidth: 140 },
|
||||
{ label: '目', prop: 'mu', minWidth: 100 },
|
||||
{ label: 'Order', prop: 'orderTitle', minWidth: 100 },
|
||||
{ label: '科', prop: 'ke', minWidth: 100 },
|
||||
{ label: 'Family', prop: 'family', minWidth: 100 },
|
||||
{ label: '属', prop: 'shu', minWidth: 100 },
|
||||
{ label: '原产地', prop: 'sourceArea', minWidth: 100 },
|
||||
{ label: '来源地', prop: 'source', minWidth: 100 },
|
||||
{ label: '释放地/实验地', prop: 'studyPlot', minWidth: 140 },
|
||||
{
|
||||
label: '引进时间/实验时间',
|
||||
prop: 'experimentDate',
|
||||
minWidth: 140,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d} {h}:{m}:{s}');
|
||||
},
|
||||
},
|
||||
{ label: '专一性', prop: 'selectivity', minWidth: 100 },
|
||||
{ label: '取食/危害阶段', prop: 'feedingHarm', minWidth: 140 },
|
||||
{ label: '取食/危害部位 ', prop: 'feedingPart', minWidth: 140 },
|
||||
{ label: '响应指标', prop: 'answerIndicator', minWidth: 100 },
|
||||
{ label: '释放记录', prop: 'releaseRecord', minWidth: 100 },
|
||||
{
|
||||
label: '是否建群',
|
||||
prop: 'isCreateGroup',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: number) {
|
||||
return val == 0 ? '否' : '是';
|
||||
},
|
||||
},
|
||||
{ label: '取食阶段', prop: 'feedingStage', minWidth: 100 },
|
||||
{
|
||||
label: '有无非目标影响',
|
||||
prop: 'isTarget',
|
||||
minWidth: 140,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: number) {
|
||||
return val == 0 ? '无' : '有';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '取食时间/活跃时间',
|
||||
prop: 'feedingDate',
|
||||
minWidth: 140,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d} {h}:{m}:{s}');
|
||||
},
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<InfoData>>({
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
latinName: undefined,
|
||||
mu: undefined,
|
||||
orderTitle: undefined,
|
||||
ke: undefined,
|
||||
family: undefined,
|
||||
shu: undefined,
|
||||
genus: undefined,
|
||||
sourceArea: undefined,
|
||||
source: undefined,
|
||||
selectivity: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码(入侵种)',
|
||||
prop: 'speciesCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入物种编码(入侵种)',
|
||||
},
|
||||
{
|
||||
label: '中文名称(天敌)',
|
||||
prop: 'zhName',
|
||||
type: 'input',
|
||||
placeholder: '请输入中文名称(天敌)',
|
||||
},
|
||||
{
|
||||
label: '拉丁学名(天敌)',
|
||||
prop: 'latinName',
|
||||
type: 'input',
|
||||
placeholder: '请输入拉丁学名(天敌)',
|
||||
},
|
||||
{ label: '目', prop: 'mu', type: 'input', placeholder: '请输入目' },
|
||||
{ label: 'Order', prop: 'orderTitle', type: 'input', placeholder: '请输入Order' },
|
||||
{ label: '科', prop: 'ke', type: 'input', placeholder: '请输入科' },
|
||||
{ label: 'Family', prop: 'family', type: 'input', placeholder: '请输入Family' },
|
||||
{ label: '属', prop: 'shu', type: 'input', placeholder: '请输入属' },
|
||||
{ label: 'Genus', prop: 'genus', type: 'input', placeholder: '请输入Genus' },
|
||||
{ label: '原产地', prop: 'sourceArea', type: 'input', placeholder: '请输入原产地' },
|
||||
{ label: '来源地', prop: 'source', type: 'input', placeholder: '请输入来源地' },
|
||||
{ label: '专一性', prop: 'selectivity', type: 'input', placeholder: '请输入专一性' },
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await reqList(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<InfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码(入侵种)',
|
||||
prop: 'speciesCode',
|
||||
type: 'select',
|
||||
options: specieslist.value.map((i) => {
|
||||
return {
|
||||
value: i.speciesCode,
|
||||
label: i.speciesCode,
|
||||
};
|
||||
}),
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入物种编码(入侵种)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择物种编码(入侵种)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '中文名称(天敌)',
|
||||
prop: 'zhName',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入中文名称(天敌)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入中文名称(天敌)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '拉丁学名(天敌)',
|
||||
prop: 'latinName',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入拉丁学名(天敌)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入拉丁学名(天敌)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '目',
|
||||
prop: 'mu',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入目',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入目', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Order',
|
||||
prop: 'orderTitle',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Order',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Order', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '科',
|
||||
prop: 'ke',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入科',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入科', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Family',
|
||||
prop: 'family',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Family',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Family', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '属',
|
||||
prop: 'shu',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入属',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入属', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: 'Genus',
|
||||
prop: 'genus',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入Genus',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入Genus', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '原产地',
|
||||
prop: 'sourceArea',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入原产地',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入原产地', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '来源地',
|
||||
prop: 'source',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入来源地',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '释放地/实验地',
|
||||
prop: 'studyPlot',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入释放地/实验地',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入释放地/实验地', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '引进时间/实验时间',
|
||||
prop: 'experimentDate',
|
||||
type: 'dateTime',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入引进时间/实验时间',
|
||||
type: 'datetime',
|
||||
defaultValue: new Date(),
|
||||
style: 'width: 100%',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入引进时间/实验时间', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '专一性',
|
||||
prop: 'selectivity',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请选择专一性',
|
||||
},
|
||||
rules: [{ required: true, message: '请选择专一性', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '取食/危害阶段',
|
||||
prop: 'feedingHarm',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入取食/危害阶段',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入取食/危害阶段', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '取食/危害部位',
|
||||
prop: 'feedingPart',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入取食/危害部位',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入取食/危害部位', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '响应指标',
|
||||
prop: 'answerIndicator',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入响应指标',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入响应指标', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '释放记录',
|
||||
prop: 'releaseRecord',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入释放记录',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入释放记录', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '是否建群',
|
||||
prop: 'isCreateGroup',
|
||||
type: 'radio',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入是否建群',
|
||||
},
|
||||
options: [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 0 },
|
||||
],
|
||||
rules: [{ required: true, message: '请输入是否建群', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '取食阶段',
|
||||
prop: 'feedingStage',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入取食阶段',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入取食阶段', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '有无非目标影响',
|
||||
prop: 'isTarget',
|
||||
type: 'radio',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入有无非目标影响',
|
||||
},
|
||||
options: [
|
||||
{ label: '有', value: 1 },
|
||||
{ label: '无', value: 0 },
|
||||
],
|
||||
rules: [{ required: true, message: '请输入有无非目标影响', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '取食时间/活跃时间',
|
||||
prop: 'feedingDate',
|
||||
type: 'dateTime',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入取食时间/活跃时间',
|
||||
type: 'datetime',
|
||||
defaultValue: new Date(),
|
||||
style: 'width: 100%',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入取食时间/活跃时间', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
style: 'width: 100%',
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const resetForm = <T,>(old: T) => {
|
||||
for (const v in old) {
|
||||
old[v] = undefined as T[Extract<keyof T, string>];
|
||||
}
|
||||
};
|
||||
const formData = ref<InfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
latinName: undefined,
|
||||
mu: undefined,
|
||||
orderTitle: undefined,
|
||||
ke: undefined,
|
||||
family: undefined,
|
||||
shu: undefined,
|
||||
genus: undefined,
|
||||
sourceArea: undefined,
|
||||
source: undefined,
|
||||
studyPlot: undefined,
|
||||
experimentDate: undefined,
|
||||
selectivity: undefined,
|
||||
feedingHarm: undefined,
|
||||
feedingPart: undefined,
|
||||
answerIndicator: undefined,
|
||||
releaseRecord: undefined,
|
||||
isCreateGroup: undefined,
|
||||
feedingStage: undefined,
|
||||
isTarget: undefined,
|
||||
feedingDate: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: InfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
reqAdd(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
reqEdit(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
zhName: undefined,
|
||||
latinName: undefined,
|
||||
mu: undefined,
|
||||
orderTitle: undefined,
|
||||
ke: undefined,
|
||||
family: undefined,
|
||||
shu: undefined,
|
||||
genus: undefined,
|
||||
sourceArea: undefined,
|
||||
source: undefined,
|
||||
studyPlot: undefined,
|
||||
experimentDate: undefined,
|
||||
selectivity: undefined,
|
||||
feedingHarm: undefined,
|
||||
feedingPart: undefined,
|
||||
answerIndicator: undefined,
|
||||
releaseRecord: undefined,
|
||||
isCreateGroup: undefined,
|
||||
feedingStage: undefined,
|
||||
isTarget: undefined,
|
||||
feedingDate: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增天敌昆虫';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: InfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑天敌昆虫';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
const handleDelete = (row: Columns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
reqDel(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: Columns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: Columns) => {
|
||||
reqAudit(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
90
src/views/businesses/naturalEnemyInsect/type.ts
Normal file
90
src/views/businesses/naturalEnemyInsect/type.ts
Normal file
@ -0,0 +1,90 @@
|
||||
export interface Columns {
|
||||
id: number; //
|
||||
speciesCode: string; // 物种编码(入侵种)
|
||||
zhName: string; // 中文名称(天敌)
|
||||
latinName: string; // 拉丁学名(天敌)
|
||||
mu: string; // 目
|
||||
orderTitle: string; // Order
|
||||
ke: string; // 科
|
||||
family: string; // Family
|
||||
shu: string; // 属
|
||||
genus: string; // Genus
|
||||
sourceArea: string; // 原产地
|
||||
source: string; // 来源地
|
||||
studyPlot: string; // 释放地/实验地
|
||||
experimentDate: string; // 引进时间/实验时间
|
||||
selectivity: string; // 专一性
|
||||
feedingHarm: string; // 取食/危害阶段
|
||||
feedingPart: string; // 取食/危害部位
|
||||
answerIndicator: string; // 响应指标
|
||||
releaseRecord: string; // 释放记录
|
||||
isCreateGroup: number; // 是否建群
|
||||
feedingStage: string; // 取食阶段
|
||||
isTarget: number; // 有无非目标影响
|
||||
feedingDate: string; // 取食时间/活跃时间
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; // 核查
|
||||
auditView: string; // 核查意见
|
||||
remark: string; // 备注
|
||||
version: number; // 版本
|
||||
createdAt: string; //
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
id: number | undefined; //
|
||||
speciesCode: string | undefined; // 物种编码(入侵种)
|
||||
zhName: string | undefined; // 中文名称(天敌)
|
||||
latinName: string | undefined; // 拉丁学名(天敌)
|
||||
mu: string | undefined; // 目
|
||||
orderTitle: string | undefined; // Order
|
||||
ke: string | undefined; // 科
|
||||
family: string | undefined; // Family
|
||||
shu: string | undefined; // 属
|
||||
genus: string | undefined; // Genus
|
||||
sourceArea: string | undefined; // 原产地
|
||||
source: string | undefined; // 来源地
|
||||
studyPlot: string | undefined; // 释放地/实验地
|
||||
experimentDate: string | undefined; // 引进时间/实验时间
|
||||
selectivity: string | undefined; // 专一性
|
||||
feedingHarm: string | undefined; // 取食/危害阶段
|
||||
feedingPart: string | undefined; // 取食/危害部位
|
||||
answerIndicator: string | undefined; // 响应指标
|
||||
releaseRecord: string | undefined; // 释放记录
|
||||
isCreateGroup: number | undefined; // 是否建群
|
||||
feedingStage: string | undefined; // 取食阶段
|
||||
isTarget: number | undefined; // 有无非目标影响
|
||||
feedingDate: string | undefined; // 取食时间/活跃时间
|
||||
sourcesData: string | undefined; // 数据来源
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集日期
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
auditStatus: number | undefined; // 核查
|
||||
auditView: string | undefined; // 核查意见
|
||||
remark: string | undefined; // 备注
|
||||
version: number | undefined; // 版本
|
||||
}
|
||||
|
||||
export interface State {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<Columns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: InfoData;
|
||||
rules: object;
|
||||
}
|
53
src/views/businesses/prevention/api.ts
Normal file
53
src/views/businesses/prevention/api.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import request from '/@/utils/request'
|
||||
// 查询防控措施列表
|
||||
export function listPrevention(query:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/prevention/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询防控措施详细
|
||||
export function getPrevention(id:number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/prevention/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增防控措施
|
||||
export function addPrevention(data:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/prevention/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改防控措施
|
||||
export function updatePrevention(data:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/prevention/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除防控措施
|
||||
export function delPrevention(ids:number[],version:number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/prevention/delete',
|
||||
method: 'delete',
|
||||
data:{
|
||||
ids:ids,
|
||||
version:version,
|
||||
}
|
||||
})
|
||||
}
|
||||
export function auditPrevention(data:object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/prevention/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
542
src/views/businesses/prevention/index.vue
Normal file
542
src/views/businesses/prevention/index.vue
Normal file
@ -0,0 +1,542 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" @click="handleAdd" v-auth="'api/v1/businesses/prevention/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/prevention/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/prevention/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/prevention/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/prevention/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'120px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import {
|
||||
listPrevention,
|
||||
delPrevention,
|
||||
addPrevention,
|
||||
updatePrevention,
|
||||
auditPrevention,
|
||||
} from './api';
|
||||
import { PreventionTableColumns, PreventionInfoData, PreventionTableDataState } from './type';
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesPreventionList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<PreventionTableDataState>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode', minWidth: 100 },
|
||||
{ label: '植物检疫', prop: 'botanyQuarantine', minWidth: 100 },
|
||||
{ label: '物理防治', prop: 'physics', minWidth: 100 },
|
||||
{ label: '化学防治', prop: 'chemistry', minWidth: 100 },
|
||||
{ label: '生物防治', prop: 'biology', minWidth: 100 },
|
||||
{ label: '其他防控措施', prop: 'other', minWidth: 120 },
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<PreventionInfoData>>({
|
||||
speciesCode: undefined,
|
||||
botanyQuarantine: undefined,
|
||||
physics: undefined,
|
||||
chemistry: undefined,
|
||||
biology: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{ label: '物种编码', prop: 'speciesCode', type: 'input', placeholder: '请输入物种编码' },
|
||||
{ label: '植物检疫', prop: 'botanyQuarantine', type: 'input', placeholder: '请输入植物检疫' },
|
||||
{ label: '物理防治', prop: 'physics', type: 'input', placeholder: '请输入物理防治' },
|
||||
{ label: '化学防治', prop: 'chemistry', type: 'input', placeholder: '请输入化学防治' },
|
||||
{ label: '生物防治', prop: 'biology', type: 'input', placeholder: '请输入生物防治' },
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
{ label: '数据采集日期', prop: 'createDate', type: 'daterange', valueFormat: 'YYYY-MM-DD' },
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listPrevention(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<PreventionInfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'select',
|
||||
options: specieslist.value.map((i) => {
|
||||
return {
|
||||
value: i.speciesCode,
|
||||
label: i.speciesCode,
|
||||
};
|
||||
}),
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入物种编码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择物种编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '植物检疫',
|
||||
prop: 'botanyQuarantine',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入植物检疫', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入植物检疫',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '物理防治',
|
||||
prop: 'physics',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入物理防治', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入物理防治',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '生物防治',
|
||||
prop: 'biology',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入生物防治', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入生物防治',
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '化学防治',
|
||||
prop: 'chemistry',
|
||||
span: 12,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入化学防治', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入化学防治',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '其他防控措施',
|
||||
prop: 'other',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入其他防控措施', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入其他防控措施',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
const formData = ref<PreventionInfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
botanyQuarantine: undefined,
|
||||
physics: undefined,
|
||||
biology: undefined,
|
||||
chemistry: undefined,
|
||||
other: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: PreventionInfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
addPrevention(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
updatePrevention(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
botanyQuarantine: undefined,
|
||||
physics: undefined,
|
||||
biology: undefined,
|
||||
chemistry: undefined,
|
||||
other: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增防控措施';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: PreventionInfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑防控措施';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
};
|
||||
const handleDelete = (row: PreventionTableColumns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
delPrevention(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: PreventionTableColumns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: PreventionTableColumns) => {
|
||||
auditPrevention(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
57
src/views/businesses/prevention/type.ts
Normal file
57
src/views/businesses/prevention/type.ts
Normal file
@ -0,0 +1,57 @@
|
||||
export interface PreventionTableColumns {
|
||||
id: number; //
|
||||
speciesCode: string; // 物种编码
|
||||
botanyQuarantine: string; // 植物检疫
|
||||
physics: string; // 物理防治
|
||||
chemistry: string; // 化学防治
|
||||
biology: string; // 生物防治
|
||||
other: string; // 其他防控措施
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; // 核查
|
||||
auditView: string; // 核查意见
|
||||
remark: string; // 备注
|
||||
version: number; // 版本
|
||||
}
|
||||
|
||||
export interface PreventionInfoData {
|
||||
id: number | undefined; //
|
||||
speciesCode: string | undefined; // 物种编码
|
||||
botanyQuarantine: string | undefined; // 植物检疫
|
||||
physics: string | undefined; // 物理防治
|
||||
chemistry: string | undefined; // 化学防治
|
||||
biology: string | undefined; // 生物防治
|
||||
other: string | undefined; // 其他防控措施
|
||||
sourcesData: string | undefined; // 数据来源
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集日期
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
auditStatus: number | undefined; // 核查
|
||||
auditView: string | undefined; // 核查意见
|
||||
remark: string | undefined; // 备注
|
||||
version: number | undefined; // 版本
|
||||
}
|
||||
|
||||
export interface PreventionTableDataState {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<PreventionTableColumns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface PreventionEditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: PreventionInfoData;
|
||||
rules: object;
|
||||
}
|
54
src/views/businesses/speciesImgs/api.ts
Normal file
54
src/views/businesses/speciesImgs/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询天敌昆虫列表
|
||||
export function reqList(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesImgs/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询天敌昆虫详细
|
||||
export function reqGet(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesImgs/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增天敌昆虫
|
||||
export function reqAdd(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesImgs/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改天敌昆虫
|
||||
export function reqEdit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesImgs/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除天敌昆虫
|
||||
export function reqDel(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesImgs/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reqAudit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesImgs/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
538
src/views/businesses/speciesImgs/index.vue
Normal file
538
src/views/businesses/speciesImgs/index.vue
Normal file
@ -0,0 +1,538 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
:label-width="'130px'"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" @click="handleAdd" v-auth="'api/v1/businesses/speciesImgs/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/speciesImgs/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/speciesImgs/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/speciesImgs/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/speciesImgs/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'140px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
<ImagesPreview ref="imgsPreviewRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed, defineAsyncComponent } from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { reqAdd, reqAudit, reqDel, reqEdit, reqList } from './api';
|
||||
import { Columns, InfoData, State } from '/@/views/businesses/speciesImgs/type';
|
||||
import { baseURL } from '/@/utils/gfast';
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
const ImagesPreview = defineAsyncComponent(() => import('/@/components/imgsPreview/index.vue'));
|
||||
defineOptions({ name: 'BusinessesDefinitenessList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<State>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode', minWidth: 140 },
|
||||
{ label: '图片类型', prop: 'imgType', minWidth: 140 },
|
||||
{ label: '图片来源', prop: 'imgSource', minWidth: 140 },
|
||||
{
|
||||
label: '图片',
|
||||
prop: 'imgs',
|
||||
minWidth: 140,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
try {
|
||||
const files =
|
||||
cellValue && typeof cellValue === 'string' ? JSON.parse(cellValue) : cellValue;
|
||||
return files
|
||||
.map((i: any) => {
|
||||
return i.name;
|
||||
})
|
||||
.join(` , `);
|
||||
} catch (error) {}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片拍摄/提供人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 140,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片拍摄/提供日期',
|
||||
minWidth: 140,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<InfoData>>({
|
||||
speciesCode: undefined,
|
||||
imgType: undefined,
|
||||
imgSource: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditStatus: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入物种编码',
|
||||
},
|
||||
{
|
||||
label: '图片类型',
|
||||
prop: 'imgType',
|
||||
type: 'input',
|
||||
placeholder: '请输入图片类型',
|
||||
},
|
||||
{
|
||||
label: '图片来源',
|
||||
prop: 'imgSource',
|
||||
type: 'input',
|
||||
placeholder: '请输入图片来源',
|
||||
},
|
||||
{
|
||||
label: '核查状态',
|
||||
prop: 'auditStatus',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '待审核', value: 0 },
|
||||
{ label: '通过', value: 1 },
|
||||
{ label: '不通过', value: 2 },
|
||||
],
|
||||
placeholder: '请选择核查状态',
|
||||
},
|
||||
{
|
||||
label: '图片拍摄/提供人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
{ label: '图片拍摄/提供日期', prop: 'createDate', type: 'daterange', valueFormat: 'YYYY-MM-DD' },
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await reqList(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<InfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
const imgsPreviewRef = ref();
|
||||
const handleCellClick = (row: InfoData, col: any) => {
|
||||
if (col.property != 'imgs') return;
|
||||
const { imgs } = row;
|
||||
const files = imgs && JSON.parse(imgs);
|
||||
imgsPreviewRef.value.openDialog(files);
|
||||
};
|
||||
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '物种编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'select',
|
||||
options: specieslist.value.map((i) => {
|
||||
return {
|
||||
value: i.speciesCode,
|
||||
label: i.speciesCode,
|
||||
};
|
||||
}),
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请输入物种编码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择物种编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片类型',
|
||||
prop: 'imgType',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入图片类型', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入图片类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片来源',
|
||||
prop: 'imgSource',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入图片来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入图片来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片拍摄/提供人',
|
||||
span: 24,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择图片拍摄/提供人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择图片拍摄/提供人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '图片拍摄/提供日期',
|
||||
span: 24,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择图片拍摄/提供日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
style: 'width: 100%',
|
||||
placeholder: '请选择图片拍摄/提供日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片',
|
||||
span: 24,
|
||||
prop: 'imgs',
|
||||
type: 'upload', // 对应 UploadImg 组件
|
||||
componentProps: {
|
||||
action: baseURL + 'api/v1/system/upload/singleImg',
|
||||
limit: 3,
|
||||
accept: '.jpg,.jpeg,.png,.gif',
|
||||
uploadSize: 5, // 文件大小限制(单位:MB)
|
||||
listType: 'picture-card',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const formData = ref<InfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
imgs: undefined,
|
||||
imgType: undefined,
|
||||
imgSource: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
remark: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditStatus: undefined,
|
||||
auditView: undefined,
|
||||
version: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: InfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
reqAdd(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
reqEdit(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
imgs: undefined,
|
||||
imgType: undefined,
|
||||
imgSource: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
remark: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditStatus: undefined,
|
||||
auditView: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增物种图片';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: InfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑物种图片';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
formData.value.imgs = JSON.parse(row.imgs as any);
|
||||
};
|
||||
const handleDelete = (row: Columns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
reqDel(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: Columns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: Columns) => {
|
||||
reqAudit(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
51
src/views/businesses/speciesImgs/type.ts
Normal file
51
src/views/businesses/speciesImgs/type.ts
Normal file
@ -0,0 +1,51 @@
|
||||
export interface Columns {
|
||||
id: number; //
|
||||
speciesCode: string; // 物种编码
|
||||
imgs: string; // 图片
|
||||
imgType: string; // 图片类型
|
||||
imgSource: string; // 图片来源
|
||||
createUser: number; // 图片拍摄/提供人
|
||||
createDate: string; // 图片拍摄/提供日期
|
||||
auditUser: string; // 图片核查人
|
||||
auditDate: string; // 图片核查日期
|
||||
auditStatus: number; // 核查
|
||||
auditView: string; // 核查意见
|
||||
remark: string; // 备注
|
||||
version: number; // 版本
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
id: number | undefined; //
|
||||
speciesCode: string | undefined; // 物种编码
|
||||
imgs: string | undefined; // 图片
|
||||
imgType: string | undefined; // 图片类型
|
||||
imgSource: string | undefined; // 图片来源
|
||||
createUser: number | undefined; // 图片拍摄/提供人
|
||||
createDate: string | undefined; // 图片拍摄/提供日期
|
||||
auditUser: string | undefined; // 图片核查人
|
||||
auditDate: string | undefined; // 图片核查日期
|
||||
auditStatus: number | undefined; // 核查
|
||||
auditView: string | undefined; // 核查意见
|
||||
remark: string | undefined; // 备注
|
||||
version: number | undefined; // 版本
|
||||
}
|
||||
|
||||
export interface State {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<Columns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: InfoData;
|
||||
rules: object;
|
||||
}
|
@ -36,16 +36,7 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
:show-expand="true"
|
||||
>
|
||||
<template #expand="{ row }">
|
||||
<el-form-item label="核查意见">
|
||||
{{ row.auditView }}
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
{{ row.remark }}
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@ -154,14 +145,14 @@ const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '物种编码', prop: 'speciesCode' },
|
||||
{ label: '物种名称', prop: 'name' },
|
||||
{ label: '物种名称内容', prop: 'content' },
|
||||
{ label: '物种编码', prop: 'speciesCode' ,minWidth:120,},
|
||||
{ label: '物种名称', prop: 'name' ,minWidth:120,},
|
||||
{ label: '物种名称内容', prop: 'content',minWidth:120, },
|
||||
{ label: '数据来源', prop: 'sourcesData' },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
isFormater: true,minWidth:120,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
@ -169,6 +160,7 @@ const columns: TableColumn[] = [
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth:120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_: SpeciesNameTableColumns, col: any, val: string) {
|
||||
@ -177,7 +169,7 @@ const columns: TableColumn[] = [
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
prop: 'auditUser',minWidth:120,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
@ -187,6 +179,7 @@ const columns: TableColumn[] = [
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth:120,
|
||||
isFormater: true,
|
||||
formater(_: SpeciesNameTableColumns, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
@ -200,6 +193,8 @@ const columns: TableColumn[] = [
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
@ -493,7 +488,9 @@ const handleDelete = (row: SpeciesNameTableColumns | null) => {
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: SpeciesNameTableColumns) => {
|
||||
auditFormRef.value.open(cloneDeep(row), userOptions.value);
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: SpeciesNameTableColumns) => {
|
||||
auditSpeciesName(val).then(() => {
|
||||
|
@ -6,7 +6,7 @@ export interface SpeciesNameTableColumns {
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集信息
|
||||
auditUser: number; // 数据核查人
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
remark: string; // 备注
|
||||
}
|
||||
@ -19,7 +19,7 @@ export interface SpeciesNameInfoData {
|
||||
sourcesData: string | undefined; // 数据来源
|
||||
createUser: number | undefined; // 数据采集人
|
||||
createDate: string | undefined; // 数据采集信息
|
||||
auditUser: number | undefined; // 数据核查人
|
||||
auditUser: string | undefined; // 数据核查人
|
||||
auditDate: string | undefined; // 数据核查日期
|
||||
remark: string | undefined; // 备注
|
||||
auditStatus?: number | undefined; // 审核状态
|
||||
|
54
src/views/businesses/speciesSurvey/api.ts
Normal file
54
src/views/businesses/speciesSurvey/api.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import request from '/@/utils/request';
|
||||
// 查询天敌昆虫列表
|
||||
export function reqList(query: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesSurvey/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询天敌昆虫详细
|
||||
export function reqGet(id: number) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesSurvey/get',
|
||||
method: 'get',
|
||||
params: {
|
||||
id: id.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增天敌昆虫
|
||||
export function reqAdd(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesSurvey/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 修改天敌昆虫
|
||||
export function reqEdit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesSurvey/edit',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 删除天敌昆虫
|
||||
export function reqDel(ids: number[], version: number[]) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesSurvey/delete',
|
||||
method: 'delete',
|
||||
data: {
|
||||
ids: ids,
|
||||
version: version,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function reqAudit(data: object) {
|
||||
return request({
|
||||
url: '/api/v1/businesses/speciesSurvey/audit',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
849
src/views/businesses/speciesSurvey/index.vue
Normal file
849
src/views/businesses/speciesSurvey/index.vue
Normal file
@ -0,0 +1,849 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="hover">
|
||||
<QueryForm
|
||||
v-model="searchForm"
|
||||
:fields="searchFields"
|
||||
@search="onSearch"
|
||||
@reset="onReset"
|
||||
:label-width="'140px'"
|
||||
ref="queryFormRef"
|
||||
/>
|
||||
|
||||
<el-row :gutter="10" style="padding-bottom: 10px">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
v-auth="'api/v1/businesses/speciesSurvey/add'"
|
||||
><el-icon><ele-Plus /></el-icon>新增</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete(null)"
|
||||
v-auth="'api/v1/businesses/speciesSurvey/delete'"
|
||||
><el-icon><ele-Delete /></el-icon>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<ProTable
|
||||
v-if="columns.length > 0"
|
||||
ref="proTableRef"
|
||||
:columns="columns"
|
||||
:data="tableData.data"
|
||||
:loading="loading"
|
||||
:show-selection="true"
|
||||
@selection-change="handleSelectionChange"
|
||||
:heightOffset="400"
|
||||
:action-width="280"
|
||||
@cell-click="handleCellClick"
|
||||
|
||||
>
|
||||
<template #actions="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleUpdate(row)"
|
||||
size="small"
|
||||
v-auth="'api/v1/businesses/speciesSurvey/edit'"
|
||||
v-if="row.auditStatus != 1"
|
||||
><el-icon><ele-EditPen /></el-icon>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'api/v1/businesses/speciesSurvey/delete'"
|
||||
><el-icon><ele-DeleteFilled /></el-icon>删除</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="handleAudit(row)"
|
||||
v-if="row.auditStatus == 0"
|
||||
v-auth="'api/v1/businesses/speciesSurvey/audit'"
|
||||
><el-icon><ele-Check /></el-icon>审核</el-button
|
||||
>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<pagination
|
||||
v-show="tableData.total > 0"
|
||||
:total="tableData.total"
|
||||
v-model:page="tableData.param.pageNum"
|
||||
v-model:limit="tableData.param.pageSize"
|
||||
@pagination="speciesNameList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<ModalForm
|
||||
v-model:visible="showDialog"
|
||||
:title="formTitle"
|
||||
:fields="formFields"
|
||||
v-model:modelValue="formData"
|
||||
:type="formType"
|
||||
:show-footer="true"
|
||||
:label-width="'150px'"
|
||||
:width="'50%'"
|
||||
@submit="handleFormSubmit"
|
||||
@cancel="handleCancel"
|
||||
ref="modalFormRef"
|
||||
>
|
||||
</ModalForm>
|
||||
|
||||
<AuditForm
|
||||
ref="auditFormRef"
|
||||
v-model="showAuditDialog"
|
||||
title="审核数据"
|
||||
@submit="onAuditSubmit"
|
||||
/>
|
||||
<ImagesPreview ref="imgsPreviewRef" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { toRefs, reactive, onMounted, ref, computed ,defineAsyncComponent} from 'vue';
|
||||
import { ElMessageBox, ElMessage } from 'element-plus';
|
||||
import { reqAdd, reqAudit, reqDel, reqEdit, reqList } from './api';
|
||||
import { Columns, InfoData, State } from '/@/views/businesses/speciesSurvey/type';
|
||||
import { baseURL } from '/@/utils/gfast';
|
||||
const ImagesPreview = defineAsyncComponent(() => import('/@/components/imgsPreview/index.vue'));
|
||||
|
||||
import QueryForm from '/@/components/dynamicpage/queryForm/index.vue';
|
||||
import ProTable from '/@/components/dynamicpage/ProTable/index.vue';
|
||||
import ModalForm from '/@/components/dynamicpage/modalForm/index.vue';
|
||||
import AuditForm from '/@/components/dynamicpage/auditForm/index.vue';
|
||||
import { QueryFormField, TableColumn, PopupFormField } from '/@/components/dynamicpage/type';
|
||||
import { getUserList } from '/@/api/system/user/index';
|
||||
import { UserItem, VersionMap } from '/@/types';
|
||||
import { parseTime } from '/@/utils/gfast';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { listSpeciesName } from '../speciesName/api';
|
||||
import { SpeciesNameInfoData } from '../speciesName/type';
|
||||
|
||||
defineOptions({ name: 'BusinessesSpeciesSurveyList' });
|
||||
|
||||
const loading = ref(false);
|
||||
// 非单个禁用
|
||||
const single = ref(true);
|
||||
// 非多个禁用
|
||||
const multiple = ref(true);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const state = reactive<State>({
|
||||
ids: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
param: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
const versionMap = ref<VersionMap>({} as VersionMap);
|
||||
const proTableRef = ref();
|
||||
const { tableData } = toRefs(state);
|
||||
const columns: TableColumn[] = [
|
||||
{ label: '调查记录编码', prop: 'speciesCode', minWidth: 140 },
|
||||
{ label: '物种名称', prop: 'speciesName', minWidth: 100 },
|
||||
{ label: '省(自治区、直辖市)', prop: 'province', minWidth: 160 },
|
||||
{ label: '市(地、州、盟)', prop: 'city', minWidth: 140 },
|
||||
{ label: '县(区、市、旗)', prop: 'county', minWidth: 140 },
|
||||
|
||||
{ label: '区划代码', prop: 'code', minWidth: 100 },
|
||||
{ label: '踏查路线名称', prop: 'courseName', minWidth: 120 },
|
||||
{ label: '踏查总面积(平方千米)', prop: 'markArea', minWidth: 160 },
|
||||
{ label: '踏查点名称', prop: 'markName', minWidth: 100 },
|
||||
{ label: '经度', prop: 'longitude', minWidth: 100 },
|
||||
{ label: '纬度', prop: 'dimensionality', minWidth: 100 },
|
||||
{ label: '海拔', prop: 'elevation', minWidth: 100 },
|
||||
{ label: '温度', prop: 'temperature', minWidth: 100 },
|
||||
{ label: '降水', prop: 'precipitation', minWidth: 100 },
|
||||
{ label: '踏查点面积(亩)', prop: 'markAreaM', minWidth: 120 },
|
||||
{ label: '生境类型', prop: 'habitatType', minWidth: 100 },
|
||||
{ label: '土壤类型', prop: 'soilType', minWidth: 100 },
|
||||
{ label: '危害对象', prop: 'harmObject', minWidth: 100 },
|
||||
{ label: '发生面积(亩)', prop: 'happenArea', minWidth: 120 },
|
||||
{ label: '治理措施(有 无)', prop: 'treatment', minWidth: 140 },
|
||||
{
|
||||
label: '是否设置标准样地',
|
||||
prop: 'isStandard',
|
||||
minWidth: 140,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '否' : '是';
|
||||
},
|
||||
},
|
||||
{ label: '标准样地编号', prop: 'standardCode', minWidth: 140 },
|
||||
{
|
||||
label: '是否采集标本',
|
||||
prop: 'isSpecimen',
|
||||
minWidth: 140,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '否' : '是';
|
||||
},
|
||||
},
|
||||
{ label: '标本编号', prop: 'specimenCode', minWidth: 100 },
|
||||
{
|
||||
label: '图片',
|
||||
prop: 'img',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const files = cellValue && typeof cellValue === 'string' ? JSON.parse(cellValue) : cellValue;
|
||||
return files
|
||||
.map((i: any) => {
|
||||
return i.name;
|
||||
})
|
||||
.join(` , `);
|
||||
},
|
||||
},
|
||||
{ label: '数据来源', prop: 'sourcesData', minWidth: 100 },
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
isFormater: true,
|
||||
minWidth: 100,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
minWidth: 120,
|
||||
prop: 'createDate',
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查人',
|
||||
prop: 'auditUser',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
const user = userOptions.value.find((i) => i.id === cellValue);
|
||||
return user ? user.userNickname : '';
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据核查日期',
|
||||
prop: 'auditDate',
|
||||
minWidth: 120,
|
||||
isFormater: true,
|
||||
formater(_, col: any, val: string) {
|
||||
return parseTime(val, '{y}-{m}-{d}');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'auditStatus',
|
||||
minWidth: 100,
|
||||
isFormater: true,
|
||||
formater(row, column, cellValue, index) {
|
||||
return cellValue == 0 ? '待审核' : cellValue == 1 ? '通过' : '不通过';
|
||||
},
|
||||
},
|
||||
{ label: '核查意见', prop: 'auditView', minWidth: 100 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 100 },
|
||||
];
|
||||
|
||||
const onSearch = async (val: Record<string, any>) => {
|
||||
let newVal: Record<string, any> = {};
|
||||
for (const v in val) {
|
||||
if (val[v] || val[v] === 0) {
|
||||
newVal[v] = val[v];
|
||||
}
|
||||
}
|
||||
state.tableData.param = { ...state.tableData.param, ...newVal };
|
||||
speciesNameList();
|
||||
};
|
||||
const onReset = () => {
|
||||
state.tableData.param = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
speciesNameList();
|
||||
};
|
||||
const searchForm = ref<Partial<InfoData>>({
|
||||
speciesCode: undefined,
|
||||
province: undefined,
|
||||
city: undefined,
|
||||
county: undefined,
|
||||
code: undefined,
|
||||
courseName: undefined,
|
||||
markName: undefined,
|
||||
habitatType: undefined,
|
||||
soilType: undefined,
|
||||
speciesName: undefined,
|
||||
standardCode: undefined,
|
||||
specimenCode: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
harmObject: undefined,
|
||||
});
|
||||
const searchFields = computed<QueryFormField[]>(() => [
|
||||
{
|
||||
label: '调查记录编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'input',
|
||||
placeholder: '请输入调查记录编码',
|
||||
},
|
||||
{
|
||||
label: '省(自治区、直辖市)',
|
||||
prop: 'province',
|
||||
type: 'input',
|
||||
placeholder: '请输入省(自治区、直辖市)',
|
||||
},
|
||||
{
|
||||
label: '市(地、州、盟)',
|
||||
prop: 'city',
|
||||
type: 'input',
|
||||
placeholder: '请输入市(地、州、盟)',
|
||||
},
|
||||
{ label: '县(区、市、旗)', prop: 'county', type: 'input', placeholder: '请输入县(区、市、旗)' },
|
||||
{ label: '区划代码', prop: 'code', type: 'input', placeholder: '请输入区划代码' },
|
||||
{ label: '踏查路线名称', prop: 'courseName', type: 'input', placeholder: '请输入踏查路线名称' },
|
||||
{ label: '踏查点名称', prop: 'markName', type: 'input', placeholder: '请输入踏查点名称' },
|
||||
{ label: '生境类型', prop: 'habitatType', type: 'input', placeholder: '请输入生境类型' },
|
||||
{ label: '土壤类型', prop: 'soilType', type: 'input', placeholder: '请输入土壤类型' },
|
||||
{ label: '物种名称', prop: 'speciesName', type: 'input', placeholder: '请输入物种名称' },
|
||||
{ label: '标准样地编号', prop: 'standardCode', type: 'input', placeholder: '请输入标准样地编号' },
|
||||
{ label: '标本编号', prop: 'specimenCode', type: 'input', placeholder: '请输入标本编号' },
|
||||
{ label: '数据来源', prop: 'sourcesData', type: 'input', placeholder: '请输入数据来源' },
|
||||
{ label: '危害对象', prop: 'harmObject', type: 'input', placeholder: '请输入危害对象' },
|
||||
|
||||
{
|
||||
label: '数据采集人',
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
]);
|
||||
|
||||
const specieslist = ref<SpeciesNameInfoData[]>([]);
|
||||
/**获取物种列表 */
|
||||
const reqListSpeciesName = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await listSpeciesName({ pageSize: 9999, pageNum: 1 });
|
||||
specieslist.value = res.data.list;
|
||||
};
|
||||
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initTableData();
|
||||
reqListSpeciesName();
|
||||
});
|
||||
// 初始化表格数据
|
||||
const initTableData = () => {
|
||||
speciesNameList();
|
||||
reqGetUserList();
|
||||
};
|
||||
// 获取列表数据
|
||||
const speciesNameList = async () => {
|
||||
loading.value = true;
|
||||
const res = await reqList(state.tableData.param);
|
||||
let list = res.data.list ?? [];
|
||||
state.tableData.data = list;
|
||||
versionMap.value = list.reduce((acc: any, cur: any) => {
|
||||
acc[cur.id] = cur.version;
|
||||
return acc;
|
||||
}, {});
|
||||
state.tableData.total = res.data.total;
|
||||
loading.value = false;
|
||||
};
|
||||
const reqGetUserList = async () => {
|
||||
if (userOptions.value.length > 0) return;
|
||||
const res = await getUserList({ pageSize: 9999, pageNum: 1 });
|
||||
userOptions.value = res.data.userList;
|
||||
};
|
||||
// 多选框选中数据
|
||||
const handleSelectionChange = (selection: Array<InfoData>) => {
|
||||
state.ids = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
const imgsPreviewRef = ref();
|
||||
const handleCellClick = (row: InfoData, col: any) => {
|
||||
if (col.property != 'img') return;
|
||||
const { img } = row;
|
||||
const files = img && JSON.parse(img);
|
||||
imgsPreviewRef.value.openDialog(files);
|
||||
};
|
||||
const showDialog = ref(false);
|
||||
const formTitle = ref('');
|
||||
const formFields = computed<PopupFormField[]>(() => [
|
||||
{
|
||||
label: '调查记录编码',
|
||||
prop: 'speciesCode',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入调查记录编码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择调查记录编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '物种名称',
|
||||
prop: 'speciesName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入物种名称', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入物种名称',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '省(自治区、直辖市)',
|
||||
prop: 'province',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入省(自治区、直辖市)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入省(自治区、直辖市)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '市(地、州、盟)',
|
||||
prop: 'city',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入市(地、州、盟)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入市(地、州、盟)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '县(区、市、旗)',
|
||||
prop: 'county',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入县(区、市、旗)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入县(区、市、旗)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '区划代码',
|
||||
prop: 'code',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入区划代码', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入区划代码',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '踏查路线名称',
|
||||
prop: 'courseName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入踏查路线名称', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入踏查路线名称',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '踏查总面积',
|
||||
prop: 'markArea',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入踏查总面积(平方千米)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入踏查总面积(平方千米)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '踏查点名称',
|
||||
prop: 'markName',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
componentProps: {
|
||||
placeholder: '请输入踏查点名称',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入踏查点名称', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入经度', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入经度',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'dimensionality',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入纬度', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入纬度',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '海拔',
|
||||
prop: 'elevation',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入海拔', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入海拔',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '气温',
|
||||
prop: 'temperature',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入气温', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入气温',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '降水量',
|
||||
prop: 'precipitation',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入降水量', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入降水量',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '踏查点面积(亩)',
|
||||
prop: 'markAreaM',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入踏查点面积(亩)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入踏查点面积(亩)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '生境类型',
|
||||
prop: 'habitatType',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入生境类型', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入生境类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '土壤类型',
|
||||
prop: 'soilType',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入土壤类型', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入土壤类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '危害对象',
|
||||
prop: 'harmObject',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入危害对象', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入危害对象',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '发生面积(亩)',
|
||||
prop: 'happenArea',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入发生面积(亩)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入发生面积(亩)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label:'治理措施',
|
||||
prop: 'treatment',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入治理措施(有 无)', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入治理措施(有 无)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '是否设置标准样地',
|
||||
prop: 'isStandard',
|
||||
type: 'radio',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入是否设置标准样地', trigger: 'change' }],
|
||||
options: [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '标准样地编号',
|
||||
prop: 'standardCode',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入标准样地编号', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入标准样地编号',
|
||||
},
|
||||
},
|
||||
{
|
||||
label:"是否采集标本",
|
||||
prop: 'isSpecimen',
|
||||
type: 'radio',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入是否采集标本', trigger: 'change' }],
|
||||
options: [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '标本编号',
|
||||
prop: 'specimenCode',
|
||||
type: 'input',
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请输入标本编号', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入标本编号',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '图片',
|
||||
prop: 'img',
|
||||
type: 'upload',
|
||||
span: 24,
|
||||
componentProps: {
|
||||
action: baseURL + 'api/v1/system/upload/singleImg',
|
||||
limit: 3,
|
||||
accept: '.jpg,.jpeg,.png,.gif',
|
||||
uploadSize: 5, // 文件大小限制(单位:MB)
|
||||
listType: 'picture-card',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
prop: 'sourcesData',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
rules: [{ required: true, message: '请输入数据来源', trigger: 'blur' }],
|
||||
componentProps: {
|
||||
placeholder: '请输入数据来源',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '数据采集人',
|
||||
span: 12,
|
||||
prop: 'createUser',
|
||||
type: 'select',
|
||||
rules: [{ required: true, message: '请选择数据采集人', trigger: 'change' }],
|
||||
componentProps: {
|
||||
placeholder: '请选择数据采集人',
|
||||
},
|
||||
options: userOptions.value.map((i) => {
|
||||
return {
|
||||
label: i.userNickname,
|
||||
value: i.id,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
label: '数据采集日期',
|
||||
span: 12,
|
||||
prop: 'createDate',
|
||||
type: 'date',
|
||||
rules: [{ required: true, message: '请选择数据采集日期', trigger: 'change' }],
|
||||
componentProps: {
|
||||
style: 'width: 100%',
|
||||
placeholder: '请选择数据采集日期',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
span: 24,
|
||||
type: 'input',
|
||||
componentProps: {
|
||||
placeholder: '请输入备注',
|
||||
type: 'textarea',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const formData = ref<InfoData>({
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
province: undefined,
|
||||
city: undefined,
|
||||
county: undefined,
|
||||
code: undefined,
|
||||
courseName: undefined,
|
||||
markArea: undefined,
|
||||
markName: undefined,
|
||||
longitude: undefined,
|
||||
dimensionality: undefined,
|
||||
elevation: undefined,
|
||||
temperature: undefined,
|
||||
precipitation: undefined,
|
||||
markAreaM: undefined,
|
||||
habitatType: undefined,
|
||||
soilType: undefined,
|
||||
speciesName: undefined,
|
||||
harmObject: undefined,
|
||||
happenArea: undefined,
|
||||
treatment: undefined,
|
||||
isStandard: undefined,
|
||||
standardCode: undefined,
|
||||
img: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
isSpecimen: undefined,
|
||||
specimenCode: undefined,
|
||||
});
|
||||
const formType = ref<'add' | 'edit'>('add');
|
||||
|
||||
const handleFormSubmit = (form: InfoData) => {
|
||||
if (formType.value === 'add') {
|
||||
reqAdd(form).then(() => {
|
||||
ElMessage.success('新增成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
} else {
|
||||
form.auditStatus = 0;
|
||||
reqEdit(form).then(() => {
|
||||
ElMessage.success('编辑成功');
|
||||
handleCancel();
|
||||
speciesNameList();
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
showDialog.value = false;
|
||||
formTitle.value = '';
|
||||
formType.value = 'add';
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
speciesCode: undefined,
|
||||
province: undefined,
|
||||
city: undefined,
|
||||
county: undefined,
|
||||
code: undefined,
|
||||
courseName: undefined,
|
||||
markArea: undefined,
|
||||
markName: undefined,
|
||||
longitude: undefined,
|
||||
dimensionality: undefined,
|
||||
elevation: undefined,
|
||||
temperature: undefined,
|
||||
precipitation: undefined,
|
||||
markAreaM: undefined,
|
||||
habitatType: undefined,
|
||||
soilType: undefined,
|
||||
speciesName: undefined,
|
||||
harmObject: undefined,
|
||||
happenArea: undefined,
|
||||
treatment: undefined,
|
||||
isStandard: undefined,
|
||||
standardCode: undefined,
|
||||
img: undefined,
|
||||
sourcesData: undefined,
|
||||
createUser: undefined,
|
||||
createDate: undefined,
|
||||
auditUser: undefined,
|
||||
auditDate: undefined,
|
||||
auditView: undefined,
|
||||
auditStatus: undefined,
|
||||
remark: undefined,
|
||||
version: undefined,
|
||||
isSpecimen: undefined,
|
||||
specimenCode: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '新增物种调查';
|
||||
formType.value = 'add';
|
||||
};
|
||||
const handleUpdate = (row: InfoData) => {
|
||||
showDialog.value = true;
|
||||
formTitle.value = '编辑物种调查';
|
||||
formType.value = 'edit';
|
||||
formData.value = cloneDeep(row);
|
||||
formData.value.img = JSON.parse(row.img as any);
|
||||
};
|
||||
const handleDelete = (row: Columns | null) => {
|
||||
let msg = '你确定要删除所选数据?';
|
||||
let id: number[] = [];
|
||||
if (row) {
|
||||
msg = `此操作将永久删除数据,是否继续?`;
|
||||
id = [row.id];
|
||||
} else {
|
||||
id = state.ids;
|
||||
}
|
||||
if (id.length === 0) {
|
||||
ElMessage.error('请选择要删除的数据。');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(msg, '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
reqDel(
|
||||
id,
|
||||
id.map((i) => versionMap.value[i])
|
||||
).then(() => {
|
||||
ElMessage.success('删除成功');
|
||||
speciesNameList();
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const auditFormRef = ref();
|
||||
const showAuditDialog = ref(false);
|
||||
const handleAudit = (row: Columns) => {
|
||||
const val = cloneDeep(row);
|
||||
val.auditUser = '';
|
||||
auditFormRef.value.open(val, userOptions.value);
|
||||
};
|
||||
const onAuditSubmit = (val: Columns) => {
|
||||
reqAudit(val).then(() => {
|
||||
ElMessage.success('审核成功');
|
||||
showAuditDialog.value = false;
|
||||
speciesNameList();
|
||||
});
|
||||
};
|
||||
</script>
|
95
src/views/businesses/speciesSurvey/type.ts
Normal file
95
src/views/businesses/speciesSurvey/type.ts
Normal file
@ -0,0 +1,95 @@
|
||||
export interface Columns {
|
||||
id: number; //
|
||||
speciesCode: string; // 调查记录编码
|
||||
province: string; // 省(自治区、直辖市)
|
||||
city: string; // 市(地、州、盟)
|
||||
county: string; // 县(区、市、旗)
|
||||
code: string; // 区划代码
|
||||
courseName: string; // 踏查路线名称
|
||||
markArea: string; // 踏查总面积(平方千米)
|
||||
markName: string; // 踏查点名称
|
||||
longitude: string; // 经度
|
||||
dimensionality: string; // 纬度
|
||||
elevation: string; // 海拔
|
||||
temperature: string; // 温度
|
||||
precipitation: string; // 降水
|
||||
markAreaM: string; // 踏查点面积(亩)
|
||||
habitatType: string; // 生境类型
|
||||
soilType: string; // 土壤类型
|
||||
speciesName: string; // 物种名称
|
||||
harmObject: string; // 危害对象
|
||||
happenArea: string; // 发生面积(亩)
|
||||
treatment: number; // 治理措施(有 无)
|
||||
isStandard: number; // 是否设置标准样地
|
||||
standardCode: string; // 标准样地编号
|
||||
isSpecimen: number; // 是否采集标本
|
||||
specimenCode: string; // 标本编号
|
||||
img: string; // 图片
|
||||
sourcesData: string; // 数据来源
|
||||
createUser: number; // 数据采集人
|
||||
createDate: string; // 数据采集日期
|
||||
auditUser: string; // 数据核查人
|
||||
auditDate: string; // 数据核查日期
|
||||
auditStatus: number; //
|
||||
auditView: string; //
|
||||
remark: string; //
|
||||
version: number; //
|
||||
}
|
||||
|
||||
export interface InfoData {
|
||||
id:number|undefined; //
|
||||
speciesCode:string|undefined; // 调查记录编码
|
||||
province:string|undefined; // 省(自治区、直辖市)
|
||||
city:string|undefined; // 市(地、州、盟)
|
||||
county:string|undefined; // 县(区、市、旗)
|
||||
code:string|undefined; // 区划代码
|
||||
courseName:string|undefined; // 踏查路线名称
|
||||
markArea:string|undefined; // 踏查总面积(平方千米)
|
||||
markName:string|undefined; // 踏查点名称
|
||||
longitude:string|undefined; // 经度
|
||||
dimensionality:string|undefined; // 纬度
|
||||
elevation:string|undefined; // 海拔
|
||||
temperature:string|undefined; // 温度
|
||||
precipitation:string|undefined; // 降水
|
||||
markAreaM:string|undefined; // 踏查点面积(亩)
|
||||
habitatType:string|undefined; // 生境类型
|
||||
soilType:string|undefined; // 土壤类型
|
||||
speciesName:string|undefined; // 物种名称
|
||||
harmObject:string|undefined; // 危害对象
|
||||
happenArea:string|undefined; // 发生面积(亩)
|
||||
treatment:number|undefined; // 治理措施(有 无)
|
||||
isStandard:number|undefined; // 是否设置标准样地
|
||||
standardCode:string|undefined; // 标准样地编号
|
||||
isSpecimen:number|undefined; // 是否采集标本
|
||||
specimenCode:string|undefined; // 标本编号
|
||||
img:string|undefined; // 图片
|
||||
sourcesData:string|undefined; // 数据来源
|
||||
createUser:number|undefined; // 数据采集人
|
||||
createDate:string|undefined; // 数据采集日期
|
||||
auditUser:string|undefined; // 数据核查人
|
||||
auditDate:string|undefined; // 数据核查日期
|
||||
auditStatus:number|undefined; //
|
||||
auditView:string|undefined; //
|
||||
remark:string|undefined; //
|
||||
version:number|undefined; //
|
||||
}
|
||||
|
||||
export interface State {
|
||||
ids: any[];
|
||||
tableData: {
|
||||
data: Array<Columns>;
|
||||
total: number;
|
||||
loading: boolean;
|
||||
param: {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditState {
|
||||
loading: boolean;
|
||||
isShowDialog: boolean;
|
||||
formData: InfoData;
|
||||
rules: object;
|
||||
}
|
@ -265,7 +265,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
data: [
|
||||
{ name: 'gfastV3', value: 520 },
|
||||
{ name: '外来入侵物种智能决策可视化模拟后台管理系统', value: 520 },
|
||||
{ name: 'lyt', value: 520 },
|
||||
{ name: 'next-admin', value: 500 },
|
||||
{ name: '更名', value: 420 },
|
||||
|
@ -116,7 +116,7 @@ const verifyStatus = ref(0)
|
||||
const state = reactive({
|
||||
isShowPassword: false,
|
||||
ruleForm: {
|
||||
username: 'demo',
|
||||
username: 'zs',
|
||||
password: 'Demo123',
|
||||
verifyCode: '',
|
||||
verifyKey:''
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="login-icon-group">
|
||||
<div class="login-icon-group-title">
|
||||
<img :src="logoMini" />
|
||||
<div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div>
|
||||
<div class="login-icon-group-title-text font20">{{ getThemeConfig.globalViceTitle }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isScan">
|
||||
|
@ -72,7 +72,7 @@ export default defineComponent({
|
||||
router.push({
|
||||
name: 'paramsDynamicDetails',
|
||||
params: {
|
||||
t: 'gfast3.2后台管理系统',
|
||||
t: '外来入侵物种智能决策可视化模拟后台管理系统',
|
||||
id: state.value,
|
||||
tagsViewName: state.tagsViewName,
|
||||
},
|
||||
|
@ -221,7 +221,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="cell">GFast系统使用:</div>
|
||||
<div class="cell">外来入侵物种智能决策可视化模拟后台管理系统</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell">{{ memorySizeFormat(sysInfo.goUsed)}}</div>
|
||||
|
@ -51,7 +51,7 @@
|
||||
<el-table-column label="操作" width="220">
|
||||
<template #default="scope">
|
||||
<el-button size="small" text type="primary" @click="onOpenEditRole(scope.row)"><el-icon><ele-EditPen /></el-icon>修改</el-button>
|
||||
<el-dropdown class="auth-action" @command="handleCommand">
|
||||
<!-- <el-dropdown class="auth-action" @command="handleCommand">
|
||||
<span class="el-dropdown-link">
|
||||
授权 <el-icon><ele-ArrowDown /></el-icon>
|
||||
</span>
|
||||
@ -62,7 +62,7 @@
|
||||
<el-dropdown-item :command="'user_'+scope.row.id">用户授权</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-dropdown> -->
|
||||
<el-button size="small" text type="primary" @click="onRowDel(scope.row)"><el-icon><ele-DeleteFilled /></el-icon>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
Loading…
x
Reference in New Issue
Block a user