关于table边框,设置了border-collapse:collapse之后,设置border-radius没效果

本文介绍了一个关于CSS中border-radius与border-collapse属性在表格应用中的冲突问题。当同时使用这两个属性时,圆角效果会失效。文章提供了一个简单示例并提出了解决方案:通过将border-collapse更改为separate来实现圆角效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做项目遇到边框需要设置圆角,然后发现在设置了border-collapse:collapse之后,border-radius:10px不起作用了,发现这个是css本身的问题,两者不能混在一起使用。

代码:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body {
padding: 60px;
}
table {
width: 400px;
height: 200px;
border: 1px solid #ddd;
border-collapse: collapse;
}
table tr td {
padding: 20px;
border: 1px solid #ddd;
}
table tr th {
padding: 20px;
border: 1px solid #ddd;
border-radius: 10px;
}

</style>
</head>
<body>
<table>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>王皓</td>
<td>男</td>
<td>28</td>
</tr>
<tr>
<td>2</td>
<td>王皓</td>
<td>男</td>
<td>28</td>
</tr>
<tr>
<td>3</td>
<td>王皓</td>
<td>男</td>
<td>28</td>
</tr>
<tr>
<td>4</td>
<td>王皓</td>
<td>男</td>
<td>28</td>
</tr>
</tbody>
</table>
</body>
</html>

效果图:
  

解决方法:
  个人采取了比较笨拙的方法,将border-collapse属性值改为separate,并重新在CSS中写table td等的边框样式。
  欢迎有更好的方法的网友指正。

转载于:https://www.cnblogs.com/chuyanfenfei/p/8034689.html

