From a2971bb8f3be26eb30302bcf4de07e12e912700c Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期四, 21 八月 2025 11:10:41 +0800
Subject: [PATCH] feat: 页面

---
 src/views/AgreementManage/AgreementManageList.vue                  |    2 
 src/hooks/useEvent.ts                                              |    1 
 src/views/ServiceChargeManage/ServiceChargeDetail.vue              |   23 +-
 src/views/ServiceChargeManage/ServiceChargeManage.vue              |  155 +++++++++++++-----
 src/views/ServiceChargeManage/components/SettleDetailDialog.vue    |   70 ++++++++
 src/views/ServiceChargeManage/components/UploadStatementDialog.vue |   99 ++++++++++++
 src/views/ServiceChargeManage/ServiceChargeSettle.vue              |  127 +++++++++------
 7 files changed, 370 insertions(+), 107 deletions(-)

diff --git a/src/hooks/useEvent.ts b/src/hooks/useEvent.ts
index f897656..b462cd4 100644
--- a/src/hooks/useEvent.ts
+++ b/src/hooks/useEvent.ts
@@ -6,6 +6,7 @@
   'taskManage:add': any;
   'taskManage:edit': any;
   checkReceiveTask: any;
+  serviceChargeSettle: any;
 };
 
 export type GlobalEventListener<T extends keyof GlobalEvent> = (payload: GlobalEvent[T]) => any;
diff --git a/src/views/AgreementManage/AgreementManageList.vue b/src/views/AgreementManage/AgreementManageList.vue
index c812998..cf0dfff 100644
--- a/src/views/AgreementManage/AgreementManageList.vue
+++ b/src/views/AgreementManage/AgreementManageList.vue
@@ -156,7 +156,7 @@
       time: [] as unknown as ModelValueType,
       orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
     },
-    queryKey: ['flexEnterpriseServices/getFlexEnterpriseList'],
+    queryKey: ['taskServices/getTaskInfos'],
     columnsRenderProps: {},
   }
 );
diff --git a/src/views/ServiceChargeManage/ServiceChargeDetail.vue b/src/views/ServiceChargeManage/ServiceChargeDetail.vue
index 97cf434..f73a96f 100644
--- a/src/views/ServiceChargeManage/ServiceChargeDetail.vue
+++ b/src/views/ServiceChargeManage/ServiceChargeDetail.vue
@@ -85,7 +85,7 @@
           <template #query>
             <QueryFilterItem>
               <SearchInput
-                v-model="extraParamState.searchWord"
+                v-model="extraParamState.keywords"
                 style="width: 300px"
                 placeholder="浜哄憳濮撳悕/韬唤璇佸彿/鎵嬫満鍙�"
                 @on-click-search="getList"
@@ -134,6 +134,7 @@
 import { SettlementListColumns } from './constants';
 import { useQuery } from '@tanstack/vue-query';
 import { downloadFileByUrl } from '@bole-core/core';
