props的几种写法——defineProps定义props、toRefs接收props、computed中get和set写法、watch深度监听immediate-true
1
<Reply :review="review" :objectType="objectType"></Reply>
<script>
//写法一
export default {
props: ['review','objectType'],
components: {
Reply
},
data() {
return{
replys:''
}
},
methods: {
replyActive() {
this.replys = this.objectType
}
}
}
//写法二
export default {
props: {
id: {
type: String
},
objectType: {
type: String
},
width: {
type: Number,
default: 1200
}
},
data() {
return{
replys:''
}
},
methods: {
replyActive() {
this.replys = this.objectType
}
}
}
</script>
2
<script lang="ts" setup>
import { ref, defineProps, defineEmits, computed, inject, onMounted } from 'vue';
const props = defineProps({
infoData: {
default: null,
type: Object,
},
dialogVisible: {
type: Boolean,
default() {
return false
},
},
})
const radio = ref(props.infoData.authorId)
//监听方法
const emit = defineEmits(['userOk', 'update:dialogVisible'])
const dialogVisible = computed({
get: () => props.dialogVisible,
set: (val) => emit('update:dialogVisible', val),
})
onMounted(() => {
userList('1')
})
const userList = (type: any) => {}
// 重置
const formRef = ref()
const resetForm = () => {
formRef.value.resetFields()
userList('1')
}
props和深度监听
const props = defineProps(['project','awardList','iconList','defaultShowImg'])
//表单绑定校验数据
const projectInfoData=ref({})
watch(()=>props.project,(val)=>{projectInfoData.value = val; projectInfoData.value.techArr = val.techCodeIdList; checked.value = true},{deep:true})
watch(()=>props.iconList,(val)=>projectInfoData.value.imageList = val,{deep:true})
watch(()=>props.awardList,(val)=>userWinner.value = val,{deep:true,})
watch(()=>props.defaultShowImg,(val)=>defaultImgId.value = val,{deep:true,})
2
export default {
props:['project','awardVoList','iconVoList','defaultShowImg'],
data() {
return {
userWinner: [],
defaultImgId: '',//照片墙选中默认图片的 id
//表单绑定校验数据
projectInfoData: {
projName: '', //表单项目名称 //projName
videoVoList: [], //表单上传视频 //videoVoList
imageList: [], //表单上传图标 //iconVoList
issueScope: 1, //发布范围单选框数据 //issueScope
//项目简介
techQuestion: '',//解决的技术问题 //techQuestion
techScheme: '', //技术方案 //techScheme
techResult: '', //技术效果或者优势 //techResult
otherInfo: '', //其他信息 //otherInfo
tech:'', //技术领域下拉框数据-字符串 最后一项
techCode1:[], //技术领域下拉框数据-数组
fileVoList: [], //上传附件的数据信息 // fileVoList
},
platformTransactionRules: null ,//复选框
}
}
watch: {
'projectInfoData.imageList':{
handler(val){
this.$refs.projectInfoDataForm.validateField(['imageList'],()=>{})
},
deep:true,
},
project:{
handler(val){
this.projectInfoData = val
this.projectInfoData.techCode1 = val.techCode1
this.platformTransactionRules = val.platformTransactionRules
},
deep:true,
// immediate:true
},
iconVoList:{
handler(val){
this.projectInfoData.imageList = val
},
deep:true,
},
awardVoList:{
handler(val){
this.userWinner = val
},
deep:true,
},
defaultShowImg:{
handler(val){
this.defaultImgId = val
},
deep:true,
},
},
}
3
<swiper :modules="modules" :slides-per-view="4" :space-between="50" :slideChange-per-group="1" :navigation="true" class="mySwiper" @swiper="onSwiper" @slideChange="onSlideChange">
<swiper-slide v-for="(item,index) in props.imgList" :key="item.id">
<img :src="baseUrl + constant.fileUpload + '/previewImage?id=' + item.fileId" alt="" :class="{ active: index == currentIndex }"
@click="changeIndex(item,index)" class="pointer">
</swiper-slide>
</swiper>
<script setup>
const props = defineProps(['imgList'])
const baseUrl = process.env.VUE_APP_API_HOST
const bigImgId = ref("")
watch(()=>{return props.imgList},()=>{bigImgId.value = props.imgList.filter(item=>{return item.isMaster == 1})[0].fileId},{deep:true})
</script>
4
<!--
@Description 一级菜单 - 题目 - 新增/编辑功能弹框
@author author
@date 2024/1/1
-->
<template>
<div>
<el-dialog :title="titleText" v-model="dialogVisible" :close-on-press-escape="false"
:close-on-click-modal="false" width="36%">
<div style="padding-right:40px">
<el-form label-width="100px" ref="formRef" :model="formInline">
<el-form-item label="名称:" prop="name" :rules="{ required: true, validator: elValidateText, title: '名称', length: 100, isRequire: true }">
<el-input v-model="formInline.name"></el-input>
</el-form-item>
<el-form-item label="类型">
<el-select v-model="formInline.type" placeholder="请选择" disabled style="width:100%">
<el-option label="一级目录" value="0"></el-option>
<el-option label="二级目录" value="1"></el-option>
<el-option label="三级目录" value="2"></el-option>
<el-option label="四级目录 " value="3"></el-option>
<el-option label="五级目录 " value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item label="标题号:" prop="sort" :rules="{
required: true,
message: '请输入',
trigger: 'blur',
}">
<el-input placeholder="请输入大于0的正整数" @input="changeSort" v-model="formInline.sort"></el-input>
</el-form-item>
<el-form-item label="目录说明:" prop="dirExplain" :rules="{ required: true, validator: elValidateText, title: '目录说明', length: 100, isRequire: true }">
<el-input type="textarea" resize="none" show-word-limit maxlength="300" v-model="formInline.dirExplain" :autosize="{minRows:3}">
</el-input>
</el-form-item>
</el-form>
</div>
<template #footer>
<span slot="footer" class="dialog-footer">
<el-button link type="primary" @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm()">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ref, defineProps, defineEmits, computed, watch, inject } from 'vue';
import { post } from "@/utils/path.js";
import { ElLoading, ElMessage } from "element-plus";
import { elValidateText} from '@/utils/validate.js'
const formRef = ref()
const dataObj = ref()
const titleText = ref('')
const directoryList = ref(['一级目录', '二级目录', '三级目录', '四级目录', '五级目录'])
const constant = inject('constant')
const formInline = ref({
collaborateId: '',
name: '',
sort: '',
sortNo: '',
dirExplain: '',
type: '0'
})
const props = defineProps({
infoData: {
default: null,
type: Object,
},
dialogVisible: {
type: Boolean,
default() {
return false
},
},
})
//监听方法
const emit = defineEmits(['emit-confirm', 'update:dialogVisible'])
const dialogVisible = computed({
get: () => props.dialogVisible,
set: (val) => emit('update:dialogVisible', val),
})
watch(
() => props.dialogVisible,
(newVal) => {
if (newVal) {
dataObj.value = JSON.parse(JSON.stringify(props.infoData))
if (dataObj.value.typeName == 'add') {
formInline.value.collaborateId = dataObj.value.id
titleText.value = '新增一级目录'
}
if (dataObj.value.typeName == 'addChild') {
formInline.value.collaborateId = dataObj.value.directoryId
formInline.value.pid = dataObj.value.id
formInline.value.type = (Number(dataObj.value.type) + 1) + ''
titleText.value = '新增' + directoryList.value[formInline.value.type]
}
if (dataObj.value.typeName == 'edit') {
formInline.value = { ...dataObj.value }
formInline.value.collaborateId = dataObj.value.directoryId
formInline.value.id = dataObj.value.id
titleText.value = '编辑' + directoryList.value[dataObj.value.type]
}
}
},
{ immediate: true }
)
const changeSort = (val: any) => {
const pattern = /^[1-9][0-9]*$/
if (!pattern.test(val)) {
formInline.value.sort = ''
}
if (titleText.value == '新增一级目录') {
formInline.value.sortNo = formInline.value.sort + '.'
}
if (dataObj.value.typeName == 'edit') {
const str = formInline.value.sortNo.split('.')
str.splice(-2,1)
formInline.value.sortNo = str.join('.') + formInline.value.sort + '.'
}
if (dataObj.value.typeName == 'addChild') {
formInline.value.sortNo = dataObj.value.sortNo + formInline.value.sort + '.'
}
}
const confirm = async () => {
await formRef.value.validate((valid: any) => {
if (!valid) {
return
} else {
const loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
const params = {
...formInline.value
}
const url = dataObj.value.typeName == 'addChild' ? '/collaborate/directory/add' : '/collaborate/directory/addRoot'
const urlInfo = dataObj.value.typeName == 'edit' ? '/collaborate/directory/update' : url
post(constant.ieopCollaborate + urlInfo, params).then((res) => {
const { code } = res.data
if (code == '200') {
loading.close()
ElMessage.success(dataObj.value.typeName == 'edit' ? '修改成功' : '新增成功')
emit('update:dialogVisible', false)
formInline.value = {}
emit('emit-confirm')
} else {
loading.close()
ElMessage.error(res.message)
emit('update:dialogVisible', false)
}
})
.catch(() => {
loading.close()
})
}
})
}
</script>
5
<!--
@Description 新增
@author author
@date 2024/1/22
-->
<template>
<div>
<el-dialog :title="textMark+'专报'" v-model="dialogVisible" :close-on-press-escape="false"
:close-on-click-modal="false" width="40%">
<div>
<el-form label-width="110px" ref="formRef" :model="formInline">
<el-form-item label="专报名称:" prop="docName" :rules="{ required: true, validator: elValidateText, title: '文档名称', length: 100, isRequire: true }">
<el-input type="text" maxlength="300" v-model="formInline.docName"></el-input>
</el-form-item>
<el-form-item label="专报说明:" :rules="{ required: true, validator: elValidateText, title: '文档说明', length: 300, isRequire: true }">
<el-input type="textarea" resize="none" rows="3" maxlength="300" show-word-limit
v-model="formInline.docExplain">
</el-input>
</el-form-item>
</el-form>
</div>
<template #footer>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ref, toRefs, defineProps, defineEmits, computed, watch, inject } from 'vue';
import { post } from "@/utils/path.js";
import { elValidateText} from '@/utils/validate.js'
import { ElMessage, ElLoading } from 'element-plus'
const constant = inject('constant')
const formRef = ref()
const props = defineProps({
textMark: {
default: '新增',
type: String,
},
infoData: {
default: null,
type: Object,
},
dialogVisible: {
type: Boolean,
default() {
return false
},
},
})
const { textMark, infoData } = toRefs(props)
const formInline = ref({})
if (textMark.value == '编辑') {
formInline.value = infoData
}
//监听方法
const emit = defineEmits(['emit-confirm', 'update:dialogVisible'])
const dialogVisible = computed({
get: () => props.dialogVisible,
set: (val) => emit('update:dialogVisible', val),
})
watch(
() => props.dialogVisible,
(newVal) => {
if (newVal) {
console.log(props.infoData);
formInline.value = props.infoData
}
},
{immediate:true}
)
const confirm = async () => {
await formRef.value.validate((valid) => {
if (!valid) return
const loading = ElLoading.service({
lock: true,
text: '加载中......',
background: 'rgba(0, 0, 0, 0.7)',
})
post(constant.ieopCollaborate + '/collaborate/info/add', formInline.value)
.then((res) => {
const { code } = res.data
if (code == '200') {
ElMessage({
type: 'success',
message: '新增成功',
})
emit('emit-confirm', formInline.value)
emit('update:dialogVisible', false)
formRef.value.resetFields()
}
})
.finally(() => {
loading.close()
})
})
}
</script>
6
<!--
@Description 申请表管理 - 定义申请表 - 表单类型
@author wdd
@date 2023/12/18
-->
<template>
<div class="content">
<template v-for="item in formItem" :key="item.prop">
<template v-if="!item.show">
<el-form-item
:key="item.prop"
:class="item.className"
:label="item.label"
:label-width="item.labelWidth"
:prop="item.prop"
:rules="item.rules"
>
<template v-if="!item.slot">
<!-- input 输入框类型 -->
<el-input
v-if="item.type === 'input'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
:maxlength="item.maxLength"
:placeholder="item.placeholder"
:show-word-limit="item.limit"
/>
<!-- number 数字类型 -->
<el-input-number
v-if="item.type === 'number'"
v-model="dataSource[`${item.prop}`]"
:controls="false"
:disabled="item.disabled || isEditDisabled"
:max="item.max || 99999999"
:min="item.min || 0"
style="width:100%"
:placeholder="item.placeholder"
:precision="item.precision"
@keydown="
(val) => (val.key === 'e' ? (val.returnValue = false) : true)
"
/>
<!-- textarea 多行文本类型 -->
<el-input
v-if="item.type === 'textarea'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
:maxlength="item.maxLength || 1000"
:placeholder="item.placeholder"
:rows="item.rows || 2"
show-word-limit
type="textarea"
/>
<!-- date 日期类型 -->
<el-date-picker
v-if="item.type === 'date'"
v-model="dataSource[`${item.prop}`]"
:clearable="false"
:disabled="item.disabled || isEditDisabled"
format="YYYY-MM-DD"
:placeholder="item.placeholder"
type="date"
style="width:100%"
value-format="YYYY-MM-DD"
/>
<!-- month 年月类型 -->
<el-date-picker
v-if="item.type === 'month'"
v-model="dataSource[`${item.prop}`]"
:clearable="false"
:disabled="item.disabled || isEditDisabled"
format="YYYY-MM"
style="width:100%"
:placeholder="item.placeholder"
type="month"
value-format="YYYY-MM"
/>
<!-- year 年度类型 -->
<el-date-picker
v-if="item.type === 'year'"
v-model="dataSource[`${item.prop}`]"
:clearable="false"
:disabled="item.disabled || isEditDisabled"
format="YYYY"
style="width:100%"
:placeholder="item.placeholder"
type="year"
value-format="YYYY"
/>
<!-- dateTimeRange 起止日期类型 -->
<el-date-picker
v-if="item.type === 'dateTimeRange'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
end-placeholder="结束时间"
format="YYYY-MM-DD"
:placeholder="item.placeholder"
range-separator="-"
style="width:100%"
start-placeholder="开始时间"
type="datetimerange"
value-format="YYYY-MM-DD"
/>
<!-- select 下拉框类型 -->
<el-select
v-if="item.type === 'select'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
:placeholder="item.placeholder"
style="width:100%"
>
<template v-if="item.selectOptions">
<el-option
v-for="obj in item.selectOptions"
:key="obj.value"
:label="obj.label"
:value="obj.value"
/>
</template>
</el-select>
<!-- radio 单选类型 -->
<el-radio-group
v-if="item.type === 'radio'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
@change="handleRadio"
style="width:100%"
>
<el-radio
v-for="obj in item.radioOptions"
:key="obj.value"
:label="obj.value"
>
{{ obj.label }}
</el-radio>
</el-radio-group>
<!-- radio 单选类型 -->
<el-checkbox-group
v-if="item.type === 'checkbox'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
@change="handleCheckbox"
style="width:100%"
>
<el-checkbox
v-for="obj in item.CheckboxOptions"
:key="obj.value"
:label="obj.value"
>
{{ obj.label }}
</el-checkbox>
</el-checkbox-group>
<!-- cascader 级联类型 -->
<el-cascader
v-if="item.type === 'cascader'"
v-model="dataSource[`${item.prop}`]"
:disabled="item.disabled || isEditDisabled"
:options="item.enumValue"
:props="{value:'code',label:'name',children:'children'}"
@change="handleCasder"
style="width:100%"
>
</el-cascader>
<!-- editor 富文本类型 -->
<wangEditor style="width:100%" v-if="item.type === 'editor'" :initValue="dataSource[`${item.prop}`]" :disabled="showWang"
></wangEditor>
<!-- file 附件类型 -->
<template v-if="item.type == 'file'">
<fileUpload v-model="dataSource[`${item.prop}`]" :objectId="item.dataArrId"
valid="doc、docx、png、jpg、jpeg、ppt、wps、pdf、ceb、xls、xlsx、txt、bmp" :max="20480" serviceType="intellectual"
:objectType = "constant.objectType.typeSBB"
:length="10" :fileType="1" @getDelAttachment="delFile"></fileUpload>
<div class="prompt">
<p>1.上传需求相关材料;</p>
<p>2.可上传多个附件,支持doc、docx、png、jpg、jpeg、ppt、wps、pdf、ceb、xls、xlsx、txt、bmp等格式;</p>
<p>3.文件大小不超过20M;</p>
</div>
</template>
</template>
<template v-else>
<slot :name="item.prop" :val="dataSource[`${item.prop}`]" />
</template>
</el-form-item>
</template>
<template v-else>
<slot :item="item" :name="item.prop" />
</template>
</template>
</div>
</template>
<script>
import { defineComponent, toRefs, reactive,inject } from 'vue'
import { useRoute } from 'vue-router'
export default defineComponent({
name: 'CustomForm',
props: {
isShow: {
require: false,
type: Boolean,
default: true,
},
curPage: {
require: false,
type: String,
default: '',
},
formData: {
require: true,
type: Object,
default: () => { },
},
formItem: {
require: true,
type: Object,
default: () => { },
},
},
emits: ['changeRadio', 'changeCheckbox','changeCasder', 'getDelAttachment'],
setup(props, { emit }) {
const route = useRoute()
const constant= inject('constant')
const query = route.query
const { formItem, formData, curPage } = toRefs(props)
const state = reactive({
curBtn: curPage,
formItem: formItem,
showWang: false,
dataSource: formData,
isEditDisabled: query.type === 'view' ? true : false,
})
const handleRadio = (val) => {
emit('changeRadio', val)
}
const handleCheckbox = (val) => {
emit('changeCheckbox', val)
}
const handleCasder = (val) => {
emit('changeCasder', val)
}
const delFile = (val) => {
emit('getDelAttachment', val);
}
return {
query,
constant,
...toRefs(state),
handleRadio,
handleCheckbox,
handleCasder,
delFile
}
},
})
</script>
<style lang="scss" scoped>
.content {
overflow: auto;
}
.prompt {
position: absolute;
top: 10px;
left: 130px;
color: gray;
p {
line-height: 25px;
}
}
</style>