mrdnrelate.vue的style改成淺褐色系列: <!-- mrdnrelate.vue --> <template> <div class="mrdnrelate-container"> <!-- 相关病态区域(上方) --> <div class="tags-section"> <h3>尚未與此醫案關聯的病態列表</h3> <div class="filter-info" v-if="filteredTags.length > 0"> 顯示與當前醫案不同但相關的病態標籤({{ filteredTags.length }}個) </div> <div v-if="filteredTags.length > 0" class="dntag-list"> <div v-for="(tag, index) in filteredTags" :key="tag.id" class="dntag-item"> <div class="tag-content"> <span class="tag-index">{{ index + 1 }}.</span> <span class="tag-name">{{ tag.id }}: {{ tag.dnname || '未命名標籤' }}</span> </div> </div> </div> <div v-else class="no-tags"> 沒有符合條件的相關病態標籤 </div> </div> <!-- 分隔线 --> <div class="divider"></div> <!-- MRDN数据区域(下方) --> <div class="mrdn-section"> <h3>醫案病態關聯管理</h3> <!-- 操作按钮 --> <div class="mrdn-controls"> <button @click="fetchMRDNData" class="refresh-btn">刷新數據</button> <button @click="manualCreateMRDN" class="create-btn">手動新增關聯</button> </div> <!-- 数据列表 --> <div v-if="mrdnData.length > 0" class="mrdn-list"> <table class="mrdn-table"> <thead> <tr> <th>ID</th> <th>醫案ID</th> <th>病態ID</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="item in mrdnData" :key="item.id"> <td>{{ item.id }}</td> <td> <span v-if="!item.editing">{{ item.mrinfo }}</span> <textarea v-else v-model="item.editData.mrinfo" class="edit-textarea"></textarea> </td> <td> <span v-if="!item.editing">{{ item.dntag }}</span> <input v-else v-model="item.editData.dntag" type="text" class="edit-input"> </td> <td class="actions"> <template v-if="!item.editing"> <button @click="startEdit(item)" class="edit-btn">編輯</button> <button @click="confirmDelete(item.id)" class="delete-btn">刪除</button> </template> <template v-else> <button @click="saveEdit(item)" class="save-btn">保存</button> <button @click="cancelEdit(item)" class="cancel-btn">取消</button> </template> </td> </tr> </tbody> </table> </div> <div v-else class="no-data"> 沒有醫案病態關聯數據 </div> </div> </div> </template> <script> export default { name: 'mrdnrelate', props: { currentCase: { type: Object, default: null }, allTags: { type: Array, required: true } }, data() { return { mrdnData: [], isCreating: false, hasAutoCreated: false }; }, computed: { filteredTags() { if (!this.currentCase) return []; const currentTagIds = this.currentCase.dntag ? this.currentCase.dntag.map(tag => tag.id) : []; const caseContent = this.currentCase.mrcase || ''; const contentLower = caseContent.toLowerCase(); return this.allTags.filter(tag => { if (currentTagIds.includes(tag.id)) return false; if (!tag.dnname) return false; return contentLower.includes(tag.dnname.toLowerCase()); }); } }, watch: { currentCase: { immediate: true, handler(newVal) { if (newVal && newVal.id) { if (!this.hasAutoCreated) { this.autoCreateMRDN(); this.hasAutoCreated = true; } } } } }, methods: { async fetchMRDNData() { try { const response = await fetch("MRDN/?format=json"); const data = await response.json(); this.mrdnData = data.map(item => ({ id: item.id, mrinfo: item.mrinfo || '', dntag: item.dntag || '', editing: false, editData: { mrinfo: item.mrinfo || '', dntag: item.dntag || '' } })); } catch (error) { console.error("獲取MRDN數據失敗:", error); alert("MRDN數據加載失敗"); } }, async autoCreateMRDN() { if (this.isCreating) return; if (!this.currentCase || !this.currentCase.id) return; if (this.filteredTags.length === 0) return; try { this.isCreating = true; const createRequests = this.filteredTags.map(tag => { return fetch("MRDN/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": this.getCSRFToken() }, body: JSON.stringify({ mrinfo: `${this.currentCase.id}`, dntag: `${tag.id}` }) }); }); const responses = await Promise.all(createRequests); const allSuccess = responses.every(res => res.ok); if (allSuccess) { console.log(`成功新增 ${this.filteredTags.length} 筆MRDN數據!`); this.fetchMRDNData(); this.triggerDataUpdate(); } else { throw new Error("部分新增失敗"); } } catch (error) { console.error("批量新增MRDN失敗:", error); } finally { this.isCreating = false; } }, async manualCreateMRDN() { try { await this.autoCreateMRDN(); if (this.filteredTags.length > 0) { alert(`成功新增 ${this.filteredTags.length} 筆MRDN數據!`); } } catch (error) { alert("新增過程中發生錯誤"); } }, startEdit(item) { item.editing = true; item.editData = { mrinfo: item.mrinfo, dntag: item.dntag }; }, cancelEdit(item) { item.editing = false; }, async saveEdit(item) { try { const response = await fetch(`MRDN/${item.id}/`, { method: "PUT", headers: { "Content-Type": "application/json", "X-CSRFToken": this.getCSRFToken() }, body: JSON.stringify({ mrinfo: item.editData.mrinfo, dntag: item.editData.dntag }) }); if (response.ok) { item.mrinfo = item.editData.mrinfo; item.dntag = item.editData.dntag; item.editing = false; alert("更新成功!"); this.triggerDataUpdate(); } else { throw new Error("更新失敗"); } } catch (error) { console.error("更新MRDN失敗:", error); alert("更新失敗"); } }, confirmDelete(id) { if (confirm("確定要刪除此數據嗎?")) { this.deleteMRDN(id); } }, async deleteMRDN(id) { try { const response = await fetch(`MRDN/${id}/`, { method: "DELETE", headers: { "X-CSRFToken": this.getCSRFToken() } }); if (response.ok) { this.mrdnData = this.mrdnData.filter(item => item.id !== id); alert("刪除成功!"); this.triggerDataUpdate(); } else { throw new Error("刪除失敗"); } } catch (error) { console.error("刪除MRDN失敗:", error); alert("刪除失敗"); } }, getCSRFToken() { return document.querySelector('[name=csrfmiddlewaretoken]')?.value || ''; }, triggerDataUpdate() { this.$emit('data-updated'); } }, mounted() { this.fetchMRDNData(); if (this.currentCase && this.currentCase.id && !this.hasAutoCreated) { this.autoCreateMRDN(); this.hasAutoCreated = true; } } }; </script> <style scoped> .mrdnrelate-container { padding: 15px; background: lightblue; height: 100%; overflow-y: auto; display: flex; flex-direction: column; gap: 15px; } .tags-section { flex: 0 0 40%; overflow-y: auto; background: rgba(255, 255, 255, 0.3); border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .divider { height: 2px; background: #3498db; margin: 10px 0; } .mrdn-section { flex: 1; overflow-y: auto; background: rgba(255, 255, 255, 0.3); border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } /* 其他样式保持不变... */ /* 分隔线样式 */ .divider { height: 2px; background: #3498db; margin: 10px 0; } h3 { margin-top: 0; padding-bottom: 8px; color: #2c3e50; text-align: center; border-bottom: 2px solid #3498db; } .filter-info { text-align: center; margin: 10px 0; font-size: 0.9em; color: #555; background: rgba(255, 255, 255, 0.3); padding: 5px; border-radius: 4px; } .dntag-list { display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 15px; } .dntag-item { background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); overflow: hidden; transition: all 0.3s ease; border-left: 4px solid #3498db; } .tag-content { padding: 12px 15px; display: flex; align-items: center; } .tag-index { font-weight: bold; margin-right: 10px; min-width: 25px; height: 25px; display: flex; align-items: center; justify-content: center; background: #3498db; color: white; border-radius: 50%; } .tag-name { flex-grow: 1; font-weight: 500; color: #2c3e50; } .no-tags, .no-data { padding: 25px; text-align: center; color: #666; font-style: italic; margin-top: 20px; border: 1px dashed #3498db; border-radius: 8px; background: rgba(255, 255, 255, 0.5); } /* MRDN数据管理样式 */ .mrdn-controls { display: flex; justify-content: space-between; margin-bottom: 15px; } .mrdn-controls button { padding: 6px 12px; border-radius: 4px; border: none; cursor: pointer; font-weight: bold; } .refresh-btn { background-color: #4CAF50; color: white; } .create-btn { background-color: #2196F3; color: white; } .mrdn-table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .mrdn-table th, .mrdn-table td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #eee; } .mrdn-table th { background-color: #3498db; color: white; font-weight: bold; } .mrdn-table tr:hover { background-color: #f5f5f5; } .actions { display: flex; gap: 5px; } .actions button { padding: 5px 10px; border: none; border-radius: 3px; cursor: pointer; font-size: 0.85em; } .edit-btn { background-color: #FFC107; color: #333; } .delete-btn { background-color: #F44336; color: white; } .save-btn { background-color: #4CAF50; color: white; } .cancel-btn { background-color: #9E9E9E; color: white; } .edit-input, .edit-textarea { width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 3px; } .edit-textarea { min-height: 60px; resize: vertical; } </style>
07-21
比較mrdnrelate.vue與mrmnrelate.vue,mrdnrelate.vue無法顯示顏色的原因為何?並展示修正後的mrdnrelate.vue代碼, mrdnrelate.vue: <!-- mrdnrelate.vue --> <template> <div class="mrdnrelate-container"> <!-- 相关病态区域(上方) --> <div class="tags-section"> <h3>尚未與此醫案關聯的病態列表</h3> <div class="filter-info" v-if="filteredTags.length > 0"> 顯示與當前醫案不同但相關的病態標籤({{ filteredTags.length }}個) </div> <div v-if="filteredTags.length > 0" class="dntag-list"> <div v-for="(tag, index) in filteredTags" :key="tag.id" class="dntag-item"> <div class="tag-content"> <span class="tag-index">{{ index + 1 }}.</span> <span class="tag-name">{{ tag.id }}: {{ tag.dnname || '未命名標籤' }}</span> </div> </div> </div> <div v-else class="no-tags"> 沒有符合條件的相關病態標籤 </div> </div> <!-- 分隔线 --> <div class="divider"></div> <!-- MRDN数据区域(下方) --> <div class="mrdn-section"> <h3>醫案病態關聯管理</h3> <!-- 操作按钮 --> <div class="mrdn-controls"> <button @click="fetchMRDNData" class="refresh-btn">刷新數據</button> <button @click="manualCreateMRDN" class="create-btn">手動新增關聯</button> </div> <!-- 数据列表 --> <div v-if="mrdnData.length > 0" class="mrdn-list"> <table class="mrdn-table"> <thead> <tr> <th>ID</th> <th>醫案ID</th> <th>病態ID</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="item in mrdnData" :key="item.id"> <td>{{ item.id }}</td> <td> <span v-if="!item.editing">{{ item.mrinfo }}</span> <textarea v-else v-model="item.editData.mrinfo" class="edit-textarea"></textarea> </td> <td> <span v-if="!item.editing">{{ item.dntag }}</span> <input v-else v-model="item.editData.dntag" type="text" class="edit-input"> </td> <td class="actions"> <template v-if="!item.editing"> <button @click="startEdit(item)" class="edit-btn">編輯</button> <button @click="confirmDelete(item.id)" class="delete-btn">刪除</button> </template> <template v-else> <button @click="saveEdit(item)" class="save-btn">保存</button> <button @click="cancelEdit(item)" class="cancel-btn">取消</button> </template> </td> </tr> </tbody> </table> </div> <div v-else class="no-data"> 沒有醫案病態關聯數據 </div> </div> </div> </template> <script> export default { name: 'mrdnrelate', props: { currentCase: { type: Object, default: null }, allTags: { type: Array, required: true } }, data() { return { mrdnData: [], isCreating: false, hasAutoCreated: false }; }, computed: { filteredTags() { if (!this.currentCase) return []; const currentTagIds = this.currentCase.dntag ? this.currentCase.dntag.map(tag => tag.id) : []; const caseContent = this.currentCase.mrcase || ''; const contentLower = caseContent.toLowerCase(); return this.allTags.filter(tag => { if (currentTagIds.includes(tag.id)) return false; if (!tag.dnname) return false; return contentLower.includes(tag.dnname.toLowerCase()); }); } }, watch: { currentCase: { immediate: true, handler(newVal) { if (newVal && newVal.id) { if (!this.hasAutoCreated) { this.autoCreateMRDN(); this.hasAutoCreated = true; } } } } }, methods: { async fetchMRDNData() { try { const response = await fetch("MRDN/?format=json"); const data = await response.json(); this.mrdnData = data.map(item => ({ id: item.id, mrinfo: item.mrinfo || '', dntag: item.dntag || '', editing: false, editData: { mrinfo: item.mrinfo || '', dntag: item.dntag || '' } })); } catch (error) { console.error("獲取MRDN數據失敗:", error); alert("MRDN數據加載失敗"); } }, async autoCreateMRDN() { if (this.isCreating) return; if (!this.currentCase || !this.currentCase.id) return; if (this.filteredTags.length === 0) return; try { this.isCreating = true; const createRequests = this.filteredTags.map(tag => { return fetch("MRDN/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": this.getCSRFToken() }, body: JSON.stringify({ mrinfo: `${this.currentCase.id}`, dntag: `${tag.id}` }) }); }); const responses = await Promise.all(createRequests); const allSuccess = responses.every(res => res.ok); if (allSuccess) { console.log(`成功新增 ${this.filteredTags.length} 筆MRDN數據!`); this.fetchMRDNData(); this.triggerDataUpdate(); } else { throw new Error("部分新增失敗"); } } catch (error) { console.error("批量新增MRDN失敗:", error); } finally { this.isCreating = false; } }, async manualCreateMRDN() { try { await this.autoCreateMRDN(); if (this.filteredTags.length > 0) { alert(`成功新增 ${this.filteredTags.length} 筆MRDN數據!`); } } catch (error) { alert("新增過程中發生錯誤"); } }, startEdit(item) { item.editing = true; item.editData = { mrinfo: item.mrinfo, dntag: item.dntag }; }, cancelEdit(item) { item.editing = false; }, async saveEdit(item) { try { const response = await fetch(`MRDN/${item.id}/`, { method: "PUT", headers: { "Content-Type": "application/json", "X-CSRFToken": this.getCSRFToken() }, body: JSON.stringify({ mrinfo: item.editData.mrinfo, dntag: item.editData.dntag }) }); if (response.ok) { item.mrinfo = item.editData.mrinfo; item.dntag = item.editData.dntag; item.editing = false; alert("更新成功!"); this.triggerDataUpdate(); } else { throw new Error("更新失敗"); } } catch (error) { console.error("更新MRDN失敗:", error); alert("更新失敗"); } }, confirmDelete(id) { if (confirm("確定要刪除此數據嗎?")) { this.deleteMRDN(id); } }, async deleteMRDN(id) { try { const response = await fetch(`MRDN/${id}/`, { method: "DELETE", headers: { "X-CSRFToken": this.getCSRFToken() } }); if (response.ok) { this.mrdnData = this.mrdnData.filter(item => item.id !== id); alert("刪除成功!"); this.triggerDataUpdate(); } else { throw new Error("刪除失敗"); } } catch (error) { console.error("刪除MRDN失敗:", error); alert("刪除失敗"); } }, getCSRFToken() { return document.querySelector('[name=csrfmiddlewaretoken]')?.value || ''; }, triggerDataUpdate() { this.$emit('data-updated'); } }, mounted() { this.fetchMRDNData(); if (this.currentCase && this.currentCase.id && !this.hasAutoCreated) { this.autoCreateMRDN(); this.hasAutoCreated = true; } } }; </script> <style scoped> .mrdnrelate-container { padding: 15px; background: lightblue; height: 100%; overflow-y: auto; display: flex; flex-direction: column; gap: 15px; } .tags-section { flex: 0 0 40%; overflow-y: auto; background: rgba(255, 255, 255, 0.3); border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .divider { height: 2px; background: #3498db; margin: 10px 0; } .mrdn-section { flex: 1; overflow-y: auto; background: rgba(255, 255, 255, 0.3); border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } /* 其他样式保持不变... */ /* 分隔线样式 */ .divider { height: 2px; background: #3498db; margin: 10px 0; } h3 { margin-top: 0; padding-bottom: 8px; color: #2c3e50; text-align: center; border-bottom: 2px solid #3498db; } .filter-info { text-align: center; margin: 10px 0; font-size: 0.9em; color: #555; background: rgba(255, 255, 255, 0.3); padding: 5px; border-radius: 4px; } .dntag-list { display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 15px; } .dntag-item { background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); overflow: hidden; transition: all 0.3s ease; border-left: 4px solid #3498db; } .tag-content { padding: 12px 15px; display: flex; align-items: center; } .tag-index { font-weight: bold; margin-right: 10px; min-width: 25px; height: 25px; display: flex; align-items: center; justify-content: center; background: #3498db; color: white; border-radius: 50%; } .tag-name { flex-grow: 1; font-weight: 500; color: #2c3e50; } .no-tags, .no-data { padding: 25px; text-align: center; color: #666; font-style: italic; margin-top: 20px; border: 1px dashed #3498db; border-radius: 8px; background: rgba(255, 255, 255, 0.5); } /* MRDN数据管理样式 */ .mrdn-controls { display: flex; justify-content: space-between; margin-bottom: 15px; } .mrdn-controls button { padding: 6px 12px; border-radius: 4px; border: none; cursor: pointer; font-weight: bold; } .refresh-btn { background-color: #4CAF50; color: white; } .create-btn { background-color: #2196F3; color: white; } .mrdn-table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .mrdn-table th, .mrdn-table td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #eee; } .mrdn-table th { background-color: #3498db; color: white; font-weight: bold; } .mrdn-table tr:hover { background-color: #f5f5f5; } .actions { display: flex; gap: 5px; } .actions button { padding: 5px 10px; border: none; border-radius: 3px; cursor: pointer; font-size: 0.85em; } .edit-btn { background-color: #FFC107; color: #333; } .delete-btn { background-color: #F44336; color: white; } .save-btn { background-color: #4CAF50; color: white; } .cancel-btn { background-color: #9E9E9E; color: white; } .edit-input, .edit-textarea { width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 3px; } .edit-textarea { min-height: 60px; resize: vertical; } </style> mrmnrelate.vue: <!-- mrmnrelate.vue --> <template> <div class="mrmnrelate-container"> <!-- 相关本草区域 --> <div class="tags-section"> <h3>尚未與此醫案關聯的本草列表</h3> <div class="filter-info" v-if="filteredTags.length > 0"> 顯示與當前醫案不同但相關的本草標籤({{ filteredTags.length }}個) </div> <div v-if="filteredTags.length > 0" class="mntag-list"> <div v-for="(tag, index) in filteredTags" :key="tag.id" class="mntag-item"> <div class="tag-content"> <span class="tag-index">{{ index + 1 }}.</span> <span class="tag-name">{{ tag.id }}: {{ tag.mnname || '未命名標籤' }}</span> </div> </div> </div> <div v-else class="no-tags"> 沒有符合條件的相關本草標籤 </div> </div> <!-- 分隔线 --> <div class="divider"></div> <!-- MRMN数据区域 --> <div class="mrmn-section"> <h3>醫案本草關聯管理</h3> <!-- 操作按钮 --> <div class="mrmn-controls"> <button @click="fetchMRMNData" class="refresh-btn">刷新數據</button> <button @click="manualCreateMRMN" class="create-btn">手動新增關聯</button> </div> <!-- 数据列表 --> <div v-if="mrmnData.length > 0" class="mrmn-list"> <table class="mrmn-table"> <thead> <tr> <th>ID</th> <th>醫案ID</th> <th>本草ID</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="item in mrmnData" :key="item.id"> <td>{{ item.id }}</td> <td> <span v-if="!item.editing">{{ item.mrinfo }}</span> <textarea v-else v-model="item.editData.mrinfo" class="edit-textarea"></textarea> </td> <td> <span v-if="!item.editing">{{ item.mntag }}</span> <input v-else v-model="item.editData.mntag" type="text" class="edit-input"> </td> <td class="actions"> <template v-if="!item.editing"> <button @click="startEdit(item)" class="edit-btn">編輯</button> <button @click="confirmDelete(item.id)" class="delete-btn">刪除</button> </template> <template v-else> <button @click="saveEdit(item)" class="save-btn">保存</button> <button @click="cancelEdit(item)" class="cancel-btn">取消</button> </template> </td> </tr> </tbody> </table> </div> <div v-else class="no-data"> 沒有醫案本草關聯數據 </div> </div> </div> </template> <script> export default { name: 'mrmnrelate', props: { currentCase: { type: Object, default: null }, allTags: { type: Array, required: true } }, data() { return { mrmnData: [], isCreating: false, hasAutoCreated: false }; }, computed: { filteredTags() { if (!this.currentCase) return []; const currentTagIds = this.currentCase.mntag ? this.currentCase.mntag.map(tag => tag.id) : []; const caseContent = this.currentCase.mrcase || ''; const contentLower = caseContent.toLowerCase(); return this.allTags.filter(tag => { if (currentTagIds.includes(tag.id)) return false; if (!tag.mnname) return false; return contentLower.includes(tag.mnname.toLowerCase()); }); } }, watch: { currentCase: { immediate: true, handler(newVal) { if (newVal && newVal.id) { if (!this.hasAutoCreated) { this.autoCreateMRMN(); this.hasAutoCreated = true; } } } } }, methods: { async fetchMRMNData() { try { const response = await fetch("MRMN/?format=json"); const data = await response.json(); this.mrmnData = data.map(item => ({ id: item.id, mrinfo: item.mrinfo || '', mntag: item.mntag || '', editing: false, editData: { mrinfo: item.mrinfo || '', mntag: item.mntag || '' } })); } catch (error) { console.error("獲取MRMN數據失敗:", error); alert("MRMN數據加載失敗"); } }, async autoCreateMRMN() { if (this.isCreating) return; if (!this.currentCase || !this.currentCase.id) return; if (this.filteredTags.length === 0) return; try { this.isCreating = true; const createRequests = this.filteredTags.map(tag => { return fetch("MRMN/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": this.getCSRFToken() }, body: JSON.stringify({ mrinfo: `${this.currentCase.id}`, mntag: `${tag.id}` }) }); }); const responses = await Promise.all(createRequests); const allSuccess = responses.every(res => res.ok); if (allSuccess) { console.log(`成功新增 ${this.filteredTags.length} 筆MRMN數據!`); this.fetchMRMNData(); this.triggerDataUpdate(); } else { throw new Error("部分新增失敗"); } } catch (error) { console.error("批量新增MRMN失敗:", error); } finally { this.isCreating = false; } }, async manualCreateMRMN() { try { await this.autoCreateMRMN(); if (this.filteredTags.length > 0) { alert(`成功新增 ${this.filteredTags.length} 筆MRMN數據!`); } } catch (error) { alert("新增過程中發生錯誤"); } }, startEdit(item) { item.editing = true; item.editData = { mrinfo: item.mrinfo, mntag: item.mntag }; }, cancelEdit(item) { item.editing = false; }, async saveEdit(item) { try { const response = await fetch(`MRMN/${item.id}/`, { method: "PUT", headers: { "Content-Type": "application/json", "X-CSRFToken": this.getCSRFToken() }, body: JSON.stringify({ mrinfo: item.editData.mrinfo, mntag: item.editData.mntag }) }); if (response.ok) { item.mrinfo = item.editData.mrinfo; item.mntag = item.editData.mntag; item.editing = false; alert("更新成功!"); this.triggerDataUpdate(); } else { throw new Error("更新失敗"); } } catch (error) { console.error("更新MRMN失敗:", error); alert("更新失敗"); } }, confirmDelete(id) { if (confirm("確定要刪除此數據嗎?")) { this.deleteMRMN(id); } }, async deleteMRMN(id) { try { const response = await fetch(`MRMN/${id}/`, { method: "DELETE", headers: { "X-CSRFToken": this.getCSRFToken() } }); if (response.ok) { this.mrmnData = this.mrmnData.filter(item => item.id !== id); alert("刪除成功!"); this.triggerDataUpdate(); } else { throw new Error("刪除失敗"); } } catch (error) { console.error("刪除MRMN失敗:", error); alert("刪除失敗"); } }, getCSRFToken() { return document.querySelector('[name=csrfmiddlewaretoken]')?.value || ''; }, triggerDataUpdate() { this.$emit('data-updated'); } }, mounted() { this.fetchMRMNData(); if (this.currentCase && this.currentCase.id && !this.hasAutoCreated) { this.autoCreateMRMN(); this.hasAutoCreated = true; } } }; </script> <style scoped> .mrmnrelate-container { padding: 15px; background: #e0f7e0; /* 本草主题绿色背景 */ height: 100%; overflow-y: auto; display: flex; flex-direction: column; gap: 15px; } .tags-section { flex: 0 0 40%; overflow-y: auto; background: rgba(255, 255, 255, 0.5); border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .divider { height: 2px; background: #4CAF50; /* 本草主题绿色 */ margin: 10px 0; } .mrmn-section { flex: 1; overflow-y: auto; background: rgba(255, 255, 255, 0.5); border-radius: 8px; padding: 15px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } h3 { margin-top: 0; padding-bottom: 8px; color: #1B5E20; /* 深绿色 */ text-align: center; border-bottom: 2px solid #4CAF50; /* 本草主题绿色 */ } .filter-info { text-align: center; margin: 10px 0; font-size: 0.9em; color: #1B5E20; /* 深绿色 */ background: rgba(76, 175, 80, 0.2); /* 本草主题绿色透明背景 */ padding: 5px; border-radius: 4px; } .mntag-list { display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 15px; } .mntag-item { background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); overflow: hidden; transition: all 0.3s ease; border-left: 4px solid #4CAF50; /* 本草主题绿色 */ } .tag-content { padding: 12px 15px; display: flex; align-items: center; } .tag-index { font-weight: bold; margin-right: 10px; min-width: 25px; height: 25px; display: flex; align-items: center; justify-content: center; background: #4CAF50; /* 本草主题绿色 */ color: white; border-radius: 50%; } .tag-name { flex-grow: 1; font-weight: 500; color: #1B5E20; /* 深绿色 */ } .no-tags, .no-data { padding: 25px; text-align: center; color: #666; font-style: italic; margin-top: 20px; border: 1px dashed #4CAF50; /* 本草主题绿色 */ border-radius: 8px; background: rgba(255, 255, 255, 0.5); } /* MRMN数据管理样式 */ .mrmn-controls { display: flex; justify-content: space-between; margin-bottom: 15px; } .mrmn-controls button { padding: 6px 12px; border-radius: 4px; border: none; cursor: pointer; font-weight: bold; } .refresh-btn { background-color: #4CAF50; /* 本草主题绿色 */ color: white; } .create-btn { background-color: #2196F3; color: white; } .mrmn-table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .mrmn-table th, .mrmn-table td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #eee; } .mrmn-table th { background-color: #4CAF50; /* 本草主题绿色 */ color: white; font-weight: bold; } .mrmn-table tr:hover { background-color: #f5f5f5; } .actions { display: flex; gap: 5px; } .actions button { padding: 5px 10px; border: none; border-radius: 3px; cursor: pointer; font-size: 0.85em; } .edit-btn { background-color: #FFC107; color: #333; } .delete-btn { background-color: #F44336; color: white; } .save-btn { background-color: #4CAF50; /* 本草主题绿色 */ color: white; } .cancel-btn { background-color: #9E9E9E; color: white; } .edit-input, .edit-textarea { width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 3px; } .edit-textarea { min-height: 60px; resize: vertical; } </style>
07-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值