Refactor code structure and remove redundant changes

This commit is contained in:
wangqiao
2025-08-15 16:45:15 +08:00
commit 99df1d1f81
220 changed files with 33086 additions and 0 deletions

View File

@ -0,0 +1,250 @@
<template>
<div>
<el-form-item label-width="110px" :prop="`${props.vaildRules}.files`" :rules="{ required: true, message: '请上传图纸', trigger: ['blur', 'change'] }">
<KlUploader
v-model:file-list="form.files"
:limit="1000"
:show-tip="false"
:cad-show="true"
:file-type="computFileType"
@validate="formRef?.validateField(`${props.vaildRules}.files`)"
@preview="handlePreview"
>
</KlUploader>
</el-form-item>
<el-form-item
label-width="110px"
label="标题:"
:prop="`${props.vaildRules}.title`"
:rules="{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }"
>
<el-input v-model="form.title" placeholder="请输入标题" class="w-361px!" maxlength="128"></el-input>
</el-form-item>
<el-form-item
label-width="110px"
label="分类:"
:prop="`${props.vaildRules}.projectType`"
:rules="{ required: true, message: '请选择分类', trigger: ['blur', 'change'] }"
>
<!-- <el-select v-model="form.projectType" placeholder="请选择分类" class="w-361px!" multiple>
<el-option v-for="(item, index) in projectTypeList" :key="index" :label="item.name" :value="item.id" />
</el-select> -->
<el-cascader v-model="form.projectType" class="w-361px!" :options="projectTypeList" :props="cascaderProps" clearable collapse-tags />
</el-form-item>
<el-form-item
label-width="110px"
label="软件版本:"
:prop="`${props.vaildRules}.editions`"
:rules="{ required: true, message: '请选择软件版本', trigger: ['blur', 'change'] }"
>
<el-select v-model="form.editions" placeholder="请选择软件版本" class="w-361px!">
<el-option v-for="(item, index) in editionsList" :key="index" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item
label-width="110px"
label="作品来源:"
:prop="`${props.vaildRules}.source`"
:rules="{ required: true, message: '请选择作品来源', trigger: ['blur', 'change'] }"
>
<el-radio-group v-model="form.source">
<el-radio :label="1">原创图纸</el-radio>
<el-radio :label="2">转载分享</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label-width="110px"
label="标签:"
:prop="`${props.vaildRules}.labels`"
:rules="{ required: true, message: '请选择标签', trigger: ['blur', 'change'] }"
>
<el-select
v-model="form.labels"
:remote-method="remoteMethod"
:loading="loading"
multiple
filterable
remote
placeholder="请输入搜索标签"
class="w-361px!"
>
<el-option v-for="(item, index) in labelsList" :key="index" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item
label-width="110px"
label="金币:"
:prop="`${props.vaildRules}.points`"
:rules="{ required: true, message: '请输入金币', trigger: ['blur', 'change'] }"
>
<el-input-number v-model="form.points" :controls="false" :precision="0" :min="0" placeholder="请输入金币" class="w-361px! text-left!"></el-input-number>
</el-form-item>
<el-form-item
label-width="110px"
label="图形格式:"
:prop="`${props.vaildRules}.formatType`"
:rules="{ required: true, message: '请选择图形格式', trigger: ['blur', 'change'] }"
>
<el-checkbox-group v-model="form.formatType">
<el-checkbox v-for="(item, index) in formatTypeList" :key="index" :label="item" :value="item"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item
label-width="110px"
label="上传封面:"
:prop="`${props.vaildRules}.coverImages`"
:rules="{ required: true, message: '请上传上传封面', trigger: ['blur', 'change'] }"
>
<KlUploader
v-model:file-list="form.coverImages"
list-type="picture-card"
:limit="1000"
:size="1"
tips="上传图片支持jpg/gif/png格式、第一张为封面图片、每张图片大小不得超过1M"
@validate="formRef?.validateField(`${props.vaildRules}.coverImages`)"
>
<div class="h-77px w-161px flex items-center justify-center border border-[#cdd0d6] rounded-1px border-dashed bg-[#fafafa]">
<el-icon class="text-[#999999]"><Plus /></el-icon>
<div class="ml-4px mt-2px text-14px text-[#999999] font-normal">上传图纸</div>
</div>
</KlUploader>
</el-form-item>
<el-form-item
v-if="form?.type === 3"
label-width="110px"
label="效果图:"
:prop="`${props.vaildRules}.renderings`"
:rules="{ required: true, message: '请上传效果图', trigger: ['blur', 'change'] }"
>
<KlUploader
v-model:file-list="form.renderings"
list-type="picture-card"
:limit="1000"
:show-tip="false"
@validate="formRef?.validateField(`${props.vaildRules}.renderings`)"
>
<div class="h-77px w-161px flex items-center justify-center border border-[#cdd0d6] rounded-1px border-dashed bg-[#fafafa]">
<el-icon class="text-[#999999]"><Plus /></el-icon>
<div class="ml-4px mt-2px text-14px text-[#999999] font-normal">上传图纸</div>
</div>
</KlUploader>
</el-form-item>
<el-form-item label-width="110px" label="上传附件:">
<KlUploader v-model:file-list="form.otherFiles" tips="请将系列文件分别压缩后上传,支持批量上传"> </KlUploader>
</el-form-item>
<el-form-item
label-width="110px"
label="描述:"
:prop="`${props.vaildRules}.description`"
:rules="[
{ required: true, message: '请输入描述', trigger: ['blur', 'change'] },
{
validator: (rule, value, callback) => {
console.log(rule)
if (value.length < 70) {
callback(new Error('输入内容不能少于 70 字'))
} else {
callback()
}
},
trigger: ['blur', 'change'],
},
]"
>
<el-input v-model="form.description" type="textarea" :rows="6" placeholder="请输入描述" class="w-361px!" minlength="70" show-word-limit></el-input>
</el-form-item>
</div>
</template>
<script setup lang="ts">
import { ref, PropType, computed } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import KlUploader from '@/components/kl-uploader/index.vue'
import { parent, keywords, labels, indexTabs } from '@/api/upnew/index'
import { TcreateReq } from '@/api/upnew/types'
const props = defineProps({
vaildRules: {
type: String as PropType<string>,
required: true,
},
formRef: {
type: Object as PropType<any>,
required: true,
},
})
const cascaderProps = { multiple: true, label: 'name', value: 'id', emitPath: false }
const emit = defineEmits(['preview'])
const form = defineModel<TcreateReq['draws'][0]>('modelValue', {
required: true,
})
const computFileType = computed(() => {
return form.value.type === 1 ? ['dwg'] : form.value.type === 2 ? ['pdf', 'xlsx', 'docx', 'xls'] : ['max', 'skp']
})
const loading = ref(false)
/** 获取标签 */
const labelsList = ref<any>([])
const remoteMethod = (query: string) => {
if (query) {
loading.value = true
keywords({
type: 1,
keywords: query,
})
.then((res) => {
labelsList.value = res.data
})
.finally(() => {
loading.value = false
})
} else {
labelsList.value = []
}
}
const formatTypeList = ref<any>([])
const getFormatTypeList = () => {
labels({
type: 2,
}).then((res) => {
// @ts-ignore
formatTypeList.value = res.data
})
}
getFormatTypeList()
const projectTypeList = ref<any>([])
/** 获取分类下拉框 */
const getParent = () => {
indexTabs().then((res) => {
projectTypeList.value = res.data
})
}
getParent()
/** 版本 */
const editionsList = ref<any>([])
const getEditionsList = () => {
parent({
type: 2,
parentId: 0,
}).then((res) => {
editionsList.value = res.data
})
}
getEditionsList()
const handlePreview = (val: any) => {
emit('preview', val)
}
</script>
<style lang="scss" scoped>
::v-deep(.el-form-item__label) {
// font-size: 16px;
}
</style>

