From 7aa0e0f68d2a3d1268a64e49ab47c0c046265e84 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期二, 20 五月 2025 11:48:23 +0800 Subject: [PATCH] 1.采购台账-开发联调 2.表格合计方法封装 --- src/views/procurementManagement/procurementLedger/index.vue | 107 +++---------- src/api/basicData/product.js | 11 + src/views/basicData/product/index.vue | 261 ++++++++++++++++++++++++++++++++ src/main.js | 2 src/views/procurementManagement/invoiceEntry/index.vue | 11 - src/utils/summarizeTable.js | 35 ++++ 6 files changed, 336 insertions(+), 91 deletions(-) diff --git a/src/api/basicData/product.js b/src/api/basicData/product.js new file mode 100644 index 0000000..b9260e6 --- /dev/null +++ b/src/api/basicData/product.js @@ -0,0 +1,11 @@ +// 浜у搧缁存姢椤甸潰鎺ュ彛 +import request from '@/utils/request' + +// 浜у搧鏍戞煡璇� +export function productTreeList(query) { + return request({ + url: '/basic/product/list', + method: 'get', + params: query + }) +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index 93b940f..65ae164 100644 --- a/src/main.js +++ b/src/main.js @@ -46,6 +46,7 @@ import PIMTable from "@/components/PIMTable/PIMTable.vue"; import { getToken } from "@/utils/auth"; +import { summarizeTable } from "@/utils/summarizeTable.js"; const app = createApp(App) @@ -54,6 +55,7 @@ app.config.globalProperties.download = download app.config.globalProperties.parseTime = parseTime app.config.globalProperties.resetForm = resetForm +app.config.globalProperties.summarizeTable = summarizeTable app.config.globalProperties.handleTree = handleTree app.config.globalProperties.addDateRange = addDateRange app.config.globalProperties.selectDictLabel = selectDictLabel diff --git a/src/utils/summarizeTable.js b/src/utils/summarizeTable.js new file mode 100644 index 0000000..6013def --- /dev/null +++ b/src/utils/summarizeTable.js @@ -0,0 +1,35 @@ +/** + * 閫氱敤鐨勮〃鏍煎悎璁℃柟娉� + * @param {Object} param + * @param {Array} param.columns 琛ㄦ牸鍒楅厤缃� + * @param {Array} param.data 鏁版嵁婧� + * @param {Array<string>} summaryProps 闇�瑕佹眹鎬荤殑瀛楁鍚嶆暟缁� + * @returns {Array} 鍚堣琛屾暟鎹� + */ +const summarizeTable = (param, summaryProps) => { + const { columns, data } = param; + const sums = []; + columns.forEach((column, index) => { + if (index === 0) { + sums[index] = '鍚堣'; + return; + } + const prop = column.property; + if (summaryProps.includes(prop)) { + const values = data.map(item => Number(item[prop])); + // 鍙鏈夋晥鏁板瓧杩涜姹傚拰 + if (!values.every(isNaN)) { + const sum = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0); + sums[index] = parseFloat(sum).toFixed(2); + } else { + sums[index] = ''; + } + } else { + sums[index] = ''; + } + }); + return sums; +}; + +// 瀵煎嚭鍑芥暟渚涘叾浠栨枃浠朵娇鐢� +export { summarizeTable }; \ No newline at end of file diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue new file mode 100644 index 0000000..0275185 --- /dev/null +++ b/src/views/basicData/product/index.vue @@ -0,0 +1,261 @@ +<template> + <div class="app-container product-view"> + <div class="left"> + <div> + <el-input + v-model="search" + style="width: 240px" + placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�" + @change="searchFilter" + @clear="searchFilter" + clearable + prefix-icon="Search" + /> + <el-button type="primary" @click="openProDia('add')" style="margin-left: 10px">鏂板浜у搧</el-button> + </div> + <div> + <el-tree ref="tree" v-loading="treeLoad" :data="list" + :default-expanded-keys="expandedKeys" :draggable="true" :filter-node-method="filterNode" + :props="{ children: 'children', label: 'label' }" highlight-current node-key="label" + style="height: calc(100vh - 190px);overflow-y: scroll;scrollbar-width: none;"> + <template #default="{ node, data }"> + <div class="custom-tree-node"> + <span>{{ node.label }}</span> + <div> + <el-button type="primary" link @click="openProDia('edit', data)"> + 缂栬緫 + </el-button> + <!-- 淇敼姝ゅ --> + <el-button + v-if="!node.childNodes.length" + style="margin-left: 4px" + type="danger" + link + @click="remove(node, data)" + > + 鍒犻櫎 + </el-button> + </div> + </div> + </template> + </el-tree> + </div> + </div> + <div class="right"> + <div style="margin-bottom: 10px"> + <el-button type="primary" @click="modelDia = true">鏂板瑙勬牸鍨嬪彿</el-button> + <el-button type="danger" @click="handleDelete" style="margin-left: 10px" plain>鍒犻櫎</el-button> + </div> + <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" :handleSelectionChange="handleSelectionChange" + :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable> + </div> + <el-dialog :visible.sync="productDia" title="浜у搧" width="400px"> + <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> + <el-row :gutter="30"> + <el-col :span="24"> + <el-form-item label="浜у搧鍚嶇О锛�" prop="productName"> + <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" clearable/> + </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="closeProDia">鍙栨秷</el-button> + </div> + </template> + </el-dialog> + </div> +</template> + +<script setup> +import {ref} from "vue"; +import {listCustomer} from "@/api/basicData/customerFile.js"; +import {ElMessageBox} from "element-plus"; +import {productTreeList} from "@/api/basicData/product.js"; +const { proxy } = getCurrentInstance() + +const search = ref('') +const treeLoad = ref(false) +const list = ref([]) +const expandedKeys = ref([]) +const tableColumn = ref([ + { + label: '瑙勬牸鍨嬪彿', + prop: 'model', + }, + { + label: '鍗曚綅', + prop: 'model', + }, + { + dataType: "action", + label: "鎿嶄綔", + align: 'center', + operation: [ + { + name: "缂栬緫", + type: "text", + clickFun: (row) => { + openForm('edit', row); + }, + }, + ], + }, +]) +const tableData = ref([]) +const tableLoading = ref(false) +const total = ref(0) +const selectedRows = ref([]) +const page = reactive({ + current: 1, + size: 10, +}) +const productDia = ref(false) +const modelDia = ref(false) +const data = reactive({ + form: { + productName: '', + }, + rules: { + productName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }], + } +}) +const { form, rules } = toRefs(data) +const getProductTreeList = () => { + treeLoad.value = true; + productTreeList().then(res => { + list.value = res + list.value.forEach((a) => { + expandedKeys.value.push(a.label); + }); + treeLoad.value = false; + }).catch(err => { + treeLoad.value = false; + }) +} +const searchFilter = () => { + proxy.$refs.tree.filter(search.value); +} +const openProDia = (type, data) => { + productDia.value = true + console.log('openEditDia', data) +} +const submitForm = () => { +} +const closeProDia = () => { + proxy.$refs.formRef.resetFields(); + productDia.value = false; +} +const remove = (value) => { + +} +// 琛ㄦ牸閫夋嫨鏁版嵁 +const handleSelectionChange = (selection) => { + selectedRows.value = selection +} +// 鍒犻櫎 +const handleDelete = () => { + let ids = [] + if (selectedRows.value.length > 0) { + ids = selectedRows.value.map(item => item.id); + } else { + proxy.$modal.msgWarning('璇烽�夋嫨鏁版嵁') + return + } + ElMessageBox.confirm( + '閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�', + '鍒犻櫎鎻愮ず', { + confirmButtonText: '纭', + cancelButtonText: '鍙栨秷', + type: 'warning', + } + ).then(() => { + tableLoading.value = true + delCustomer(ids).then(res => { + proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛") + getList() + }).finally(() => { + tableLoading.value = false + }) + }).catch(() => { + proxy.$modal.msg("宸插彇娑�") + }) +} +// 鏌ヨ瑙勬牸鍨嬪彿 +const pagination = ({ current, limit }) => { + page.current = current; + page.size = limit; + getList() +} +const getList = () => { + tableLoading.value = true + listCustomer({...searchForm.value, ...page}).then(res => { + tableLoading.value = false + tableData.value = res.rows + total.value = res.total + }) +} +// 璋冪敤tree杩囨护鏂规硶 涓枃鑻辫繃婊� +const filterNode = (value, data, node) => { + if (!value) {銆�銆�銆�銆�//濡傛灉鏁版嵁涓虹┖锛屽垯杩斿洖true,鏄剧ず鎵�鏈夌殑鏁版嵁椤� + return true + } + // 鏌ヨ鍒楄〃鏄惁鏈夊尮閰嶆暟鎹紝灏嗗�煎皬鍐欙紝鍖归厤鑻辨枃鏁版嵁 + let val = value.toLowerCase() + return chooseNode(val, data, node) // 璋冪敤杩囨护浜屽眰鏂规硶 +} +// 杩囨护鐖惰妭鐐� / 瀛愯妭鐐� (濡傛灉杈撳叆鐨勫弬鏁版槸鐖惰妭鐐逛笖鑳藉尮閰嶏紝鍒欒繑鍥炶鑺傜偣浠ュ強鍏朵笅鐨勬墍鏈夊瓙鑺傜偣锛涘鏋滃弬鏁版槸瀛愯妭鐐癸紝鍒欒繑鍥炶鑺傜偣鐨勭埗鑺傜偣銆俷ame鏄腑鏂囧瓧绗︼紝enName鏄嫳鏂囧瓧绗�. +const chooseNode = (value, data, node) => { + if (data.label.indexOf(value) !== -1) { + return true + } + const level = node.level + // 濡傛灉浼犲叆鐨勮妭鐐规湰韬氨鏄竴绾ц妭鐐瑰氨涓嶇敤鏍¢獙浜� + if (level === 1) { + return false + } + // 鍏堝彇褰撳墠鑺傜偣鐨勭埗鑺傜偣 + let parentData = node.parent + // 閬嶅巻褰撳墠鑺傜偣鐨勭埗鑺傜偣 + let index = 0 + while (index < level - 1) { + // 濡傛灉鍖归厤鍒扮洿鎺ヨ繑鍥烇紝姝ゅname鍊兼槸涓枃瀛楃锛宔nName鏄嫳鏂囧瓧绗︺�傚垽鏂尮閰嶄腑鑻辨枃杩囨护 + if (parentData.data.label.indexOf(value) !== -1) { + return true + } + // 鍚﹀垯鐨勮瘽鍐嶅線涓婁竴灞傚仛鍖归厤 + parentData = parentData.parent + index++ + } + // 娌″尮閰嶅埌杩斿洖false + return false +} +getProductTreeList() +</script> + +<style scoped> +.product-view { + display: flex; +} +.left { + width: 380px; + padding: 16px; + background: #ffffff; +} +.right { + width: calc(100% - 380px); + padding: 16px; + margin-left: 20px; + background: #ffffff; +} +.custom-tree-node { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + padding-right: 8px; +} +</style> \ No newline at end of file diff --git a/src/views/procurementManagement/invoiceEntry/index.vue b/src/views/procurementManagement/invoiceEntry/index.vue index 2218d4b..bebd18d 100644 --- a/src/views/procurementManagement/invoiceEntry/index.vue +++ b/src/views/procurementManagement/invoiceEntry/index.vue @@ -54,7 +54,6 @@ <el-table-column label="閲囪喘鍚堝悓鍙�" prop="purchaseContractNumber" show-overflow-tooltip/> <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip/> <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" show-overflow-tooltip/> - <el-table-column label="涓氬姟鍛�" prop="businessPerson" show-overflow-tooltip/> <el-table-column label="椤圭洰鍚嶇О" prop="projectName" show-overflow-tooltip/> <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" show-overflow-tooltip/> <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center"> @@ -91,15 +90,6 @@ <el-col :span="12"> <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName"> <el-input v-model="form.projectName" placeholder="鑷姩濉厖" clearable disabled/> - </el-form-item> - </el-col> - </el-row> - <el-row :gutter="30"> - <el-col :span="12"> - <el-form-item label="涓氬姟鍛橈細" prop="businessPersonId"> - <el-select v-model="form.businessPersonId" placeholder="鑷姩濉厖" clearable disabled> - <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"/> - </el-select> </el-form-item> </el-col> </el-row> @@ -337,7 +327,6 @@ form.value.projectName = res.projectName productData.value = res.productData form.value.supplierName = res.supplierName - form.value.businessPersonId = res.businessPersonId }) } // 鎻愪氦琛ㄥ崟 diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue index 393d7aa..887f786 100644 --- a/src/views/procurementManagement/procurementLedger/index.vue +++ b/src/views/procurementManagement/procurementLedger/index.vue @@ -40,9 +40,9 @@ <el-table-column label="鍗曚綅" prop="unit" /> <el-table-column label="鏁伴噺" prop="quantity" /> <el-table-column label="绋庣巼(%)" prop="taxRate" /> - <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" /> - <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" /> - <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" /> + <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> + <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> + <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> </el-table> </template> </el-table-column> @@ -50,9 +50,8 @@ <el-table-column label="閲囪喘鍚堝悓鍙�" prop="purchaseContractNumber" show-overflow-tooltip/> <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip/> <el-table-column label="渚涘簲鍟嗗悕绉�" prop="supplierName" show-overflow-tooltip/> - <el-table-column label="涓氬姟鍛�" prop="businessPerson" show-overflow-tooltip/> <el-table-column label="椤圭洰鍚嶇О" prop="projectName" show-overflow-tooltip/> - <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" show-overflow-tooltip/> + <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" show-overflow-tooltip :formatter="formattedNumber"/> <el-table-column label="褰曞叆浜�" prop="recorderName" show-overflow-tooltip/> <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" show-overflow-tooltip/> <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center"> @@ -96,20 +95,6 @@ </el-row> <el-row :gutter="30"> <el-col :span="12"> - <el-form-item label="涓氬姟鍛橈細" prop="businessPersonId"> - <el-select v-model="form.businessPersonId" placeholder="璇烽�夋嫨" clearable @change="setPhone"> - <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"/> - </el-select> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item label="鐢佃瘽锛�" prop="phoneNumber"> - <el-input v-model="form.phoneNumber" placeholder="璇疯緭鍏�" clearable/> - </el-form-item> - </el-col> - </el-row> - <el-row :gutter="30"> - <el-col :span="12"> <el-form-item label="褰曞叆浜猴細" prop="recorderId"> <el-select v-model="form.recorderId" placeholder="璇烽�夋嫨" clearable disabled> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"/> @@ -137,7 +122,7 @@ <el-button plain type="danger" @click="deleteProduct">鍒犻櫎</el-button> </el-form-item> </el-row> - <el-table :data="productData" border @selection-change="productSelected"> + <el-table :data="productData" border @selection-change="productSelected" show-summary :summary-method="summarizeProTable"> <el-table-column align="center" type="selection" width="55" /> <el-table-column align="center" label="搴忓彿" type="index" width="60" /> <el-table-column label="浜у搧澶х被" prop="productCategory" /> @@ -145,12 +130,12 @@ <el-table-column label="鍗曚綅" prop="unit" /> <el-table-column label="鏁伴噺" prop="quantity" /> <el-table-column label="绋庣巼(%)" prop="taxRate" /> - <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" /> - <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" /> - <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" /> + <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber"/> + <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber"/> + <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber"/> <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center"> <template #default="scope"> - <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row);">缂栬緫</el-button> + <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row, scope.$index);">缂栬緫</el-button> </template> </el-table-column> </el-table> @@ -229,7 +214,7 @@ <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice"> - <el-input v-model="productForm.taxInclusiveUnitPrice" placeholder="璇疯緭鍏�" clearable/> + <el-input-number v-model="productForm.taxInclusiveUnitPrice" :precision="2" :step="0.1" clearable style="width: 100%"/> </el-form-item> </el-col> <el-col :span="12"> @@ -245,12 +230,12 @@ <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice"> - <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable/> + <el-input-number v-model="productForm.taxInclusiveTotalPrice" :precision="2" :step="0.1" clearable style="width: 100%"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice"> - <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable/> + <el-input-number v-model="productForm.taxExclusiveTotalPrice" :precision="2" :step="0.1" clearable style="width: 100%"/> </el-form-item> </el-col> </el-row> @@ -325,8 +310,6 @@ recorderId: '', entryDate: '', productData: [], - businessPersonId: '', - phoneNumber: '', supplierName: '', supplierId: '', }, @@ -334,8 +317,6 @@ purchaseContractNumber: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }], salesLedgerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }], projectName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }], - businessPersonId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }], - phoneNumber: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }], supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }], } }) @@ -343,6 +324,7 @@ // 浜у搧琛ㄥ崟寮规鏁版嵁 const productFormVisible = ref(false) const productOperationType = ref('') +const productOperationIndex = ref('') const currentId = ref('') const productFormData = reactive({ productForm: { @@ -376,7 +358,9 @@ headers: { Authorization: "Bearer " + getToken() }, }) - +const formattedNumber = (row, column, cellValue) => { + return parseFloat(cellValue).toFixed(2); +}; // 鏌ヨ鍒楄〃 /** 鎼滅储鎸夐挳鎿嶄綔 */ const handleQuery = () => { @@ -431,50 +415,12 @@ } // 涓昏〃鍚堣鏂规硶 const summarizeMainTable = (param) => { - const { columns, data } = param; - const sums = []; - columns.forEach((column, index) => { - if (index === 0) { - sums[index] = '鍚堣'; - return; - } - const prop = column.property; - if (['contractAmount'].includes(prop)) { - const values = data.map(item => Number(item[prop])); - if (!values.every(value => isNaN(value))) { - sums[index] = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0); - } else { - sums[index] = ''; - } - } else { - sums[index] = ''; - } - }) - return sums; + return proxy.summarizeTable(param, ['contractAmount']); }; // 瀛愯〃鍚堣鏂规硶 -const summarizeChildrenTable = (param) => { - const { columns, data } = param; - const sums = []; - columns.forEach((column, index) => { - if (index === 0) { - sums[index] = '鍚堣'; - return; - } - const prop = column.property; - if (['taxInclusiveUnitPrice', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice'].includes(prop)) { - const values = data.map(item => Number(item[prop])); - if (!values.every(value => isNaN(value))) { - sums[index] = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0); - } else { - sums[index] = ''; - } - } else { - sums[index] = ''; - } - }); - return sums; -} +const summarizeProTable = (param) => { + return proxy.summarizeTable(param, ['taxInclusiveUnitPrice', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']); +}; // 鎵撳紑寮规 const openForm = (type, row) => { operationType.value = type @@ -505,10 +451,6 @@ }) } dialogFormVisible.value = true -} -// 璧嬪�肩數璇� -const setPhone = (id) => { - form.value.phoneNumber = userList.value.find(u => u.userId === id)?.phonenumber || ''; } // 涓婁紶鍓嶆牎妫� function handleBeforeUpload(file) { @@ -577,8 +519,9 @@ dialogFormVisible.value = false } // 鎵撳紑浜у搧寮规 -const openProductForm = (type, row) => { +const openProductForm = (type, row, index) => { productOperationType.value = type + productOperationIndex.value = index productForm.value = {} proxy.resetForm("productFormRef") if (type === 'edit') { @@ -593,7 +536,11 @@ if (operationType.value === "edit") { submitProductEdit() } else { - productData.value.push({...productForm.value}) + if (productOperationType.value === 'add') { + productData.value.push({...productForm.value}) + } else { + productData.value[productOperationIndex.value] = {...productForm.value} + } closeProductDia() } } -- Gitblit v1.9.3