From 0c445ac6d2a20153e5eac390555ba88f950d76b0 Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期四, 14 八月 2025 17:16:16 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/dev_7004' into dev_7004 --- src/views/collaborativeApproval/noticeManagement/index.vue | 705 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 705 insertions(+), 0 deletions(-) diff --git a/src/views/collaborativeApproval/noticeManagement/index.vue b/src/views/collaborativeApproval/noticeManagement/index.vue new file mode 100644 index 0000000..daa4cd7 --- /dev/null +++ b/src/views/collaborativeApproval/noticeManagement/index.vue @@ -0,0 +1,705 @@ +<template> + <div class="app-container"> + <!-- 鎼滅储琛ㄥ崟 --> + <div class="search_form"> + <div> + <span class="search_title">鍏憡鏍囬锛�</span> + <el-input + v-model="searchForm.noticeTitle" + style="width: 240px" + placeholder="璇疯緭鍏ュ叕鍛婃爣棰樻悳绱�" + @change="handleQuery" + clearable + :prefix-icon="Search" + /> + <span class="search_title ml10">鍏憡绫诲瀷锛�</span> + <el-select v-model="searchForm.noticeType" clearable @change="handleQuery" style="width: 240px"> + <el-option label="鏀惧亣閫氱煡" value="1" /> + <el-option label="璁惧缁翠慨閫氱煡" value="2" /> + </el-select> + <span class="search_title ml10">鐘舵�侊細</span> + <el-select v-model="searchForm.status" clearable @change="handleQuery" style="width: 240px"> + <el-option label="鑽夌" value="0" /> + <el-option label="宸插彂甯�" value="1" /> + <el-option label="宸蹭笅绾�" value="2" /> + </el-select> + <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button> + <el-button @click="resetQuery" style="margin-left: 10px">閲嶇疆</el-button> + </div> + <div> + <el-button type="primary" @click="openForm('add')">鏂板鍏憡</el-button> + <el-button type="danger" plain @click="handleDelete" :disabled="!selectedIds.length">鍒犻櫎</el-button> + </div> + </div> + + <!-- 閫氱煡鍏憡鏉� --> + <div class="notice-board"> + <!-- 鏀惧亣閫氱煡鍖哄煙 --> + <div class="notice-section" v-if="holidayNotices.length > 0"> + <div class="section-header"> + <h3>馃搮 鏀惧亣閫氱煡</h3> + <span class="section-count">{{ holidayNotices.length }}鏉�</span> + </div> + <div class="notice-cards"> + <div + v-for="notice in holidayNotices" + :key="notice.id" + class="notice-card holiday-card" + :class="{ 'urgent': notice.priority === '3' }" + > + <div class="card-header"> + <div class="card-title"> + <el-icon class="holiday-icon"><Calendar /></el-icon> + {{ notice.noticeTitle }} + </div> + <div class="card-actions"> + <el-button link type="primary" @click="handleEdit(notice)">缂栬緫</el-button> + <el-button link type="danger" @click="handleDelete(notice.id)">鍒犻櫎</el-button> + </div> + </div> + <div class="card-content"> + <p>{{ notice.noticeContent }}</p> + </div> + <div class="card-footer"> + <div class="card-meta"> + <span class="priority" :class="'priority-' + notice.priority"> + {{ getPriorityText(notice.priority) }} + </span> + <span class="status" :class="'status-' + notice.status"> + {{ getStatusText(notice.status) }} + </span> + </div> + <div class="card-info"> + <span class="creator">{{ notice.createBy }}</span> + <span class="time">{{ notice.createTime }}</span> + </div> + </div> + <div class="card-remark" v-if="notice.remark"> + <el-icon><InfoFilled /></el-icon> + <span>{{ notice.remark }}</span> + </div> + </div> + </div> + </div> + + <!-- 璁惧缁翠慨閫氱煡鍖哄煙 --> + <div class="notice-section" v-if="maintenanceNotices.length > 0"> + <div class="section-header"> + <h3>馃敡 璁惧缁翠慨閫氱煡</h3> + <span class="section-count">{{ maintenanceNotices.length }}鏉�</span> + </div> + <div class="notice-cards"> + <div + v-for="notice in maintenanceNotices" + :key="notice.id" + class="notice-card maintenance-card" + :class="{ 'urgent': notice.priority === '3' }" + > + <div class="card-header"> + <div class="card-title"> + <el-icon class="maintenance-icon"><Tools /></el-icon> + {{ notice.noticeTitle }} + </div> + <div class="card-actions"> + <el-button link type="primary" @click="handleEdit(notice)">缂栬緫</el-button> + <el-button link type="danger" @click="handleDelete(notice.id)">鍒犻櫎</el-button> + </div> + </div> + <div class="card-content"> + <p>{{ notice.noticeContent }}</p> + </div> + <div class="card-footer"> + <div class="card-meta"> + <span class="priority" :class="'priority-' + notice.priority"> + {{ getPriorityText(notice.priority) }} + </span> + <span class="status" :class="'status-' + notice.status"> + {{ getStatusText(notice.status) }} + </span> + </div> + <div class="card-info"> + <span class="creator">{{ notice.createBy }}</span> + <span class="time">{{ notice.createTime }}</span> + </div> + </div> + <div class="card-remark" v-if="notice.remark"> + <el-icon><InfoFilled /></el-icon> + <span>{{ notice.remark }}</span> + </div> + </div> + </div> + </div> + + <!-- 绌虹姸鎬� --> + <div class="empty-state" v-if="filteredNotices.length === 0"> + <el-empty description="鏆傛棤閫氱煡鍏憡" /> + </div> + </div> + + <!-- 鏂板/缂栬緫瀵硅瘽妗� --> + <el-dialog + :title="dialogTitle" + v-model="dialogVisible" + width="800px" + append-to-body + @close="resetForm" + > + <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鍏憡鏍囬" prop="noticeTitle"> + <el-input v-model="form.noticeTitle" placeholder="璇疯緭鍏ュ叕鍛婃爣棰�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍏憡绫诲瀷" prop="noticeType"> + <el-select v-model="form.noticeType" placeholder="璇烽�夋嫨鍏憡绫诲瀷" style="width: 100%"> + <el-option label="鏀惧亣閫氱煡" value="1" /> + <el-option label="璁惧缁翠慨閫氱煡" value="2" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鐘舵��"> + <el-radio-group v-model="form.status"> + <el-radio value="0">鑽夌</el-radio> + <el-radio value="1">宸插彂甯�</el-radio> + <el-radio value="2">宸蹭笅绾�</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="浼樺厛绾�"> + <el-select v-model="form.priority" placeholder="璇烽�夋嫨浼樺厛绾�" style="width: 100%"> + <el-option label="鏅��" value="1" /> + <el-option label="閲嶈" value="2" /> + <el-option label="绱ф��" value="3" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="鍏憡鍐呭" prop="noticeContent"> + <el-input + v-model="form.noticeContent" + type="textarea" + :rows="6" + placeholder="璇疯緭鍏ュ叕鍛婂唴瀹�" + maxlength="500" + show-word-limit + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="澶囨敞"> + <el-input + v-model="form.remark" + type="textarea" + :rows="3" + placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" + maxlength="200" + show-word-limit + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="dialogVisible = false">鍙� 娑�</el-button> + </div> + </template> + </el-dialog> + </div> +</template> + +<script setup> +import { Search, Calendar, Tools, InfoFilled } from "@element-plus/icons-vue"; +import { onMounted, ref, reactive, toRefs, computed } from "vue"; +import { ElMessage, ElMessageBox } from "element-plus"; +import useUserStore from "@/store/modules/user"; + +const userStore = useUserStore(); + +// 鍝嶅簲寮忔暟鎹� +const data = reactive({ + searchForm: { + noticeTitle: "", + noticeType: "", + status: "", + }, + form: { + id: undefined, + noticeTitle: "", + noticeType: "", + noticeContent: "", + status: "0", + priority: "1", + remark: "", + createBy: "", + createTime: "", + }, + rules: { + noticeTitle: [ + { required: true, message: "鍏憡鏍囬涓嶈兘涓虹┖", trigger: "blur" } + ], + noticeType: [ + { required: true, message: "璇烽�夋嫨鍏憡绫诲瀷", trigger: "change" } + ], + noticeContent: [ + { required: true, message: "鍏憡鍐呭涓嶈兘涓虹┖", trigger: "blur" } + ] + } +}); + +const { searchForm, form, rules } = toRefs(data); + +// 椤甸潰鐘舵�� +const dialogVisible = ref(false); +const dialogTitle = ref(""); +const selectedIds = ref([]); +const formRef = ref(); + +// 妯℃嫙鏁版嵁 - 鏍规嵁娉曞畾鑺傚亣鏃ヨ璁� +const mockData = [ + { + id: 1, + noticeTitle: "2024骞存槬鑺傛斁鍋囬�氱煡", + noticeType: "1", + priority: "2", + status: "1", + noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞存槬鑺傛斁鍋囧畨鎺掑涓嬶細2鏈�10鏃ワ紙鍒濅竴锛夎嚦2鏈�17鏃ワ紙鍒濆叓锛夋斁鍋囪皟浼戯紝鍏�8澶┿��2鏈�4鏃ワ紙鏄熸湡鏃ワ級銆�2鏈�18鏃ワ紙鏄熸湡鏃ワ級涓婄彮銆傝鍚勯儴闂ㄦ彁鍓嶅仛濂藉伐浣滃畨鎺掋��", + remark: "鏀惧亣鏈熼棿璇蜂繚鎸佹墜鏈虹晠閫氾紝濡傛湁绱ф�ヤ簨鍔″強鏃惰仈绯�", + createBy: "浜轰簨閮�", + createTime: "2024-01-15 10:30:00" + }, + { + id: 2, + noticeTitle: "2024骞存竻鏄庤妭鏀惧亣閫氱煡", + noticeType: "1", + priority: "1", + status: "1", + noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞存竻鏄庤妭鏀惧亣瀹夋帓濡備笅锛�4鏈�4鏃ワ紙鏄熸湡鍥涳級鑷�4鏈�6鏃ワ紙鏄熸湡鍏級鏀惧亣璋冧紤锛屽叡3澶┿��4鏈�7鏃ワ紙鏄熸湡鏃ワ級涓婄彮銆�", + remark: "璇峰悇閮ㄩ棬鍋氬ソ鍊肩彮瀹夋帓锛岀‘淇濊妭鏃ユ湡闂村悇椤瑰伐浣滄甯歌繍杞�", + createBy: "琛屾斂閮�", + createTime: "2024-01-14 14:20:00" + }, + { + id: 3, + noticeTitle: "2024骞村姵鍔ㄨ妭鏀惧亣閫氱煡", + noticeType: "1", + priority: "1", + status: "1", + noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞村姵鍔ㄨ妭鏀惧亣瀹夋帓濡備笅锛�5鏈�1鏃ワ紙鏄熸湡涓夛級鑷�5鏈�5鏃ワ紙鏄熸湡鏃ワ級鏀惧亣璋冧紤锛屽叡5澶┿��4鏈�28鏃ワ紙鏄熸湡鏃ワ級銆�5鏈�11鏃ワ紙鏄熸湡鍏級涓婄彮銆�", + remark: "鏀惧亣鍓嶈鍏抽棴鐢垫簮锛岄攣濂介棬绐楋紝娉ㄦ剰瀹夊叏", + createBy: "琛屾斂閮�", + createTime: "2024-01-13 09:15:00" + }, + { + id: 4, + noticeTitle: "2024骞寸鍗堣妭鏀惧亣閫氱煡", + noticeType: "1", + priority: "1", + status: "1", + noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞寸鍗堣妭鏀惧亣瀹夋帓濡備笅锛�6鏈�8鏃ワ紙鏄熸湡鍏級鑷�6鏈�10鏃ワ紙鏄熸湡涓�锛夋斁鍋囪皟浼戯紝鍏�3澶┿��6鏈�11鏃ワ紙鏄熸湡浜岋級涓婄彮銆�", + remark: "绁濆ぇ瀹剁鍗堣妭蹇箰锛岄槚瀹跺垢绂忥紒", + createBy: "琛屾斂閮�", + createTime: "2024-01-12 16:30:00" + }, + { + id: 5, + noticeTitle: "2024骞翠腑绉嬭妭鏀惧亣閫氱煡", + noticeType: "1", + priority: "1", + status: "1", + noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞翠腑绉嬭妭鏀惧亣瀹夋帓濡備笅锛�9鏈�15鏃ワ紙鏄熸湡鏃ワ級鑷�9鏈�17鏃ワ紙鏄熸湡浜岋級鏀惧亣璋冧紤锛屽叡3澶┿��9鏈�14鏃ワ紙鏄熸湡鍏級涓婄彮銆�", + remark: "涓浣宠妭锛岀澶у鍥㈠渾缇庢弧锛屽垢绂忓畨搴凤紒", + createBy: "琛屾斂閮�", + createTime: "2024-01-11 11:20:00" + }, + { + id: 6, + noticeTitle: "2024骞村浗搴嗚妭鏀惧亣閫氱煡", + noticeType: "1", + priority: "2", + status: "1", + noticeContent: "鏍规嵁鍥藉姟闄㈠姙鍏巺閫氱煡锛�2024骞村浗搴嗚妭鏀惧亣瀹夋帓濡備笅锛�10鏈�1鏃ワ紙鏄熸湡浜岋級鑷�10鏈�7鏃ワ紙鏄熸湡涓�锛夋斁鍋囪皟浼戯紝鍏�7澶┿��9鏈�29鏃ワ紙鏄熸湡鏃ワ級銆�10鏈�12鏃ワ紙鏄熸湡鍏級涓婄彮銆�", + remark: "鍥藉簡鏈熼棿璇峰悇閮ㄩ棬鍋氬ソ鍊肩彮瀹夋帓锛岀‘淇濆畨鍏ㄧǔ瀹�", + createBy: "琛屾斂閮�", + createTime: "2024-01-10 15:45:00" + }, + { + id: 7, + noticeTitle: "A杞﹂棿鐢熶骇绾垮勾搴︽淇�氱煡", + noticeType: "2", + priority: "2", + status: "1", + noticeContent: "A杞﹂棿鐢熶骇绾垮皢浜�2024骞�1鏈�20鏃ワ紙鍛ㄥ叚锛夎繘琛屽勾搴︽淇淮鎶わ紝棰勮鍋滃伐8灏忔椂銆傛淇唴瀹瑰寘鎷細璁惧娓呮磥銆佹鼎婊戜繚鍏汇�佸畨鍏ㄨ缃鏌ョ瓑銆傝鐢熶骇閮ㄩ棬鎻愬墠璋冩暣鐢熶骇璁″垝銆�", + remark: "缁翠慨鏈熼棿璇风浉鍏充汉鍛橀厤鍚堬紝纭繚妫�淇伐浣滃畨鍏ㄩ『鍒╄繘琛�", + createBy: "璁惧閮�", + createTime: "2024-01-14 14:20:00" + }, + { + id: 8, + noticeTitle: "B杞﹂棿璁惧棰勯槻鎬х淮鎶ら�氱煡", + noticeType: "2", + priority: "1", + status: "1", + noticeContent: "B杞﹂棿鍏抽敭璁惧灏嗕簬2024骞�1鏈�25鏃ヨ繘琛岄闃叉�х淮鎶わ紝棰勮鍋滃伐4灏忔椂銆傜淮鎶ゅ唴瀹瑰寘鎷細璁惧妫�鏌ャ�侀浂浠舵洿鎹€�佹�ц兘娴嬭瘯绛夈�傝鐩稿叧閮ㄩ棬閰嶅悎銆�", + remark: "缁存姢瀹屾垚鍚庡皢杩涜璇曡繍琛岋紝纭繚璁惧姝e父杩愯", + createBy: "璁惧閮�", + createTime: "2024-01-13 09:15:00" + } +]; + +// 璁$畻灞炴�� +const filteredNotices = computed(() => { + let filtered = [...mockData]; + + if (searchForm.value.noticeTitle) { + filtered = filtered.filter(item => + item.noticeTitle.includes(searchForm.value.noticeTitle) + ); + } + if (searchForm.value.noticeType) { + filtered = filtered.filter(item => + item.noticeType === searchForm.value.noticeType + ); + } + if (searchForm.value.status !== "") { + filtered = filtered.filter(item => + item.status === searchForm.value.status + ); + } + + return filtered; +}); + +const holidayNotices = computed(() => { + return filteredNotices.value.filter(notice => notice.noticeType === "1"); +}); + +const maintenanceNotices = computed(() => { + return filteredNotices.value.filter(notice => notice.noticeType === "2"); +}); + +// 鏂规硶瀹氫箟 +const handleQuery = () => { + // 鎼滅储鍔熻兘淇濇寔涓嶅彉锛屼絾鏁版嵁閫氳繃璁$畻灞炴�ц嚜鍔ㄨ繃婊� +}; + +const resetQuery = () => { + searchForm.value = { + noticeTitle: "", + noticeType: "", + status: "" + }; +}; + +const getPriorityText = (priority) => { + const priorityMap = { "1": "鏅��", "2": "閲嶈", "3": "绱ф��" }; + return priorityMap[priority] || "鏅��"; +}; + +const getStatusText = (status) => { + const statusMap = { "0": "鑽夌", "1": "宸插彂甯�", "2": "宸蹭笅绾�" }; + return statusMap[status] || "鏈煡"; +}; + +const openForm = (type) => { + if (type === 'add') { + dialogTitle.value = "鏂板鍏憡"; + form.value = { + id: undefined, + noticeTitle: "", + noticeType: "", + noticeContent: "", + status: "0", + priority: "1", + remark: "", + createBy: userStore.name || "褰撳墠鐢ㄦ埛", + createTime: new Date().toLocaleString() + }; + } + dialogVisible.value = true; +}; + +const handleEdit = (row) => { + dialogTitle.value = "缂栬緫鍏憡"; + form.value = { ...row }; + dialogVisible.value = true; +}; + +const handleSelectionChange = (selection) => { + selectedIds.value = selection.map(item => item.id); +}; + +const handleDelete = (id) => { + ElMessageBox.confirm( + "纭鍒犻櫎杩欐潯鍏憡鍚楋紵", + "鎻愮ず", + { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning" + } + ).then(() => { + const index = mockData.findIndex(item => item.id === id); + if (index > -1) { + mockData.splice(index, 1); + ElMessage.success("鍒犻櫎鎴愬姛"); + } + }); +}; + +const submitForm = () => { + formRef.value.validate((valid) => { + if (valid) { + if (form.value.id) { + // 缂栬緫妯″紡 + const index = mockData.findIndex(item => item.id === form.value.id); + if (index > -1) { + mockData[index] = { ...form.value }; + } + ElMessage.success("淇敼鎴愬姛"); + } else { + // 鏂板妯″紡 + const newId = Math.max(...mockData.map(item => item.id)) + 1; + const newNotice = { + ...form.value, + id: newId, + createTime: new Date().toLocaleString() + }; + mockData.unshift(newNotice); + ElMessage.success("鏂板鎴愬姛"); + } + dialogVisible.value = false; + } + }); +}; + +const resetForm = () => { + formRef.value?.resetFields(); +}; + +// 鐢熷懡鍛ㄦ湡 +onMounted(() => { + // 椤甸潰鍔犺浇瀹屾垚 +}); +</script> + +<style scoped> +.search_form { + background: #fff; + padding: 20px; + margin-bottom: 20px; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + display: flex; + justify-content: space-between; + align-items: center; +} + +.search_title { + font-weight: 500; + color: #333; + margin-right: 8px; +} + +.ml10 { + margin-left: 10px; +} + +.notice-board { + background: #f5f7fa; + padding: 20px; + border-radius: 8px; +} + +.notice-section { + margin-bottom: 30px; +} + +.section-header { + display: flex; + align-items: center; + margin-bottom: 20px; + padding: 0 10px; +} + +.section-header h3 { + margin: 0; + color: #303133; + font-size: 18px; + font-weight: 600; +} + +.section-count { + margin-left: 10px; + background: #409eff; + color: white; + padding: 2px 8px; + border-radius: 12px; + font-size: 12px; +} + +.notice-cards { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + gap: 20px; +} + +.notice-card { + background: white; + border-radius: 12px; + padding: 20px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + border-left: 4px solid transparent; +} + +.notice-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.holiday-card { + border-left-color: #67c23a; +} + +.maintenance-card { + border-left-color: #e6a23c; +} + +.urgent { + border-left-color: #f56c6c; + background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%); +} + +.card-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 15px; +} + +.card-title { + display: flex; + align-items: center; + font-size: 16px; + font-weight: 600; + color: #303133; + flex: 1; +} + +.holiday-icon { + color: #67c23a; + margin-right: 8px; + font-size: 18px; +} + +.maintenance-icon { + color: #e6a23c; + margin-right: 8px; + font-size: 18px; +} + +.card-actions { + display: flex; + gap: 8px; +} + +.card-content { + margin-bottom: 15px; +} + +.card-content p { + margin: 0; + color: #606266; + line-height: 1.6; + font-size: 14px; +} + +.card-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} + +.card-meta { + display: flex; + gap: 8px; +} + +.priority, .status { + padding: 2px 8px; + border-radius: 12px; + font-size: 12px; + font-weight: 500; +} + +.priority-1 { background: #f0f9ff; color: #0369a1; } +.priority-2 { background: #fef3c7; color: #d97706; } +.priority-3 { background: #fef2f2; color: #dc2626; } + +.status-0 { background: #f3f4f6; color: #6b7280; } +.status-1 { background: #d1fae5; color: #059669; } +.status-2 { background: #fef3c7; color: #d97706; } + +.card-info { + display: flex; + flex-direction: column; + align-items: flex-end; + font-size: 12px; + color: #909399; +} + +.creator { + font-weight: 500; + margin-bottom: 2px; +} + +.card-remark { + display: flex; + align-items: center; + gap: 6px; + padding: 8px 12px; + background: #f8f9fa; + border-radius: 6px; + font-size: 12px; + color: #606266; + border-left: 3px solid #409eff; +} + +.empty-state { + text-align: center; + padding: 60px 20px; +} + +.dialog-footer { + text-align: right; +} + +/* 鍝嶅簲寮忚璁� */ +@media (max-width: 768px) { + .notice-cards { + grid-template-columns: 1fr; + } + + .search_form { + flex-direction: column; + gap: 15px; + } + + .search_form > div { + width: 100%; + } +} +</style> -- Gitblit v1.9.3