View File

@ -0,0 +1,148 @@
<template>
<div class="box-border border border-[#EEEEEE] rounded-12px border-solid bg-[#FFFFFF] px-33px py-22px pb-10px!">
<el-form-item
label="选择上传资料类型:"
label-width="170px"
label-position="left"
prop="type"
:rules="[{ required: true, message: '请选择上传资料类型', trigger: 'change' }]"
>
<el-checkbox-group v-model="form.type" @change="handleTypeChange">
<el-checkbox :value="1">图纸</el-checkbox>
<el-checkbox :value="3">模型</el-checkbox>
<el-checkbox :value="2">文本</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item
label="选择国家:"
label-width="110px"
label-position="left"
prop="isDomestic"
:rules="[{ required: true, message: '请选择国家', trigger: 'change' }]"
>
<el-select v-model="form.isDomestic" placeholder="请选择" class="w-200px!" @change="handleCountryChange">
<el-option label="国内" :value="1"></el-option>
<el-option label="国外" :value="0"></el-option>
</el-select>
</el-form-item>
<div class="flex">
<el-form-item
label="所在地区:"
label-width="110px"
label-position="left"
prop="province"
:rules="[{ required: true, message: '请选择所在地区', trigger: 'change' }]"
>
<el-select v-model="form.province" placeholder="请选择" class="w-200px!" @change="handleProvinceChange">
<el-option v-for="(item, index) in provinceList" :key="index" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label-width="10px" label-position="left" prop="city" :rules="[{ required: true, message: '请选择地址', trigger: 'change' }]">
<el-select v-model="form.city" placeholder="请选择" class="w-200px!" @change="handleCityChange">
<el-option v-for="(item, index) in cityList" :key="index" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label-width="10px" label-position="left" prop="county" :rules="[{ required: true, message: '请选择地区', trigger: 'change' }]">
<el-select v-model="form.county" placeholder="请选择" class="w-200px!">
<el-option v-for="(item, index) in countyList" :key="index" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</div>
</div>
</template>
<script setup lang="ts">
import { nextTick, ref } from 'vue'
import { TcreateReq } from '@/api/upnew/types'
import { tree } from '@/api/common/index'
import { DrawsEnmu } from '../util.ts'
const form = defineModel<TcreateReq>('modelValue', {
required: true,
})
// 添加旧值引用
const oldTypeValue = ref<(number | string)[]>([])
const handleTypeChange = (val: any) => {
console.log(val, 'val')
// 新增的项(当前值有但旧值没有的)
const added = val.filter((item: number | string) => !oldTypeValue.value.includes(item))
// 减少的项(旧值有但当前值没有的)
const removed = oldTypeValue.value.filter((item) => !val.includes(item))
if (added.length) {
form.value.draws.push({
...JSON.parse(JSON.stringify(DrawsEnmu)),
type: added[0],
})
} else if (removed.length) {
form.value.draws = form.value.draws.filter((item) => item.type !== removed[0])
}
// 更新旧值
oldTypeValue.value = [...val]
// 更新当前activeName值
if (!val?.length) {
form.value.activeName = ''
}
nextTick(() => {
form.value.activeName = val[val.length - 1]
})
}
// 切换国家
const handleCountryChange = (val: any) => {
form.value.province = ''
form.value.city = ''
form.value.county = ''
provinceList.value = []
cityList.value = []
countyList.value = []
getAdress('province', val)
}
// 选择省份 获取市区
const handleProvinceChange = (val: any) => {
form.value.city = ''
form.value.county = ''
cityList.value = []
countyList.value = []
getAdress('city', val)
}
// 选择市份 获取区
const handleCityChange = (val: any) => {
form.value.county = ''
countyList.value = []
getAdress('county', val)
}
// 获取地址
const provinceList = ref()
const cityList = ref()
const countyList = ref()
const getAdress = async (type: string, val?: any) => {
const res = await tree({
id: val,
})
if (res.code === 0) {
if (type === 'province') {
provinceList.value = res.data
} else if (type === 'city') {
cityList.value = res.data
} else if (type === 'county') {
countyList.value = res.data
}
}
}
defineExpose({
handleTypeChange,
})
</script>
<style scoped lang="scss">
::v-deep(.el-form-item__label) {
// font-size: 16px;
}
</style>

