a-table单元格指定合并以及表格双击编辑以及未填写指定验证功能

news2024/11/16 7:19:42

文章目录

  • a-table单元格指定合并以及表格双击编辑以及未填写指定验证功能
    • 一、 a-table单元格指定合并
      • 1. a-table
      • 2. columns
      • 3. 图例
    • 二、a-table 表格双击编辑以及未填写验证
      • 1. a-table
      • 2. js
      • 3. 图例

a-table单元格指定合并以及表格双击编辑以及未填写指定验证功能

一、 a-table单元格指定合并

1. a-table

				<a-table
					ref="table"
					:pagination="{
						position: ['none']
					}"
					:columns="columns"
					:dataSource="tableData"
					:alert="false"
					:row-key="(record) => record.id"
					bordered
				>
				</a-table>

2. columns

columns.value = [
			{
				title: '序号',
				dataIndex: 'index',
				align: 'center',
				width: '300px',
				customRender: function ({ text, record, index }) {
					if (record.objectName === '单元测评结果(符合/部分符合/不符合/不适用)') {
						return record.objectName
					} else {
						return index + 1
					}
				},
				customCell: (data, index) => {
					if (data.objectName === '单元测评结果(符合/部分符合/不符合/不适用)') {
						return {
							colSpan: 2
						}
					} else {
						return { colSpan: 1 }
					}
				}
			},
			{
				title: '测评对象',
				dataIndex: 'objectName',
				align: 'center',
				width: '300px',
				customCell: (data, index) => {
					if (data.objectName === '单元测评结果(符合/部分符合/不符合/不适用)') {
						return {
							colSpan: 0
						}
					} else {
						return { colSpan: 1 }
					}
				}
			},
			{
				title: '测评指标符合情况(符合/部分符合/不符合/不适用)',
				dataIndex: 'content1',
				align: 'center',
				width: '300px',
				children: [
					{
						title: '身份鉴别',
						dataIndex: '9',
						align: 'center',
						width: '300px'
					},
					{
						title: '远程管理通道安全',
						dataIndex: '10',
						align: 'center',
						width: '300px'
					},
					{
						title: '系统资源访问控制信息完整性',
						dataIndex: '11',
						align: 'center',
						width: '300px'
					},
					{
						title: '重要信息资源安全标记完整性',
						dataIndex: '12',
						align: 'center',
						width: '300px'
					},
					{
						title: '日志记录完整性',
						dataIndex: '13',
						align: 'center',
						width: '300px'
					},
					{
						title: '重要可执行程序完整性、重要可执行程序来源真实性',
						dataIndex: '14',
						align: 'center',
						width: '300px'
					}
				]
			}
		]

3. 图例

在这里插入图片描述

二、a-table 表格双击编辑以及未填写验证

1. a-table

		<a-table
			style="width: 100%"
			bordered
			:dataSource="tableData"
			ref="selection"
			:pagination="false"
			:columns="columns"
			:customRow="Rowclick"
			:row-key="(record) => record.evaluationEnvironmentId"
			:class="{ 'no-hover': disableHover }"
		>
			<template #bodyCell="{ column, index, record }">
				<template v-if="column.key === 'handle'">
					<a-space>
						<a-button type="primary" danger @click="onDelete(record, index)" :disabled="isReview"> 删除 </a-button>
						<a-button
							type="primary"
							@click="getModifications(record, index)"
							:disabled="isReview"
							v-if="record.checkState == '0' || !record.checkState"
							style="background: rgb(183 175 175); border: none"
						>
							后续修改
						</a-button>
						<a-button
							type="primary"
							@click="getModifications(record, index)"
							:disabled="isReview"
							v-if="record.checkState == '1'"
							style="background: #f88f5e; border: none"
						>
							后续修改
							<CloseCircleFilled />
						</a-button>
					</a-space>
				</template>
			</template>
		</a-table>

2. js

子组件内容

//双击编辑

