Merge pull request 'master' (#1002) from master into prod

Reviewed-on: http://git.feashow.cn/clay/mosr-web/pulls/1002
This commit is contained in:
2025-04-27 06:29:31 +00:00

View File

@@ -4,22 +4,37 @@
<fvForm :schema="schema" @getInstance="(e)=>baseForm = e" label-position="left" label-width="left"
style="margin-left: 15px;margin-bottom: -18px"></fvForm>
<baseTitle title="项目实施-上传附件" ></baseTitle>
<el-form :model="formData" ref="tagForm" label-width="auto">
<el-form-item label="标签名称" prop="tagName" style="margin-left: 15px;">
<el-input v-model="formData.tagName" placeholder="请输入标签名称" style="width: 300px;margin-right: 10px" v-if="showInput" clearable/>
<el-select v-model="formData.tagName" placeholder="请选择标签名称" clearable filterable style="width: 300px;margin-right: 10px" v-else>
<el-option
v-for="item in tagsOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button type="primary" link @click="changeInput">{{ showInput ? '选择' : '输入' }}</el-button>
</el-form-item>
</el-form>
<!-- <baseTitle title="其他文件"></baseTitle>-->
<file-upload @getFile="getFile" :disabled="!formData.tagName" :title="!formData.tagName?'请先选择/输入标签!':''" style="margin-left: 15px"/>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleTabClick" @tab-remove="tabRemove"
style="margin-left: 15px;margin-top: -10px">
<el-tab-pane name="all" :closable="false" label="全部">
</el-tab-pane>
<el-tab-pane v-for="item in tagsOption" :closable="item.isClose==1"
:key="item.tagId"
:label="item.fileTag"
:name="item.tagId">
<div class="tag-title">
<div></div>
{{ item.fileTag }}
</div>
</el-tab-pane>
<el-tab-pane name="plus" :closable="false">
<template #label>
<div style="margin-top: 4px;">
<el-icon color="#BEA266">
<Plus/>
</el-icon>
</div>
</template>
</el-tab-pane>
</el-tabs>
<div style="margin-top:10px;margin-bottom: 8px;margin-left: 15px;display: flex">
<file-upload v-if="activeName!='plus'&&activeName!='all'" @getFile="getFile"/>
<el-button color="#DED0B2" @click="handleEditTag" v-if="activeName!='all'&&activeName!='plus'&&!isDefault"
style="margin-left: 10px;">编辑
</el-button>
</div>
<fvTable style="width: 100%;max-height: 318px;" v-if="showTable" height="318" :tableConfig="tableConfig"
:data="fileList" :isSettingCol="false" :pagination="false">
<template #empty>
@@ -31,15 +46,25 @@
</div>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
<el-dialog v-model="tagNameShow" center width="450" top="40vh">
<div style="display: flex;align-items: center">标签
<el-input v-model="fileParam.tagName" placeholder="请输入标签名称" style="width: 335px;" clearable/>
</div>
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
<el-button color="#DED0B2" @click="changeTag()">确定</el-button>
<el-button @click="tagNameShow=false">取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script setup lang="jsx">
import {getTags} from "@/api/project-manage";
import {ElNotification} from "element-plus";
import {addTag, delTag, getTagList, getTags, updateTag} from "@/api/project-manage";
import {ElMessageBox, ElNotification} from "element-plus";
import {useTagsView} from '@/stores/tagsview.js'
import {uploadFileList} from "@/api/project-manage/attachment";
import {computed, ref} from "vue";
import {searchImplementationFileList, uploadFileList} from "@/api/project-manage/attachment";
import {computed, nextTick, ref} from "vue";
import {getBaseInfoApi} from "@/components/steps/api";
import {deleteFile, downloadFile} from "@/api/project-demand";
@@ -52,7 +77,11 @@ const tagsViewStore = useTagsView()
const route = useRoute()
const router = useRouter()
const fileList = ref([])
const allFileList = ref([])
const activeName = ref('all')
const tagNameShow = ref(false)
const showInput = ref(false)
const isDefault = ref(false)
const baseFormData = ref([])
const schema = computed(() => {
return [
@@ -197,6 +226,22 @@ const schema = computed(() => {
</div>
)
},
{
label: '实际经费预算(元)',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '产学研联合',
prop: 'industryUniversityResearch',
@@ -238,6 +283,22 @@ const schema = computed(() => {
},
{
label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount',
colProps: {
span: 6
@@ -246,7 +307,7 @@ const schema = computed(() => {
<div>
{
baseFormData.value?.specialFundAmount ?
<span>{ toThousands(baseFormData.value?.specialFundAmount )}</span>
<span>{toThousands(baseFormData.value?.specialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
@@ -274,12 +335,19 @@ const schema = computed(() => {
colProps: {
span: 6
}
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
}
]
})
const baseForm = ref()
const tagsOption = ref([])
const formData = ref({
const fileParam = ref({
tagName: ''
})
const tableConfig = reactive({
@@ -318,8 +386,11 @@ const tableConfig = reactive({
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
{
row.oldType ? null : <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
onDelete={() => handleDelete(row)}/>
}
</div>
)
}
@@ -338,11 +409,147 @@ const filePreviewParam = ref({
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const isEdit = ref(false)
const changeTag = async () => {
let res = null
if (isEdit.value) {
res = await updateTag({
tagId: activeName.value,
fileTag: fileParam.value.tagName,
projectId: route.query.projectId,
})
} else {
res = await addTag({
projectId: route.query.projectId,
fileTag: fileParam.value.tagName
})
fileParam.value.tagName = ''
activeName.value = 'all'
}
getTagsOption()
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
tagNameShow.value = false;
}
const getOldFileList = (tag,flag) => {
let params = {}
if (tag == 'all') {
params = {
targetId: route.query.projectId,
targetState: "30",
}
} else {
params = {
targetId: route.query.projectId,
targetState: "30",
tag: getTagName(activeName.value)
}
}
showTable.value = false
searchImplementationFileList(params).then(res => {
if (res.code === 1000) {
if(tag == 'all'){
res.data.fileList?.forEach(item=>{
item.oldType=true
fileList.value.push(item)
})
}else{
console.log("🚀 ~ file:'res.data.fileList ",res.data.fileList )
res.data.fileList?.forEach(item=>{
item.oldType=true
if(getTagName(activeName.value)==item.tag){
fileList.value.push(item)
}
})
console.log("🚀 ~ file:'fileList.value ",fileList.value)
}
if(flag){
getTagsOption(flag)
}
nextTick(() => {
showTable.value = true
})
changeImplementFile()
}
})
}
const handleEditTag = () => {
fileParam.value.tagName = getTagName(activeName.value)
if(fileList.value&&fileList.value.length>0){
ElNotification({
title: '提示',
message: '该标签下存在文件,不能编辑标签。如需编辑标签,请先删除该标签下的所有文件。',
type: 'error'
})
return;
}
tagNameShow.value = true
isEdit.value = true
}
const tabRemove = async (val) => {
if(fileList.value&&fileList.value.length>0){
ElNotification({
title: '提示',
message: '该标签下存在文件,不能删除标签。如需删除标签,请先删除该标签下的所有文件。',
type: 'error'
})
return;
}
ElMessageBox.confirm(`确认删除名称为${getTagName(val)}的标签吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
let res = await delTag(val)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
getTagsOption()
}
})
}
const handleTabClick = (item) => {
const defaultArray=tagsOption.value.filter(item1=>item1.tagId==item.props.name)
if(defaultArray&&defaultArray.length>0){
isDefault.value=defaultArray[0].isDefault==1
}else{
isDefault.value=false
}
tagNameShow.value = item.props.name == 'plus';
if (item.props.name == 'plus') {
isEdit.value = false
fileParam.value.tagName = ''
}
const fileArray=JSON.parse(localStorage.getItem('implementFile'))
if (item.props.name != 'plus') {
if (item.props.name == 'all') {
fileList.value=fileArray
getOldFileList('all')
} else {
fileList.value=fileArray.filter(item1 => item1.tag == getTagName(item.props.name))
getOldFileList()
showTable.value = false
nextTick(() => {
showTable.value = true
})
}
}
}
if(localStorage.getItem('implementFile')){
fileList.value=JSON.parse(localStorage.getItem('implementFile'))
allFileList.value=JSON.parse(localStorage.getItem('implementFile'))
}
const changeImplementFile=()=>{
localStorage.setItem('implementFile', JSON.stringify(fileList.value))
localStorage.setItem('implementFile', JSON.stringify(allFileList.value))
}
const clickToPreview=(row)=>{
@@ -358,7 +565,7 @@ const clickToPreview=(row)=>{
}
onActivated(() => {
console.log('onActivated')
formData.value.tagName = '';
fileParam.value.tagName = '';
showTable.value = false
nextTick(() => {
showTable.value = true
@@ -371,7 +578,7 @@ const filterDict = (data, value) => {
let label = ''
let result = []
if (value instanceof Array) {
value.forEach(item1 => {
value?.forEach(item1 => {
data.find(item => {
if (item.value == item1) {
result.push(item.label)
@@ -425,14 +632,54 @@ const getBaseInfo = async () => {
getBaseInfo()
const changeInput = () => {
showInput.value = !showInput.value;
formData.value.tagName = '';
fileParam.value.tagName = '';
}
const getTagName = (name) => {
const tagArray = tagsOption.value.filter((item1) => item1.tagId == name)
let tagName = ''
if (tagArray && tagArray.length > 0) {
tagName = tagArray[0].fileTag
}
return tagName
}
const getTagsOption = () => {
if (!route.query.projectId) return
getTags(route.query.projectId).then(res => {
getTagList(route.query.projectId).then(res => {
if (res.code === 1000) {
showInput.value = res.data.length === 0;
tagsOption.value = res.data
tagsOption.value = res.data.rows
console.log("🚀 ~ file: res.data.rows ", res.data.rows)
tagsOption.value?.forEach((tag, index) => {
tagsOption.value[index].isClose =1
})
let defaultArray=[
{
tagId: 'd1',
fileTag: '合同(专项任务书)',
isDefault: 1,
isClose: 2
},
{
tagId: 'd2',
fileTag: '周报',
isDefault: 1,
isClose: 2
},
{
tagId: 'd3',
fileTag: '阶段性验收',
isDefault: 1,
isClose: 2
},
{
tagId: 'd4',
fileTag: '科研成果',
isDefault: 1,
isClose: 2
}
]
tagsOption.value=[...defaultArray,...tagsOption.value]
console.log("🚀 ~ file:tagsOption.value ", tagsOption.value)
}else{
ElNotification({
title: '提示',
@@ -444,9 +691,9 @@ const getTagsOption = () => {
}
const compositeParam = (item) => {
tagsOption.value.forEach(item => {
if (item.value == formData.value.tagName) {
formData.value.tagName = item.label
tagsOption.value?.forEach(item => {
if (item.value == fileParam.value.tagName) {
fileParam.value.tagName = item.label
}
})
return {
@@ -456,7 +703,7 @@ const compositeParam = (item) => {
fileType: item.fileType,
url: item.url,
newFile: true,
tag: formData.value.tagName,
tag: getTagName(activeName.value) || '项目实施',
}
}
const getFile = (val) => {
@@ -464,24 +711,17 @@ const getFile = (val) => {
showTable.value = false
let fileObj = compositeParam(val)
fileList.value.push(fileObj)
allFileList.value.push(fileObj)
nextTick(() => {
showTable.value = true
})
changeImplementFile()
}
const handleSubmit = async (instance) => {
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
const files=JSON.parse(localStorage.getItem('implementFile'))
let params = {
fileList: fileList.value,
fileList: files,
projectId: route.query.projectId,
targetState: "30"
}
@@ -525,9 +765,9 @@ const handleSubmit = async (instance) => {
}
localStorage.removeItem('implementFile')
}
})
}
getTagsOption()
getOldFileList('all')
</script>
<style scoped lang="scss">
@@ -550,4 +790,12 @@ getTagsOption()
}
}
}
:deep(.el-tabs__item.is-active) {
color: #BEA266;
}
:deep(.el-tabs__active-bar) {
background-color: #BEA266;
}
</style>