+import * as taskServices from '@/services/api/task';
 
 defineOptions({
   name: 'ServiceChargeDetail',
@@ -158,17 +159,19 @@
 });
 
 const { isLoading } = useQuery({
-  queryKey: ['flexTaskServices/getFlexTaskDetail', id],
+  queryKey: ['taskServices/getTaskInfo', id],
   queryFn: async () => {
-    return await flexTaskServices.getFlexTaskDetail(
+    return await taskServices.getTaskInfo(
       { id: id },
       {
         showLoading: false,
       }
     );
   },
-  placeholderData: () => ({} as API.GetFlexTaskDetailForBackOutput),
-  onSuccess(data) {},
+  placeholderData: () => ({} as API.GetTaskInfoQueryResult),
+  onSuccess(data) {
+    form.name = data.name;
+  },
   enabled: !!id,
 });
 
@@ -181,16 +184,16 @@
 } = useTable(
   async ({ pageIndex, pageSize }, extraParamState) => {
     try {
-      let params: API.GetFlexEnterpriseInput = {
+      let params: API.GetOpenTaskInfosQuery = {
         pageModel: {
           rows: pageSize,
           page: pageIndex,
           orderInput: extraParamState.orderInput,
         },
-        searchWord: extraParamState.searchWord,
+        keywords: extraParamState.keywords,
       };
 
-      let res = await flexEnterpriseServices.getFlexEnterpriseList(params);
+      let res = await taskServices.getOpenTaskInfos(params);
       return res;
     } catch (error) {
       console.log('error: ', error);
@@ -198,10 +201,10 @@
   },
   {
     defaultExtraParams: {
-      searchWord: '',
+      keywords: '',
       orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
     },
-    queryKey: ['flexEnterpriseServices/getFlexEnterpriseList'],
+    queryKey: ['taskServices/getOpenTaskInfos'],
     columnsRenderProps: {},
   }
 );
diff --git a/src/views/ServiceChargeManage/ServiceChargeManage.vue b/src/views/ServiceChargeManage/ServiceChargeManage.vue
index d9cbb15..bd7fa87 100644
--- a/src/views/ServiceChargeManage/ServiceChargeManage.vue
+++ b/src/views/ServiceChargeManage/ServiceChargeManage.vue
@@ -5,7 +5,7 @@
         <template #query>
           <QueryFilterItem tip-content="缁撶畻鍗曠姸鎬�">
             <FieldRadio
-              v-model="extraParamState.flexEnterpriseSettingStatus"
+              v-model="extraParamState.status"
               :value-enum="[
                 { label: '宸插畨鎺�', value: 1 },
                 { label: '寰呭畨鎺�', value: 0 },
@@ -17,7 +17,7 @@
           </QueryFilterItem>
           <QueryFilterItem tip-content="缁撶畻鐘舵��">
             <FieldRadio
-              v-model="extraParamState.flexEnterpriseSettingStatus"
+              v-model="extraParamState.status"
               :value-enum="[
                 { label: '宸插畨鎺�', value: 1 },
                 { label: '寰呭畨鎺�', value: 0 },
@@ -29,7 +29,7 @@
           </QueryFilterItem>
           <QueryFilterItem>
             <FieldDatePicker
-              v-model="extraParamState.flexEnterpriseSettingStatus"
+              v-model="extraParamState.time"
               type="daterange"
               range-separator="~"
               start-placeholder="璧峰鏃ユ湡"
@@ -52,18 +52,8 @@
         </template>
         <template #btn>
           <el-button type="primary" link @click="handleDownloadTemplate()">缁撶畻鍗曟ā鏉�</el-button>
-          <BlFileUpload
-            :limitFileSize="10"
-            accept="xls,xlsx"
-            :showTip="false"
-            :show-file-list="false"
-            :on-success="handleUploadSuccess"
-            style="margin-right: 10px; margin-left: 10px"
-          >
-            <template #default>
-              <el-button type="primary">涓婁紶缁撶畻鍗�</el-button>
-            </template>
-          </BlFileUpload>
+
+          <el-button type="primary" @click="openDialog()">涓婁紶缁撶畻鍗�</el-button>
           <el-button type="primary" @click="handleDownloadTemplate()">瀵煎嚭</el-button>
         </template>
       </ProTableQueryFilterBar>
@@ -72,23 +62,10 @@
         :columns="ServiceChargeManageColumns"
         :operationBtns="operationBtns"
       >
-        <template #operationBtn-uploadBtn="{ data, row }">
-          <BlFileUpload
-            v-model:file-url="row.fileUrl"
-            :limitFileSize="2"
-            :limit="1"
-            accept="doc,docx"
-            ref="uploadRef"
-            :showTip="false"
-            :on-success="(response) => handleUpload(response, row)"
-            :show-file-list="false"
-            class="pro-table-operation-btn upload-style-btn"
-          >
-            <el-button link type="primary">涓婁紶</el-button>
-          </BlFileUpload>
-        </template>
       </ProTableV2>
     </AppContainer>
+    <UploadStatementDialog v-bind="dialogProps" />
+    <SettleDetailDialog v-bind="dialogSettleProps" />
   </LoadingLayout>
 </template>
 
@@ -104,12 +81,15 @@
   FieldDatePicker,
   FieldRadio,
   defineOperationBtns,
-  BlFileUpload,
+  useFormDialog,
   UploadUserFile,
 } from '@bole-core/components';
 import { ServiceChargeManageColumns } from './constants';
-import { EnumUserGender } from '@/constants';
 import { downloadFileByUrl } from '@/utils';
+import * as taskServices from '@/services/api/task';
+import { ModelValueType } from 'element-plus';
+import UploadStatementDialog from './components/UploadStatementDialog.vue';
+import SettleDetailDialog from './components/SettleDetailDialog.vue';
 
 defineOptions({
   name: 'ServiceChargeManageList',
@@ -121,6 +101,24 @@
       enCode: 'uploadBtn',
       name: '涓婁紶',
     },
+    emits: {
+      onClick: (role) => openDialog(role),
+    },
+    extraProps: {
+      hide: () => false,
+    },
+  },
+  {
+    data: {
+      enCode: 'reUploadBtn',
+      name: '閲嶆柊涓婁紶',
+    },
+    emits: {
+      onClick: (role) => openDialog(role),
+    },
+    extraProps: {
+      hide: () => false,
+    },
   },
   {
     data: {
@@ -128,7 +126,22 @@
       name: '缁撶畻',
     },
     emits: {
-      onClick: (role) => goSettle(role),
+      onClick: (role) => openSettleDialog(role),
+    },
+    extraProps: {
+      hide: () => false,
+    },
+  },
+  {
+    data: {
+      enCode: 'recallBtn',
+      name: '鎾ゅ洖',
+    },
+    emits: {
+      onClick: (role) => handleRecall(role),
+    },
+    extraProps: {
+      hide: () => false,
     },
   },
   {
@@ -148,10 +161,19 @@
     emits: {
       onClick: (role) => handleExport(role),
     },
+    extraProps: {
+      hide: () => false,
+    },
   },
 ]);
 
 const router = useRouter();