const Rowclick = (columns, index, record) => {
		return {
			onClick: (event) => {
				if (!isReview) {
				//isReview为验证在什么条件下可以编辑/不可以编辑
					if (currentRowIndex.value != undefined) {
						if (currentRowIndex.value != index) {
							lastRowIndex.value = currentRowIndex.value
						}
					}
					currentRowIndex.value = index
					const cellElement = event.target.closest('td')
					if (cellElement) {
						currentColumnIndex.value = cellElement.cellIndex
					}
				}
			},
			onDblclick: (event) => {
				console.log(isReview,'isReview')
				if (!isReview) {
					if (lastRowIndex.value != undefined) {
						if (lastRowIndex.value != index) {
							if (cloneDataList.value[index]) {
								cloneDataList.value[index].editting = {}
							}
						}
					}
					const cellElement = event.target.closest('td')
					const dataIndex = props.columns[cellElement.cellIndex].key
					cloneDataList.value[index].editting = {}
					cloneDataList.value[index].editting[dataIndex] = true
					pasteStatus.value = false
				}
			}
		}
	}

//可以复制

const pasteInfo = (e) => {
		if (!isReview) {
			try {
				if (pasteStatus.value) {
					//获得粘贴的文字
					var data = null
					var clipboardData = e.clipboardData // IE
					if (!clipboardData) {
						//chrome
						clipboardData = e.originalEvent.clipboardData
					}
					data = clipboardData.getData('Text')
					var rowStrArray = data.split('\n')
					rowsInfo.value = []
					for (var i = 0; i < rowStrArray.length - 1; i++) {
						var row = []
						var tdStrArray = rowStrArray[i].split('\t')
						for (var j = 0; j < tdStrArray.length; j++) {
							row.push(tdStrArray[j].replace('\r', ''))
						}
						rowsInfo.value.push(row)
					}
					let tableLength = props.tableData.length
					for (var j = 0; j < rowsInfo.value.length; j++) {
						if (currentRowIndex.value + j >= tableLength) {
							addLine()
						}
						temp.value = JSON.parse(JSON.stringify(props.tableData[currentRowIndex.value + j]))
						let num = 0
						let numFlag = 0
						for (var key in props.emptyObj) {
							if (!rowsInfo.value[j][num]) {
								break
							}
							if (currentColumnIndex.value - 2 <= numFlag) {
								temp.value[key] = rowsInfo.value[j][num]
								if (temp.value.cellClassName && temp.value.cellClassName[key]) {
									delete temp.value.cellClassName[key]
								}
								num = num + 1
							}
							numFlag = numFlag + 1
						}
						// this.$set(tableData.value, currentRowIndex.value+j, temp.value)
						props.tableData[currentRowIndex.value + j] = temp.value
					}
					window.localStorage.setItem('editTableLength', props.tableData.length)
					cloneDataList.value = JSON.parse(JSON.stringify(props.tableData)).map((item) => {
						item.editting = false
						return item
					})
				}
			} catch (err) {
				message.error({
					content: '请选择复制位置'
				})
			}
		}
	}