View File

@ -0,0 +1,33 @@
<template>
<div class="ml-23px box-border min-h-930px w-516px border border-[#EEEEEE] rounded-12px border-solid bg-[#FFFFFF] px-33px py-22px">
<div class="flex items-center">
<img src="@/assets/images/preview.png" alt="" srcset="" width="16px" height="19px" /><span class="ml-7px text-18px text-[#333333] font-normal"
>预览</span
></div
>
<div class="mt-20px">
<el-image :src="previewUrl" class="mb-16px max-h-320px max-w-460px min-h-200px" fit="contain"></el-image>
<span class="text-16px text-[#333333] font-normal">{{ previewName || '图纸标题' }}</span></div
>
<div class="my-30px h-1px w-460px rounded-1px bg-[#EEEEEE]"></div>
<div class="flex items-center"
><img src="@/assets/images/tip.png" width="20px" height="20px" /><span class="ml-7px text-18px text-[#333333] font-normal"
>上传遇到问题可以咨询</span
></div
>
<div class="mt-20px text-center"><el-image src="https://picsum.photos/290/290?_t" alt="" srcset="" class="h-290px w290" /></div>
<div class="mt-30px text-center text-16px text-[#333333] font-normal">
<div>TEL13315189735 </div>
<div class="mt-4px">在线时间8:30-18:00</div>
</div>
</div>
</template>
<script setup lang="ts">
const previewUrl = defineModel<string>('previewUrl', {
required: true,
})
const previewName = defineModel<string>('previewName', {
required: true,
})
</script>

145
pages/upnew/index.vue Normal file
View File