+
+const eventContext = useGlobalEventContext();
+
+eventContext.addEvent('serviceChargeSettle', () => {
+  getList(paginationState.pageIndex);
+});
 
 const BaseState = {
   loading: true,
@@ -173,17 +195,15 @@
 } = useTable(
   async ({ pageIndex, pageSize }, extraParamState) => {
     try {
-      let params: API.GetFlexEnterpriseInput = {
+      let params: API.GetTaskInfosQuery = {
         pageModel: {
           rows: pageSize,
           page: pageIndex,
           orderInput: extraParamState.orderInput,
         },
-        flexEnterpriseSettingStatus: extraParamState.flexEnterpriseSettingStatus,
-        searchWord: extraParamState.searchWord,
       };
 
-      let res = await flexEnterpriseServices.getFlexEnterpriseList(params, {
+      let res = await taskServices.getTaskInfos(params, {
         showLoading: !state.loading,
       });
       return res;
@@ -194,22 +214,69 @@
   {
     defaultExtraParams: {
       searchWord: '',
+      status: 0,
+      time: [] as unknown as ModelValueType,
       orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
-      flexEnterpriseSettingStatus: '' as any as FlexEnterpriseSettingStatus,
     },
-    queryKey: ['flexEnterpriseServices/getFlexEnterpriseList'],
+    queryKey: ['taskServices/getTaskInfos'],
     columnsRenderProps: {},
   }
 );
 
-function goSettle(row) {
+const { dialogProps, handleAdd, handleEdit, editForm } = useFormDialog({
+  onConfirm: handleAddOrEdit,
+  defaultFormParams: {
+    id: '',
+    name: '',
+    settlementUrl: [] as UploadUserFile[],
+  },
+});
+
+function openDialog(row?) {
+  if (row) {
+    handleEdit({
+      id: row?.id,
+      name: row?.name,
+      settlementUrl: [] as UploadUserFile[],
+    });
+  } else {
+    handleAdd();
+  }
+}
+
+async function handleAddOrEdit() {}
+
+const {
+  dialogProps: dialogSettleProps,
+  handleEdit: handleSettleEdit,
+  editForm: settleEditForm,
+} = useFormDialog({
+  onConfirm: goSettle,
+  defaultFormParams: {
+    id: '',
+    name: '',
+    count: 0,
+  },
+});
+
+function openSettleDialog(row?) {
+  handleSettleEdit({
+    id: row.id,
+    name: row.name,
+    count: row.count,
+  });
+}
+
+async function goSettle() {
   router.push({
     name: 'ServiceChargeSettle',
     params: {
-      id: row.id,
+      id: settleEditForm.id,
     },
   });
 }
+
+function handleRecall(row) {}
 
 function goDetail(row) {
   router.push({
@@ -218,12 +285,6 @@
       id: row.id,
     },
   });
-}
-
-function handleUploadSuccess(response: UploadUserFile) {}
-
-function handleUpload(val, row) {
-  console.log('val: ', val);
 }
 
 function handleExport(val) {
diff --git a/src/views/ServiceChargeManage/ServiceChargeSettle.vue b/src/views/ServiceChargeManage/ServiceChargeSettle.vue
index d48fdbf..bdfca37 100644
--- a/src/views/ServiceChargeManage/ServiceChargeSettle.vue
+++ b/src/views/ServiceChargeManage/ServiceChargeSettle.vue
@@ -29,47 +29,30 @@
         </ProForm>
       </ChunkCell>
       <ChunkCell title="鏀舵鏂逛俊鎭�">
-        <ProForm :model="form" ref="formRef" label-width="120px">
-          <ProFormItemV2
-            label="鏀舵鏂硅处鎴�:"
-            prop="name"
-            :check-rules="[{ message: '璇烽�夋嫨鏀舵鏂硅处鎴�' }]"
-          >
-            <ProFormRadio
-              v-model="form.name"
-              :valueEnum="[]"
-              placeholder="璇烽�夋嫨鏀舵鏂硅处鎴�"
-              clearable
-            >
-            </ProFormRadio>
-          </ProFormItemV2>
-          <ProFormMixinsItemContainer>
-            <ProFormItemV2
-              label="鏀舵鏂规埛鍚�:"
-              prop="name"
-              :check-rules="[{ message: '璇疯緭鍏ユ敹娆炬柟鎴峰悕' }]"
-              mode="read"
-            >
-              <ProFormText v-model="form.name"> </ProFormText>
-            </ProFormItemV2>
-            <ProFormItemV2
-              label="鏀舵鏂硅处鍙�:"
-              prop="name"
-              :check-rules="[{ message: '璇疯緭鍏ユ敹娆炬柟璐﹀彿' }]"
-              mode="read"
-            >
-              <ProFormText v-model="form.name"> </ProFormText>
-            </ProFormItemV2>
-            <ProFormItemV2
-              label="鏀舵鏂瑰紑鎴疯:"
-              prop="name"
-              :check-rules="[{ message: '璇疯緭鍏ユ敹娆惧紑鎴疯' }]"
-              mode="read"
-            >
-              <ProFormText v-model="form.name"> </ProFormText>
-            </ProFormItemV2>
-          </ProFormMixinsItemContainer>
-        </ProForm>
+        <ProTableQueryFilterBar @on-reset="reset">
+          <template #query>
+            <QueryFilterItem>
+              <SearchInput
+                v-model="extraParamState.keywords"
+                style="width: 300px"
+                placeholder="浜哄憳濮撳悕/韬唤璇佸彿/鎵嬫満鍙�"
+                @on-click-search="getList"
+              >
+              </SearchInput>
+            </QueryFilterItem>
+          </template>
+        </ProTableQueryFilterBar>
+        <ProTableV2
+          v-bind="proTableProps"
+          :columns="SettlementListColumns"
+          :show-operation-column="false"
+          :auto-height="false"
+          ref="proTable"
+          :tableProps="{
+            maxHeight: '400px',
+          }"
+        >
+        </ProTableV2>
       </ChunkCell>
       <ChunkCell title="杞处淇℃伅">
         <ProForm :model="form" ref="formRef" label-width="120px">
@@ -105,13 +88,19 @@
   ProFormText,
   ProFormSelect,
   ProFormInputNumber,
-  ProFormRadio,
+  ProTableV2,
+  QueryFilterItem,
+  SearchInput,
+  ProTableQueryFilterBar,
   ProFormMixinsItemContainer,
+  useTable,
 } from '@bole-core/components';
 import { useQuery } from '@tanstack/vue-query';
 import { useRouteView } from '@/hooks';
 import { FormInstance } from 'element-plus';
 import { validateFormList } from '@/utils';
+import * as taskServices from '@/services/api/task';
+import { SettlementListColumns } from './constants';
 
 defineOptions({
   name: 'ServiceChargeSettle',
@@ -119,7 +108,7 @@
 
 const route = useRoute();
 const id = (route.params.id as string) ?? '';
-
+const eventContext = useGlobalEventContext();
 const { closeViewPush } = useRouteView();
 
 const form = reactive({
@@ -128,19 +117,55 @@
 });
 
 const { isLoading } = useQuery({
-  queryKey: ['flexTaskServices/getFlexTaskDetail', id],
+  queryKey: ['taskServices/getTaskInfo', id],
   queryFn: async () => {
-    return await flexTaskServices.getFlexTaskDetail(
+    return await taskServices.getTaskInfo(
       { id: id },
       {
         showLoading: false,
       }
     );
   },
-  placeholderData: () => ({} as API.GetFlexTaskDetailForBackOutput),
-  onSuccess(data) {},
+  placeholderData: () => ({} as API.GetTaskInfoQueryResult),
+  onSuccess(data) {
+    form.name = data.name;
+  },
   enabled: !!id,
 });
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetOpenTaskInfosQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        keywords: extraParamState.keywords,
+      };
+
+      let res = await taskServices.getOpenTaskInfos(params);
+      return res;
+    } catch (error) {
+      console.log('error: ', error);
+    }
+  },
+  {
+    defaultExtraParams: {
+      keywords: '',
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
+    },
+    queryKey: ['taskServices/getOpenTaskInfos'],
+    columnsRenderProps: {},
+  }
+);
 
 function handleBack() {
   closeViewPush(route, {
@@ -152,12 +177,16 @@
   try {
     const valid = await validateFormList([formRef.value]);
     if (valid) {
-      //
+      submit();
     }
   } catch (error) {}
 }
 
-onMounted(() => {});
+async function submit() {
+  try {
+    eventContext.emit('serviceChargeSettle');
+  } catch (error) {}
+}
 </script>
 
 <style lang="scss" scoped>
diff --git a/src/views/ServiceChargeManage/components/SettleDetailDialog.vue b/src/views/ServiceChargeManage/components/SettleDetailDialog.vue
new file mode 100644
index 0000000..189905a
--- /dev/null
+++ b/src/views/ServiceChargeManage/components/SettleDetailDialog.vue
@@ -0,0 +1,70 @@
+<template>
+  <ProDialog
+    title="缁撶畻纭"
+    v-model="visible"
+    @close="onDialogClose"
+    destroy-on-close
+    draggable
+    :width="700"
+  >
+    <ProForm :model="form" ref="dialogForm" label-width="120px" is-read>
+      <ProFormItemV2 label="浠诲姟鍗曞彿锛�" prop="name">
+        <ProFormSelect v-model="form.name" :valueEnum="[]"> </ProFormSelect>
+      </ProFormItemV2>
+      <ProFormItemV2 label="浠诲姟鍚嶇О锛�" prop="name">
+        <ProFormText v-model.trim="form.name"></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2 label="缁撶畻浜烘暟锛�" prop="count">
+        <ProFormInputNumber v-model="form.count" unit="浜�"> </ProFormInputNumber>
+      </ProFormItemV2>
+      <ProFormItemV2 label="缁撶畻閲戦锛�" prop="count">
+        <ProFormInputNumber v-model="form.count" unit="鍏�"> </ProFormInputNumber>
+      </ProFormItemV2>
+    </ProForm>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="emit('onCancel')">鍙栨秷</el-button>
+        <el-button type="primary" @click="emit('onConfirm')">纭</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { FormInstance } from 'element-plus';
+import {
+  ProDialog,
+  ProForm,
+  ProFormItemV2,
+  ProFormText,
+  ProFormSelect,
+  ProFormInputNumber,
+} from '@bole-core/components';
+
+defineOptions({
+  name: 'SettleDetailDialog',
+});
+
+type Form = {
+  title?: string;
+  id: string;
+  name: string;
+  count: number;
+};
+
+const visible = defineModel({ type: Boolean });
+
+const form = defineModel<Form>('form');
+
+const emit = defineEmits<{
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+function onDialogClose() {
+  if (!dialogForm.value) return;
+  dialogForm.value.resetFields();
+}
+</script>
diff --git a/src/views/ServiceChargeManage/components/UploadStatementDialog.vue b/src/views/ServiceChargeManage/components/UploadStatementDialog.vue
new file mode 100644
index 0000000..451b4fc
--- /dev/null
+++ b/src/views/ServiceChargeManage/components/UploadStatementDialog.vue
@@ -0,0 +1,99 @@
+<template>
+  <ProDialog
+    title="涓婁紶缁撶畻鍗�"
+    v-model="visible"
+    @close="onDialogClose"
+    destroy-on-close
+    draggable
+    :width="700"
+  >
+    <ProForm :model="form" ref="dialogForm" label-width="120px">
+      <ProFormItemV2 label="浠诲姟鍗曞彿锛�" prop="name" :check-rules="[{ message: '璇烽�夋嫨浠诲姟鍗曞彿' }]">
+        <ProFormSelect
+          v-model="form.name"
+          :valueEnum="[]"
+          placeholder="璇烽�夋嫨浠诲姟鍗曞彿"
+          filterable
+          clearable
+        >
+        </ProFormSelect>
+      </ProFormItemV2>
+      <ProFormItemV2 label="浠诲姟鍚嶇О锛�" prop="name" :check-rules="[{ message: '璇疯緭鍏ヤ换鍔″悕绉�' }]">
+        <ProFormText
+          style="width: 50%"
+          placeholder="璇疯緭鍏ヤ换鍔″悕绉�"
+          v-model.trim="form.name"
+        ></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2
+        label="涓婁紶缁撶畻鍗曪細"
+        prop="settlementUrl"
+        :check-rules="[{ message: '璇蜂笂浼犵粨绠楀崟', type: 'upload' }]"
+      >
+        <ProFormUpload
+          v-model:file-url="form.settlementUrl"
+          :limit="1"
+          :limitFileSize="10"
+          accept="jpg/jpeg,png,pdf"
+        ></ProFormUpload>
+      </ProFormItemV2>
+    </ProForm>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="emit('onCancel')">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleConfirm">纭</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { FormInstance } from 'element-plus';
+import {
+  ProDialog,
+  ProForm,
+  ProFormItemV2,
+  ProFormText,
+  ProFormUpload,
+  ProFormSelect,
+  UploadUserFile,
+} from '@bole-core/components';
+
+defineOptions({
+  name: 'UploadStatementDialog',
+});
+
+type Form = {
+  title?: string;
+  id: string;
+  name: string;
+  settlementUrl: UploadUserFile[];
+};
+
+const visible = defineModel({ type: Boolean });
+
+const form = defineModel<Form>('form');
+
+const emit = defineEmits<{
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+function onDialogClose() {
+  if (!dialogForm.value) return;
+  dialogForm.value.resetFields();
+}
+
+function handleConfirm() {
+  if (!dialogForm.value) return;
+  dialogForm.value.validate((valid) => {
+    if (valid) {
+      emit('onConfirm');
+    } else {
+      return;
+    }
+  });
+}
+</script>

--
Gitblit v1.9.1