//获取tableData

	const init = () => {
		cloneDataList.value = JSON.parse(JSON.stringify(props.tableData)).map((item, index) => {
			item.editting = false
			return item
		})
		props.columns.forEach((item, index) => {
			// if (item.editable) {
			// $set(item, 'renderHeader', (h, params) => {
			// return h('div', [h('span', {
			//   domProps: {
			//     innerHTML: item.title
			//   },
			// }),
			// ])
			// });
			// }
			//如果含有editable属性并且为true
			if (item.editable) {
				item.customRender = function ({ text, record, index, column }) {
					var currentRow = cloneDataList.value[index]
					if (!currentRow.editting[item.key]) {
						if (item.date) {
							return h('span', currentRow[item.key])
						}
						// 下拉类型中value与label不一致时单独渲染
						if (item.option) {
							// 我这里为了简单的判断了第一个元素为object的情况,其实最好用every来判断所有元素
							if (typeof item.option[0] === 'object') {
								if (item.multiple) {
									let arr1 = [],
										arr
									if (typeof currentRow[item.key] == 'string' && currentRow[item.key])
										arr = currentRow[item.key].split(',')
									else arr = currentRow[item.key]
									arr &&
										arr.length > 0 &&
										arr.forEach((optionItem) => {
											// arr1.push(item.option.find(findObjectInOption(optionItem)).label)
											arr1.push(
												item.option.find(findObjectInOption(optionItem))
													? item.option.find(findObjectInOption(optionItem)).label
													: optionItem
											)
										})
									return h('span', {}, arr1.join())
								} else {
									// let params = item.option.find(findObjectInOption(currentRow[item.key])) ? item.option.find(findObjectInOption(currentRow[item.key])).label : '请选择'
									let params = item.option.find(findObjectInOption(currentRow[item.key]))
										? item.option.find(findObjectInOption(currentRow[item.key])).label
										: currentRow[item.key]
									return h('span', {}, params)
								}
							}
						}
						return h('span', currentRow[item.key])
					} else {
						if (item.option) {
							//  && typeof currentRow[column.key] == 'string'
							if (item.multiple) {
								// let arr = currentRow[column.key].split(',')
								let arr = currentRow[column.key]
								if (arr == '请选择') {
									arr = undefined
								}
								return h(Select, {
									placeholder: '请选择',
									value: arr,
									options: item.option,
									mode: 'multiple',
									style: { width: '100%' },
									onChange: (value) => {
										// if(!value){
										//   currentRow[column.key] ='请选择'
										// }else{
										//   currentRow[column.key] = value
										// }
										currentRow[column.key] = value
										saveData(currentRow, index, column.key, value)
									},
									onClear: function () {}
								})
							} else {
								return h(Select, {
									placeholder: '请选择',
									value: currentRow[column.key],
									options: item.option,
									style: { width: '100%' },
									onChange: (value) => {
										if (value.length == 0) {
											currentRow[column.key] = '请选择'
										} else {
											currentRow[column.key] = value
										}
										saveData(currentRow, index, column.key, value)
									}
								})
							}
						} else if (item.date) {
							//如果含有date属性
							return h('DatePicker', {
								props: {
									type: item.date.split('_')[0] || 'date',
									clearable: false,
									value: currentRow[params.column.key]
								},
								on: {
									'on-change': function (value) {
										self.$set(currentRow, params.column.key, value)
									}
								}
							})
						} else {
							return h(Input, {
								placeholder: '请输入',
								// value: currentRow[column.key] = '未填写'? undefined:currentRow[column.key],
								value: currentRow[column.key],
								onChange: (event) => {
									currentRow[column.key] = event.target.value
									saveData(currentRow, index, column.key, event.target.value)
								},
								onBlur: (event) => {
									cloneDataList.value[index].editting = {}
									if (event.target.value == '') {
										currentRow[column.key] = '未填写'
									}
									saveData(currentRow, index, column.key, event.target.value)
								}
							})
						}
					}
				}
			} else {
				if (item.key == 'orderNum') {
					item.customRender = function ({ text, record, index }) {
						return index + 1
					}
				}
			}
			// 使用$set 可以触发视图更新
			// 如果含有titleHtml属性 将其值填入表头
			if (item.children) {
				item.children.forEach((child) => {
					if (child.editable) {
						child.render = function (h, params) {
							var currentRow = self.cloneDataList[params.index]
							// 非编辑状态
							if (!currentRow.editting) {
								// 日期类型单独 渲染(利用工具暴力的formatDate格式化日期)
								if (child.date) {
									// return h('span', self.utils.formatDate(currentRow[item.key], item.date.split('_')[1]))
									return h('span', currentRow[child.key])
								}
								// 下拉类型中value与label不一致时单独渲染
								if (child.option) {
									// 我这里为了简单的判断了第一个元素为object的情况,其实最好用every来判断所有元素
									if (typeof child.option[0] === 'object') {
										let params = child.option.find(findObjectInOption(currentRow[child.key]))
											? child.option.find(findObjectInOption(currentRow[child.key])).label
											: currentRow[child.key]
										return h('span', {}, params)
									}
								}
								return h('span', currentRow[child.key])
							} else {
								// 编辑状态
								//如果含有option属性
								if (child.option) {
									return h(
										'Select',
										{
											props: {
												// ***重点***:  这里要写currentRow[params.column.key],绑定的是cloneDataList里的数据
												value: currentRow[params.column.key],
												transfer: true,
												filterable: true
											},
											on: {
												'on-change': function (value) {
													self.$set(currentRow, params.column.key, value)
												}
											}
										},
										child.option.map(function (child) {
											return h(
												'Option',
												{
													props: {
														value: child.value,
														label: child.label
													}
												},
												child.label
											)
										})
									)
								} else if (child.date) {
									//如果含有date属性
									return h('DatePicker', {
										props: {
											type: child.date.split('_')[0] || 'date',
											clearable: false,
											value: currentRow[params.column.key]
										},
										on: {
											'on-change': function (value) {
												self.$set(currentRow, params.column.key, value)
											}
										}
									})
								} else {
									return h('input', {
										props: {
											// type类型也是自定的属性
											type: child.input || 'text',
											// rows只有在input 为textarea时才会起作用
											rows: 3,
											// disabled: (params.row.type == '1' || params.row.type == '2') && (child.key == 'evaluationtDocumentsName' || child.key == 'content') ? true : false,
											value: currentRow[params.column.key],
											placeholder: child.placeholder ? item.placeholder : ''
										},
										on: {
											'on-change'(event) {
												self.$set(currentRow, params.column.key, event.target.value)
											}
										}
									})
								}
							}
						}
					}
				})
			}
		})
	}