@ -0,0 +1,145 @@
<template>
<!-- 导航 -->
<KlNavTab />
<!-- 发布图纸 -->
<div class="ma-auto mt-30px w-1440px flex">
<div class="w-900px">
<el-form ref="formRef" :model="form" label-width="120px">
<!-- 图纸分类 -->
<DrawType ref="drawTypeRef" v-model="form" />
<div class="mt-24px box-border border border-[#EEEEEE] rounded-12px border-solid bg-[#FFFFFF] px-33px py-22px">
<el-tabs v-model="form.activeName" class="demo-tabs">
<el-tab-pane v-for="(item, index) in form.draws" :key="item.type" :label="computLabel(item.type)" :name="item.type">
<DrawForm v-if="form.draws[index]" v-model="form.draws[index]" :vaild-rules="'draws.' + index" :form-ref="formRef" @preview="handlePreview" />
</el-tab-pane>
</el-tabs>
<el-form-item label-width="110px" class="mt-20px">
<!-- <el-button class="w-121px h-37px!" :loading="loading" @click="handleSubmit">预览</el-button> -->
<el-button type="primary" class="w-121px h-37px!" :loading="loading" @click="handleSubmit">发布</el-button>
</el-form-item>
</div>
</el-form>
</div>
<!-- 预览图 -->
<PreView v-model:preview-url="previewUrl" v-model:preview-name="previewName"></PreView>
</div>
</template>
<script setup lang="ts">
import PreView from './components/Preview.vue'
import DrawType from './components/DrawType.vue'
import DrawForm from './components/DrawForm.vue'
import KlNavTab from '@/components/kl-nav-tab/index.vue'
import { reactive, ref, onMounted, computed } from 'vue'
import { TcreateReq } from '@/api/upnew/types'
import { create } from '@/api/upnew/index'
const form = reactive<TcreateReq>({
activeName: '', // 标签
id: '', // 图纸id id,示例值(24548)
type: [], // 图纸类型 类型,示例值(1)
isDomestic: '', // 是否是国内: 1是 0否
province: '', // 省份编码
city: '', // 城市编码
county: '', // 区县编码
draws: [], // 图纸信息
})
// const previewForm = reactive({
// url: '',
// name: '',
// })
const computLabel = (type: number) => {
switch (type) {
case 1:
return '图纸'
case 2:
return '文本'
case 3:
return '模型'
}
}
const previewUrl = computed(() => {
if (form.draws.length && form.activeName) {
const info = form.draws.find((c) => c.type === Number(form.activeName))
if (info && info.coverImages.length) return info.coverImages[0].url
}
return ''
})
const previewName = computed(() => {
if (form.draws.length && form.activeName) {
const info = form.draws.find((c) => c.type === Number(form.activeName))
if (info && info.coverImages.length) return info.coverImages[0].name
}
return ''
})
/**
* 提交
*/
const loading = ref(false)
const formRef = ref()
const handleSubmit = () => {
console.log(form)
formRef.value.validate((valid: boolean, val: any) => {
console.log('00000----', val)
if (valid) {
loading.value = true
create(form)
.then((res) => {
console.log(res)
const { code } = res
if (code === 0) {
// 弹窗提示
ElMessage.success('操作成功')
// 关闭弹窗
setTimeout(() => {
window.close()
}, 100)
}
})
.finally(() => {
loading.value = false
})
} else {
console.log('error submit!')
// 弹窗提示
ElMessage.error('请填写以上信息')
return false
}
})
}
/** 暂时不用了 直接展示封面图 */
const handlePreview = (val: any) => {
console.log(val)
// previewForm.url = val.url
// previewForm.name = val.name
}
// 图纸类型
const drawTypeRef = ref()
onMounted(() => {
// 初始化图纸类型
drawTypeRef.value.handleTypeChange([1])
// 初始化图纸类型
form.type = [1]
})
</script>
<style lang="scss" scoped>
.demo-tabs > .el-tabs__content {
padding: 32px;
color: #6b778c;
font-size: 32px;
font-weight: 600;
}
::v-deep(.el-tabs__item) {
font-size: 16px;
}
</style>

25
pages/upnew/util.ts Normal file
View File

@ -0,0 +1,25 @@
export const DrawsEnmu = {
id: '', // 图纸id id,示例值(24548)
projectId: '', // 所属,示例值(25728)
title: '', // 标题
description: '', // 描述
ownedUserId: '', // 所属人
editions: '', // 软件版本信息,最多上传5个
labels: [], // 标签内容最多5个
type: undefined, // 图纸类型 类型,示例值(1)
source: '', // 来源
editType: '', // 编辑类型
status: [], // 状态值,示例值(2)
createAddress: '', // 创建地址编码信息
createIp: '', // 创建地址ipv4信息
files: [], // 文件信息
province: '', // 省份编码
city: '', // 城市编码
county: '', // 区县编码
points: undefined, // 金币
projectType: [], // 分类
formatType: [], // 格式
coverImages: [], // 封面图片
otherFiles: [], // 附件信息
renderings: [], // 渲染信息
}