中间组件
//editTable

		<editTable
			:emptyObj="emptyObj"
			:columns="columns"
			ref="editTables"
			:tableData="tableData"
			:reviewShow="reviewShow"
			v-if="refresh_2"
		>
		</editTable>

//消息保存验证

	const getFormData = async () => {
		let flag = false
		subDataList.value = []
		let saveFlag = true
		// 创建一个 Promise 数组来处理异步操作
		const promises = []
		tableData.value.forEach((item, index) => {
			//判断多出来的一行保存的时候不保存最后一行
			if (tableData.value.length - 1 == index && JSON.stringify(item) == JSON.stringify(emptyObj.value)) {
				console.log('空白行')
			} else {
				item.cellClassName = {};
				item.evaluationId = route.query.evaluationId
				item.evaluationInformationId = route.query.evaluationInformationId
				for (var key in item) {
					if (emptyObj.value.hasOwnProperty(key)) {
						if ((item[key] === '' || item[key] === '未填写' || item[key] === '请选择') && key != 'remark') {
							item.cellClassName[key] = 'demo-table-info-cell-name'
							columns.value.forEach((item_1, index_1) => {
								if (item_1.key == key)
									columns.value[index_1].customCell = (record, rowIndex) => {
										return {
											class:
												record[item_1.key] == '请选择' || record[item_1.key] == '未填写'
													? 'demo-table-info-cell-name'
													: ''
										}
									}
							})
						}
						// 重要程度
						if (key === 'levels') {
							let levelsFlag = false
							for (var i = 0; i < columns.value[3].option.length; i++) {
								if (columns.value[3].option[i].label == item[key] || columns.value[3].option[i].value == item[key]) {
									item[key] = columns.value[3].option[i].value
									levelsFlag = true
									break
								}
							}

							if (!levelsFlag) {
								columns.value.forEach((item_1, index_1) => {
									if (item_1.option) {
										columns.value[index_1].customCell = (record, rowIndex) => {
											// 遍历 item_1.option 数组的每一项
											for (let i = 0; i < item_1.option.length; i++) {
												const currentOption = item_1.option[i]
												// 检查条件并返回相应的 class
												if (record.levels == currentOption.label || record.levels == currentOption.value) {
													levelsFlag = true
													item[key] = currentOption.value
													return {
														class: ''
													}
												}
											}
											// 如果没有匹配项,返回默认的 class
											return { class: 'demo-table-info-cell-name' }
										}
									}
								})
								saveFlag = false
							}
						}
					}
				}

				if (Object.keys(item.cellClassName).length == 0) {
					delete item.cellClassName
					let processData = JSON.parse(JSON.stringify(item))
					subDataList.value.push(processData)
				} else {
					saveFlag = false
				}
			}
		})
		console.log(saveFlag, 'saveFlag3')
		if (!saveFlag) {
			editTables.value.init()
		} else {
			subDataList.value.push(...store.state.isopreservation.deleteList)
			store.commit('resetDeleteList')
			const res = await bizEnvironmentApi.saveEnvironmentList(subDataList.value)
			if (res == null) {
				flag = true
			}
		}
		return flag
	}

父组件

//调用中间组件方法
let flag = await researchSysForms.value.getFormData() 

3. 图例

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1864962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

API 安全策略和基础指南

API 是当今数字创新计划的核心&#xff0c;已成为应用程序的头号攻击载体。了解什么是 API 安全、为什么它如此重要&#xff0c;以及如何保护您的 API 免受现代威胁至关重要。 什么是 API 安全&#xff1f; 应用程序编程接口&#xff08;API&#xff09;是现代应用程序的基石…

react学习——15react生命周期(新)

一、生命周期图新 二、生命周期三个阶段&#xff08;新&#xff09; 1. 初始化阶段&#xff1a;由ReactDOM.render()触发—初次渲染 1. constructor() 2. getDerivedStateFromProps 3. render() 4. componentDidMount()2. 更新阶段&#xff1a;由组件内部this.setSate()或…

【Linux学习十八】网站管理:防火墙介绍、静态站点、动态站点、域名

1.Apache Apache官网: www.apache.org 软件包名称: httpd 服务端口:80/tcp(http) 443/tcp(https) 配置文件: /etc/httpd/conf/httpd.conf 子配置文件:/etc/httpd/conf.d/*.conf 查看被占用的端口号 netstat -tuln | grep <端口号> 解哪个程序正在使用端口 80&#xff0…

微信小程序版threejs的使用

首先是使用环境:我是使用的uniapp制作的微信小程序,当然原生的也是可以的,但是测试过很多,发现微信官方的threejs移植版本只能够导入gltf格式的模型,无法导入obj,这就有些尴尬了,为此我找了很多版本的threejs,首先是threejs-miniprogram,也就是官方的,可以直接在unia…

和AI高效对话,掌握这6个原则就够了!

一、前言 2023年11月30日&#xff0c;ChatGPT3.5发布以后&#xff0c;震撼了全球。很多普通人发现&#xff0c;只要会提问题&#xff0c;自己也可以大大方方地拥抱AI和大模型的浪潮~ 对大模型AI提问的技术&#xff0c;就是我们常说的Prompt技术。 Prompt技术&#xff0c;全称为…

状态压缩动态规划(State Compression DP)算法详解

状态压缩动态规划&#xff08;State Compression DP&#xff09;是一种高效解决组合优化问题的技术&#xff0c;特别适用于那些状态空间较大且可以用二进制表示的情况。本文将详细讲解状态压缩DP的原理、常用的位运算技巧、以及具体的例题分析。 原理概述 状态压缩DP的核心思…

[ios逆向]查看ios安装包ipa签名证书embedded.mobileprovision解密 附带解密环境openssl

openssl smime -inform der -verify -noverify -in embedded.mobileprovision 解密embedded.mobileprovision文件 链接&#xff1a;https://pan.baidu.com/s/1UwNOWONKV1SNj5aX_ZZCzQ?pwdglco 提取码&#xff1a;glco –来自百度网盘超级会员V8的分享 可以使用everything 查看…

红酒邂逅瑜伽,开启一场身、心、灵的完美和谐之旅

在喧嚣的都市中&#xff0c;人们总是渴望寻找一处心灵的宁静&#xff0c;一个能够释放身心疲惫的场景。而红酒与瑜伽&#xff0c;正是这样一对奇妙的组合&#xff0c;它们共同为我们开启了一场身心灵的和谐之旅。今天&#xff0c;就让我们一起走进这个充满魅力的世界&#xff0…

守护变电箱消防安全,全氟己酮自动灭火片该安装在哪个位置?

变电箱、配电柜、换电柜是电力设备的重要组成部分&#xff0c;安全性至关重要。但在使用过程中&#xff0c;容易受到电气、机械、环境等因素影响&#xff0c;出现接触不良、短路、漏电等安全隐患&#xff0c;从而引发火灾事故。为了及时防范火灾风险&#xff0c;提前安装一款能…

「51媒体」湖北地区媒体邀约

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 湖北地区拥有网络媒体、电视媒体、报纸杂志、视频媒体等多…

【论文速读】|MEDFUZZ:探索大语言模型在医学问题回答中的鲁棒性

本次分享论文&#xff1a;MEDFUZZ: EXPLORING THE ROBUSTNESS OF LARGE LANGUAGE MODELS IN MEDICAL QUESTION ANSWERING 基本信息 原文作者&#xff1a;Robert Osazuwa Ness, Katie Matton, Hayden Helm, Sheng Zhang, Junaid Bajwa, Carey E. Priebe, Eric Horvitz 作者单…

ModuleNotFoundError: No module named ‘gdal‘

第一步检查gdal包是否正确安装&#xff1a; conda list 已经安装显示如下 若查找不到&#xff1a;请按照此说明步骤进行安装&#xff1a;ModuleNotFoundError: No module named ‘osgeo‘_modulenotfounderror: no module named osgeo-CSDN博客 第二步&#xff1a;检查是否可以…

Shopee、Lazada测评,是找服务商呢?还是建议自己养号补单呢?

目前大部分Shopee、Lazada的卖家由于运营成本的增加&#xff0c;都会找服务商测评来打造权重&#xff0c;但是找服务商有很多不靠谱&#xff0c;建议还是自行精养一批号&#xff0c;账号在手里比较安全可控&#xff0c;随时随地可以送测&#xff0c;精准搜索关键词货比三家下单…

SolidWorks薄壁等厚实体转换成钣金方法

1. 打开SolidWorks软件&#xff0c;新建一个零件。选前视基准面绘制草图&#xff0c;二次创建凸台拉伸特征&#xff0c;如图所示。 2. 创建抽壳特征&#xff0c;厚度“2 mm”&#xff0c;如图所示。 3. 添加切口草图&#xff0c;根据钣金加工工艺在所选面上创建切口草图&#x…

自定义 Django 管理界面中的多对多内联模型

1. 问题背景 在 Django 管理界面中&#xff0c;用户可以使用内联模型来管理一对多的关系。但是&#xff0c;当一对多关系是多对多时&#xff0c;Django 提供的默认内联模型可能并不适合。例如&#xff0c;如果存在一个产品模型和一个发票模型&#xff0c;并且产品和发票之间是…

LICEcap最轻便的C++开源GIF录制工具汉化版本

LICEcap是一款开源的、跨平台的GIF动画录制工具&#xff0c;它使用C编写&#xff0c;旨在为用户提供简单、高效且功能丰富的屏幕录制体验。无论是Windows、macOS还是Linux&#xff08;通过WINE模拟器&#xff09;&#xff0c;LICEcap都能轻松捕获屏幕上的动态内容&#xff0c;并…

VB列表框

移动是将列表框1中选中的数字移动到列表框2中。 全部是将列表框1中所有数字移动到列表框2中。 Public Class Form1Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.LoadDim i As Integer, a As IntegerRandomize()For i 0 To 9a Int(Rnd() * 90) …

Trip.com 如何从 Elasticsearch 迁移到 ClickHouse 并构建了 50PB 的日志解决方案

本文字数&#xff1a;8721&#xff1b;估计阅读时间&#xff1a;22 分钟 审校&#xff1a;庄晓东&#xff08;魏庄&#xff09; 本文在公众号【ClickHouseInc】首发 在 Trip.com&#xff0c;我们为用户提供广泛的数字产品&#xff0c;包括酒店和机票预订、景点、旅游套餐、商务…

玩个游戏 找以下2个wordpress外贸主题的不同 你几找到几处

Aitken艾特肯wordpress外贸主题 适合中国产品出海的蓝色风格wordpress外贸主题&#xff0c;产品多图展示、可自定义显示产品详细参数。 https://www.jianzhanpress.com/?p7060 Ultra奥创工业装备公司wordpress主题 蓝色风格wordpress主题&#xff0c;适合装备制造、工业设备…

红酒达人教你秘技:选酒、存酒,一招一式皆学问

在繁忙的都市生活中&#xff0c;红酒不仅仅是一种饮品&#xff0c;更是一种生活态度&#xff0c;一种品味的象征。然而&#xff0c;面对琳琅满目的红酒品牌与种类&#xff0c;如何选择一瓶心仪的红酒&#xff0c;又如何妥善保存&#xff0c;使其保持很好口感&#xff0c;成为了…