From 2dcae4165bca6ad5df074afe4c7cf14bc8369db7 Mon Sep 17 00:00:00 2001
From: b2894lxlx <517289602@qq.com>
Date: Mon, 20 Jul 2026 11:56:02 +0800
Subject: [PATCH] 260720
---
.gitignore | 6 +
App.vue | 33 +
components/common-hero/common-hero.vue | 195 ++
components/u-input/u-input.vue | 112 ++
index.html | 20 +
main.js | 27 +
manifest.json | 72 +
packageMine/declare.vue | 373 ++++
packageMine/manuscripts.vue | 441 +++++
packageMine/profile.vue | 932 +++++++++
packageMine/qingma.vue | 362 ++++
pages.json | 237 +++
pages/activity-outline/index.vue | 881 +++++++++
pages/activity-outline/service.js | 17 +
pages/assistant/chat-service.js | 447 +++++
pages/assistant/index.vue | 1725 +++++++++++++++++
pages/creative-assistant/index.vue | 1038 ++++++++++
pages/creative-assistant/service.js | 45 +
pages/gxmu/config.js | 395 ++++
pages/gxmu/cross-school-board.vue | 886 +++++++++
pages/gxmu/declare-service.js | 10 +
pages/gxmu/form.vue | 892 +++++++++
pages/gxmu/index.vue | 697 +++++++
pages/gxmu/module-form-service.js | 212 ++
pages/gxmu/qmgc.vue | 432 +++++
pages/gxmu/review-list.vue | 1297 +++++++++++++
pages/gxmu/stats-service.js | 10 +
pages/gxmu/stats.vue | 735 +++++++
pages/gxmu/tzb-database-service.js | 19 +
pages/gxmu/tzb-database.vue | 205 ++
pages/gxmu/tzb-project-list.vue | 661 +++++++
pages/gxmu/tzb-talent-list.vue | 680 +++++++
pages/gxmu/tzbcy.vue | 787 ++++++++
pages/gxmu/wxxzx.vue | 192 ++
pages/index/index.vue | 568 ++++++
pages/login/index.vue | 298 +++
pages/login/service.js | 21 +
pages/manuscript/index.vue | 1112 +++++++++++
pages/manuscript/service.js | 52 +
pages/mine/declare.vue | 355 ++++
pages/mine/index.vue | 501 +++++
pages/mine/manuscripts.vue | 422 ++++
pages/mine/profile.vue | 566 ++++++
pages/mine/qingma.vue | 344 ++++
pages/mine/service.js | 187 ++
pages/tygl/index.vue | 1260 ++++++++++++
pages/tygl/service.js | 47 +
static/indexBg.jpg | Bin 0 -> 3701 bytes
static/logo.png | Bin 0 -> 4023 bytes
static/swiper.jpg | Bin 0 -> 362986 bytes
static/tabbar/chat-active.png | Bin 0 -> 16019 bytes
static/tabbar/chat.png | Bin 0 -> 21822 bytes
static/tabbar/home-active.png | Bin 0 -> 8857 bytes
static/tabbar/home.png | Bin 0 -> 16544 bytes
static/tabbar/user-active.png | Bin 0 -> 11052 bytes
static/tabbar/user.png | Bin 0 -> 18038 bytes
uni.promisify.adaptor.js | 13 +
uni.scss | 78 +
uni_modules/uv-icon/changelog.md | 31 +
.../uv-icon/components/uv-icon/icons.js | 160 ++
.../uv-icon/components/uv-icon/props.js | 90 +
.../uv-icon/components/uv-icon/uv-icon.vue | 226 +++
.../uv-icon/components/uv-icon/uvicons.ttf | Bin 0 -> 39632 bytes
uni_modules/uv-icon/package.json | 83 +
uni_modules/uv-icon/readme.md | 15 +
uni_modules/uv-input/changelog.md | 29 +
.../uv-input/components/uv-input/props.js | 175 ++
.../uv-input/components/uv-input/uv-input.vue | 348 ++++
uni_modules/uv-input/package.json | 88 +
uni_modules/uv-input/readme.md | 19 +
uni_modules/uv-loading-icon/changelog.md | 9 +
.../components/uv-loading-icon/props.js | 67 +
.../uv-loading-icon/uv-loading-icon.vue | 347 ++++
uni_modules/uv-loading-icon/package.json | 87 +
uni_modules/uv-loading-icon/readme.md | 19 +
uni_modules/uv-overlay/changelog.md | 9 +
.../uv-overlay/components/uv-overlay/props.js | 25 +
.../components/uv-overlay/uv-overlay.vue | 85 +
uni_modules/uv-overlay/package.json | 88 +
uni_modules/uv-overlay/readme.md | 11 +
uni_modules/uv-picker/changelog.md | 33 +
.../uv-picker/components/uv-picker/props.js | 95 +
.../components/uv-picker/uv-picker.vue | 330 ++++
uni_modules/uv-picker/package.json | 90 +
uni_modules/uv-picker/readme.md | 21 +
uni_modules/uv-popup/changelog.md | 18 +
.../uv-popup/components/uv-popup/keypress.js | 45 +
.../uv-popup/components/uv-popup/uv-popup.vue | 539 +++++
uni_modules/uv-popup/package.json | 92 +
uni_modules/uv-popup/readme.md | 21 +
uni_modules/uv-safe-bottom/changelog.md | 11 +
.../uv-safe-bottom/uv-safe-bottom.vue | 67 +
uni_modules/uv-safe-bottom/package.json | 87 +
uni_modules/uv-safe-bottom/readme.md | 11 +
uni_modules/uv-status-bar/changelog.md | 7 +
.../components/uv-status-bar/props.js | 8 +
.../uv-status-bar/uv-status-bar.vue | 54 +
uni_modules/uv-status-bar/package.json | 87 +
uni_modules/uv-status-bar/readme.md | 10 +
uni_modules/uv-toolbar/changelog.md | 2 +
.../uv-toolbar/components/uv-toolbar/props.js | 40 +
.../components/uv-toolbar/uv-toolbar.vue | 109 ++
uni_modules/uv-toolbar/package.json | 87 +
uni_modules/uv-toolbar/readme.md | 31 +
uni_modules/uv-transition/changelog.md | 19 +
.../uv-transition/createAnimation.js | 131 ++
.../components/uv-transition/props.js | 31 +
.../uv-transition/uv-transition.vue | 320 +++
uni_modules/uv-transition/package.json | 87 +
uni_modules/uv-transition/readme.md | 15 +
uni_modules/uv-ui-tools/changelog.md | 76 +
.../components/uv-ui-tools/uv-ui-tools.vue | 6 +
uni_modules/uv-ui-tools/index.js | 79 +
uni_modules/uv-ui-tools/index.scss | 7 +
uni_modules/uv-ui-tools/libs/config/config.js | 34 +
uni_modules/uv-ui-tools/libs/css/color.scss | 32 +
uni_modules/uv-ui-tools/libs/css/common.scss | 100 +
.../uv-ui-tools/libs/css/components.scss | 23 +
.../uv-ui-tools/libs/css/variable.scss | 111 ++
uni_modules/uv-ui-tools/libs/css/vue.scss | 40 +
.../libs/function/colorGradient.js | 134 ++
.../uv-ui-tools/libs/function/debounce.js | 29 +
.../uv-ui-tools/libs/function/digit.js | 167 ++
.../uv-ui-tools/libs/function/index.js | 734 +++++++
.../uv-ui-tools/libs/function/platform.js | 75 +
uni_modules/uv-ui-tools/libs/function/test.js | 287 +++
.../uv-ui-tools/libs/function/throttle.js | 30 +
.../libs/luch-request/adapters/index.js | 132 ++
.../luch-request/core/InterceptorManager.js | 51 +
.../libs/luch-request/core/Request.js | 201 ++
.../libs/luch-request/core/buildFullPath.js | 20 +
.../libs/luch-request/core/defaults.js | 33 +
.../libs/luch-request/core/dispatchRequest.js | 6 +
.../libs/luch-request/core/mergeConfig.js | 126 ++
.../libs/luch-request/core/settle.js | 16 +
.../libs/luch-request/helpers/buildURL.js | 64 +
.../libs/luch-request/helpers/combineURLs.js | 14 +
.../luch-request/helpers/isAbsoluteURL.js | 14 +
.../uv-ui-tools/libs/luch-request/index.d.ts | 197 ++
.../uv-ui-tools/libs/luch-request/index.js | 2 +
.../uv-ui-tools/libs/luch-request/utils.js | 135 ++
.../libs/luch-request/utils/clone.js | 264 +++
uni_modules/uv-ui-tools/libs/mixin/button.js | 13 +
uni_modules/uv-ui-tools/libs/mixin/mixin.js | 172 ++
uni_modules/uv-ui-tools/libs/mixin/mpMixin.js | 8 +
uni_modules/uv-ui-tools/libs/mixin/mpShare.js | 13 +
.../uv-ui-tools/libs/mixin/openType.js | 47 +
uni_modules/uv-ui-tools/libs/mixin/touch.js | 59 +
uni_modules/uv-ui-tools/libs/util/dayjs.js | 216 +++
uni_modules/uv-ui-tools/libs/util/route.js | 126 ++
uni_modules/uv-ui-tools/package.json | 81 +
uni_modules/uv-ui-tools/readme.md | 23 +
uni_modules/uv-ui-tools/theme.scss | 43 +
uni_modules/uv-ui/changelog.md | 353 ++++
uni_modules/uv-ui/components/uv-ui/uv-ui.vue | 7 +
uni_modules/uv-ui/package.json | 162 ++
uni_modules/uv-ui/readme.md | 164 ++
uni_modules/zero-markdown-view/changelog.md | 15 +
.../components/mp-html/highlight/config.js | 5 +
.../components/mp-html/highlight/index.js | 109 ++
.../components/mp-html/highlight/prism.min.js | 7 +
.../components/mp-html/markdown/index.js | 34 +
.../components/mp-html/markdown/marked.min.js | 6 +
.../components/mp-html/mp-html.vue | 503 +++++
.../components/mp-html/node/node.vue | 678 +++++++
.../components/mp-html/parser.js | 1335 +++++++++++++
.../components/mp-html/style/index.js | 129 ++
.../components/mp-html/style/parser.js | 175 ++
.../zero-markdown-view/zero-markdown-view.vue | 177 ++
uni_modules/zero-markdown-view/package.json | 86 +
uni_modules/zero-markdown-view/readme.md | 134 ++
utils/gxmu/config.js | 395 ++++
utils/gxmu/declare-service.js | 10 +
utils/gxmu/review-list-service.js | 439 +++++
utils/markdown.js | 125 ++
utils/request.js | 139 ++
176 files changed, 34633 insertions(+)
create mode 100644 .gitignore
create mode 100644 App.vue
create mode 100644 components/common-hero/common-hero.vue
create mode 100644 components/u-input/u-input.vue
create mode 100644 index.html
create mode 100644 main.js
create mode 100644 manifest.json
create mode 100644 packageMine/declare.vue
create mode 100644 packageMine/manuscripts.vue
create mode 100644 packageMine/profile.vue
create mode 100644 packageMine/qingma.vue
create mode 100644 pages.json
create mode 100644 pages/activity-outline/index.vue
create mode 100644 pages/activity-outline/service.js
create mode 100644 pages/assistant/chat-service.js
create mode 100644 pages/assistant/index.vue
create mode 100644 pages/creative-assistant/index.vue
create mode 100644 pages/creative-assistant/service.js
create mode 100644 pages/gxmu/config.js
create mode 100644 pages/gxmu/cross-school-board.vue
create mode 100644 pages/gxmu/declare-service.js
create mode 100644 pages/gxmu/form.vue
create mode 100644 pages/gxmu/index.vue
create mode 100644 pages/gxmu/module-form-service.js
create mode 100644 pages/gxmu/qmgc.vue
create mode 100644 pages/gxmu/review-list.vue
create mode 100644 pages/gxmu/stats-service.js
create mode 100644 pages/gxmu/stats.vue
create mode 100644 pages/gxmu/tzb-database-service.js
create mode 100644 pages/gxmu/tzb-database.vue
create mode 100644 pages/gxmu/tzb-project-list.vue
create mode 100644 pages/gxmu/tzb-talent-list.vue
create mode 100644 pages/gxmu/tzbcy.vue
create mode 100644 pages/gxmu/wxxzx.vue
create mode 100644 pages/index/index.vue
create mode 100644 pages/login/index.vue
create mode 100644 pages/login/service.js
create mode 100644 pages/manuscript/index.vue
create mode 100644 pages/manuscript/service.js
create mode 100644 pages/mine/declare.vue
create mode 100644 pages/mine/index.vue
create mode 100644 pages/mine/manuscripts.vue
create mode 100644 pages/mine/profile.vue
create mode 100644 pages/mine/qingma.vue
create mode 100644 pages/mine/service.js
create mode 100644 pages/tygl/index.vue
create mode 100644 pages/tygl/service.js
create mode 100644 static/indexBg.jpg
create mode 100644 static/logo.png
create mode 100644 static/swiper.jpg
create mode 100644 static/tabbar/chat-active.png
create mode 100644 static/tabbar/chat.png
create mode 100644 static/tabbar/home-active.png
create mode 100644 static/tabbar/home.png
create mode 100644 static/tabbar/user-active.png
create mode 100644 static/tabbar/user.png
create mode 100644 uni.promisify.adaptor.js
create mode 100644 uni.scss
create mode 100644 uni_modules/uv-icon/changelog.md
create mode 100644 uni_modules/uv-icon/components/uv-icon/icons.js
create mode 100644 uni_modules/uv-icon/components/uv-icon/props.js
create mode 100644 uni_modules/uv-icon/components/uv-icon/uv-icon.vue
create mode 100644 uni_modules/uv-icon/components/uv-icon/uvicons.ttf
create mode 100644 uni_modules/uv-icon/package.json
create mode 100644 uni_modules/uv-icon/readme.md
create mode 100644 uni_modules/uv-input/changelog.md
create mode 100644 uni_modules/uv-input/components/uv-input/props.js
create mode 100644 uni_modules/uv-input/components/uv-input/uv-input.vue
create mode 100644 uni_modules/uv-input/package.json
create mode 100644 uni_modules/uv-input/readme.md
create mode 100644 uni_modules/uv-loading-icon/changelog.md
create mode 100644 uni_modules/uv-loading-icon/components/uv-loading-icon/props.js
create mode 100644 uni_modules/uv-loading-icon/components/uv-loading-icon/uv-loading-icon.vue
create mode 100644 uni_modules/uv-loading-icon/package.json
create mode 100644 uni_modules/uv-loading-icon/readme.md
create mode 100644 uni_modules/uv-overlay/changelog.md
create mode 100644 uni_modules/uv-overlay/components/uv-overlay/props.js
create mode 100644 uni_modules/uv-overlay/components/uv-overlay/uv-overlay.vue
create mode 100644 uni_modules/uv-overlay/package.json
create mode 100644 uni_modules/uv-overlay/readme.md
create mode 100644 uni_modules/uv-picker/changelog.md
create mode 100644 uni_modules/uv-picker/components/uv-picker/props.js
create mode 100644 uni_modules/uv-picker/components/uv-picker/uv-picker.vue
create mode 100644 uni_modules/uv-picker/package.json
create mode 100644 uni_modules/uv-picker/readme.md
create mode 100644 uni_modules/uv-popup/changelog.md
create mode 100644 uni_modules/uv-popup/components/uv-popup/keypress.js
create mode 100644 uni_modules/uv-popup/components/uv-popup/uv-popup.vue
create mode 100644 uni_modules/uv-popup/package.json
create mode 100644 uni_modules/uv-popup/readme.md
create mode 100644 uni_modules/uv-safe-bottom/changelog.md
create mode 100644 uni_modules/uv-safe-bottom/components/uv-safe-bottom/uv-safe-bottom.vue
create mode 100644 uni_modules/uv-safe-bottom/package.json
create mode 100644 uni_modules/uv-safe-bottom/readme.md
create mode 100644 uni_modules/uv-status-bar/changelog.md
create mode 100644 uni_modules/uv-status-bar/components/uv-status-bar/props.js
create mode 100644 uni_modules/uv-status-bar/components/uv-status-bar/uv-status-bar.vue
create mode 100644 uni_modules/uv-status-bar/package.json
create mode 100644 uni_modules/uv-status-bar/readme.md
create mode 100644 uni_modules/uv-toolbar/changelog.md
create mode 100644 uni_modules/uv-toolbar/components/uv-toolbar/props.js
create mode 100644 uni_modules/uv-toolbar/components/uv-toolbar/uv-toolbar.vue
create mode 100644 uni_modules/uv-toolbar/package.json
create mode 100644 uni_modules/uv-toolbar/readme.md
create mode 100644 uni_modules/uv-transition/changelog.md
create mode 100644 uni_modules/uv-transition/components/uv-transition/createAnimation.js
create mode 100644 uni_modules/uv-transition/components/uv-transition/props.js
create mode 100644 uni_modules/uv-transition/components/uv-transition/uv-transition.vue
create mode 100644 uni_modules/uv-transition/package.json
create mode 100644 uni_modules/uv-transition/readme.md
create mode 100644 uni_modules/uv-ui-tools/changelog.md
create mode 100644 uni_modules/uv-ui-tools/components/uv-ui-tools/uv-ui-tools.vue
create mode 100644 uni_modules/uv-ui-tools/index.js
create mode 100644 uni_modules/uv-ui-tools/index.scss
create mode 100644 uni_modules/uv-ui-tools/libs/config/config.js
create mode 100644 uni_modules/uv-ui-tools/libs/css/color.scss
create mode 100644 uni_modules/uv-ui-tools/libs/css/common.scss
create mode 100644 uni_modules/uv-ui-tools/libs/css/components.scss
create mode 100644 uni_modules/uv-ui-tools/libs/css/variable.scss
create mode 100644 uni_modules/uv-ui-tools/libs/css/vue.scss
create mode 100644 uni_modules/uv-ui-tools/libs/function/colorGradient.js
create mode 100644 uni_modules/uv-ui-tools/libs/function/debounce.js
create mode 100644 uni_modules/uv-ui-tools/libs/function/digit.js
create mode 100644 uni_modules/uv-ui-tools/libs/function/index.js
create mode 100644 uni_modules/uv-ui-tools/libs/function/platform.js
create mode 100644 uni_modules/uv-ui-tools/libs/function/test.js
create mode 100644 uni_modules/uv-ui-tools/libs/function/throttle.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/Request.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/core/settle.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/helpers/combineURLs.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/index.d.ts
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/index.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/utils.js
create mode 100644 uni_modules/uv-ui-tools/libs/luch-request/utils/clone.js
create mode 100644 uni_modules/uv-ui-tools/libs/mixin/button.js
create mode 100644 uni_modules/uv-ui-tools/libs/mixin/mixin.js
create mode 100644 uni_modules/uv-ui-tools/libs/mixin/mpMixin.js
create mode 100644 uni_modules/uv-ui-tools/libs/mixin/mpShare.js
create mode 100644 uni_modules/uv-ui-tools/libs/mixin/openType.js
create mode 100644 uni_modules/uv-ui-tools/libs/mixin/touch.js
create mode 100644 uni_modules/uv-ui-tools/libs/util/dayjs.js
create mode 100644 uni_modules/uv-ui-tools/libs/util/route.js
create mode 100644 uni_modules/uv-ui-tools/package.json
create mode 100644 uni_modules/uv-ui-tools/readme.md
create mode 100644 uni_modules/uv-ui-tools/theme.scss
create mode 100644 uni_modules/uv-ui/changelog.md
create mode 100644 uni_modules/uv-ui/components/uv-ui/uv-ui.vue
create mode 100644 uni_modules/uv-ui/package.json
create mode 100644 uni_modules/uv-ui/readme.md
create mode 100644 uni_modules/zero-markdown-view/changelog.md
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/highlight/config.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/highlight/index.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/highlight/prism.min.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/markdown/index.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/markdown/marked.min.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/mp-html.vue
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/node/node.vue
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/parser.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/style/index.js
create mode 100644 uni_modules/zero-markdown-view/components/mp-html/style/parser.js
create mode 100644 uni_modules/zero-markdown-view/components/zero-markdown-view/zero-markdown-view.vue
create mode 100644 uni_modules/zero-markdown-view/package.json
create mode 100644 uni_modules/zero-markdown-view/readme.md
create mode 100644 utils/gxmu/config.js
create mode 100644 utils/gxmu/declare-service.js
create mode 100644 utils/gxmu/review-list-service.js
create mode 100644 utils/markdown.js
create mode 100644 utils/request.js
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e6dd08d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+node_modules/
+unpackage/
+.hbuilderx/
+.DS_Store
+/.claude/
+/.idea/
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..228c31c
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,33 @@
+
+
+
diff --git a/components/common-hero/common-hero.vue b/components/common-hero/common-hero.vue
new file mode 100644
index 0000000..1ee76bb
--- /dev/null
+++ b/components/common-hero/common-hero.vue
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/u-input/u-input.vue b/components/u-input/u-input.vue
new file mode 100644
index 0000000..f5e14b6
--- /dev/null
+++ b/components/u-input/u-input.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..b5d330d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..517affb
--- /dev/null
+++ b/main.js
@@ -0,0 +1,27 @@
+import App from './App'
+import uvUI from '@/uni_modules/uv-ui-tools'
+
+// #ifndef VUE3
+import Vue from 'vue'
+import './uni.promisify.adaptor'
+
+Vue.config.productionTip = false
+Vue.use(uvUI)
+
+App.mpType = 'app'
+const app = new Vue({
+ ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+ const app = createSSRApp(App)
+ app.use(uvUI)
+ return {
+ app
+ }
+}
+// #endif
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..20443f9
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,72 @@
+{
+ "name" : "tuanwei",
+ "appid" : "__UNI__F254BAB",
+ "description" : "",
+ "versionName" : "1.0.0",
+ "versionCode" : "100",
+ "transformPx" : false,
+ /* 5+App特有相关 */
+ "app-plus" : {
+ "usingComponents" : true,
+ "nvueStyleCompiler" : "uni-app",
+ "compilerVersion" : 3,
+ "splashscreen" : {
+ "alwaysShowBeforeRender" : true,
+ "waiting" : true,
+ "autoclose" : true,
+ "delay" : 0
+ },
+ /* 模块配置 */
+ "modules" : {},
+ /* 应用发布信息 */
+ "distribute" : {
+ /* android打包配置 */
+ "android" : {
+ "permissions" : [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+ },
+ /* ios打包配置 */
+ "ios" : {},
+ /* SDK配置 */
+ "sdkConfigs" : {}
+ }
+ },
+ /* 快应用特有相关 */
+ "quickapp" : {},
+ /* 小程序特有相关 */
+ "mp-weixin" : {
+ "appid" : "wxf7ee9cd5801bf7a6",
+ "setting" : {
+ "urlCheck" : false
+ },
+ "usingComponents" : true
+ },
+ "mp-alipay" : {
+ "usingComponents" : true
+ },
+ "mp-baidu" : {
+ "usingComponents" : true
+ },
+ "mp-toutiao" : {
+ "usingComponents" : true
+ },
+ "uniStatistics" : {
+ "enable" : false
+ },
+ "vueVersion" : "3"
+}
diff --git a/packageMine/declare.vue b/packageMine/declare.vue
new file mode 100644
index 0000000..b19e616
--- /dev/null
+++ b/packageMine/declare.vue
@@ -0,0 +1,373 @@
+
+
+
+
+
+ 我的申报
+ 汇总本地草稿、已提交记录和当前开放的申报项目。
+
+
+ {{ localRecords.length }}
+ 本地记录
+
+
+ {{ submittedCount }}
+ 已提交
+
+
+ {{ openDeclareList.length }}
+ 开放项目
+
+
+
+
+
+
+ 本地申报记录
+ 刷新
+
+
+ 当前还没有本地草稿或提交记录,可先前往申报页填写。
+
+
+
+
+
+ {{ item.title }}
+ {{ item.year || '未设置年度' }} · {{ item.group }}
+
+
+ {{ item.status }}
+
+
+ 保存时间:{{ item.savedAt || '-' }}
+
+ 继续编辑
+ 复制标题
+
+
+
+
+
+
+
+ 当前开放项目
+ 全部查看
+
+ 正在加载开放项目...
+ {{ errorText }}
+ 当前暂无开放的申报项目。
+
+
+
+
+ {{ getDeclareTitle(item) }}
+ {{ getDeclareGroup(item.module) }} · {{ item.year || '未设置年度' }}
+
+ 可申报
+
+ 时间范围:{{ formatDateTime(item.startTime) }} 至 {{ formatDateTime(item.endTime) }}
+
+ 进入申报
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packageMine/manuscripts.vue b/packageMine/manuscripts.vue
new file mode 100644
index 0000000..bf4ec69
--- /dev/null
+++ b/packageMine/manuscripts.vue
@@ -0,0 +1,441 @@
+
+
+
+
+
+ 我的稿件
+ 汇总当前账号创建或参与的稿件记录,可查看状态和内容摘要。
+
+
+ {{ manuscripts.length }}
+ 稿件总数
+
+
+ {{ publishedCount }}
+ 已通过/发布
+
+
+ {{ pendingCount }}
+ 待处理
+
+
+
+
+
+
+
+ 刷新
+ 去创作
+
+
+
+
+ 正在加载稿件...
+ 请稍候,正在同步当前账号的稿件记录。
+
+
+ 加载失败
+ {{ errorText }}
+
+
+ 暂无稿件
+ 当前账号还没有可展示的稿件,可前往文稿工作台开始生成。
+
+
+
+
+
+ {{ item.title || '未命名稿件' }}
+
+ 创建时间:{{ formatDateTime(item.createTime) }} · 更新时间:{{ formatDateTime(item.updateTime) }}
+
+
+
+ {{ getStatusMeta(item).text }}
+
+
+
+
+
+ {{ getContentPreview(item.content) }}
+
+ {{ expandedId === item.id ? '收起内容' : '查看内容' }}
+ 复制标题
+
+ {{ item.content || '暂无正文内容' }}
+
+
+
+
+
+
+
+
+
diff --git a/packageMine/profile.vue b/packageMine/profile.vue
new file mode 100644
index 0000000..514c496
--- /dev/null
+++ b/packageMine/profile.vue
@@ -0,0 +1,932 @@
+
+
+
+
+
+
+ 基础信息
+
+
+
+
+
+
+
+
+
+ 姓名
+
+
+
+
+
+ 昵称
+
+
+
+
+
+ 性别
+
+
+ {{ editingGender || '请选择性别' }}
+
+
+
+
+
+
+ 所属组织机构
+
+ {{ editingOrganizationName || '请选择所属组织机构' }}
+
+
+
+
+
+ 手机号码
+ {{ profile.phone || '-' }}
+
+ 复制
+
+
+
+ 保存基础信息
+
+
+
+
+
+
+
+ 选择所属组织机构
+ 关闭
+
+
+
+
+
+
+
+ {{ item.rawLabel || item.text }}
+
+
+ {{ isOrganizationExpanded(item.value) ? '收起' : '展开' }}
+
+
+
+
+ 没有匹配的组织机构
+
+
+
+
+
+
+
+
+
diff --git a/packageMine/qingma.vue b/packageMine/qingma.vue
new file mode 100644
index 0000000..25cf847
--- /dev/null
+++ b/packageMine/qingma.vue
@@ -0,0 +1,362 @@
+
+
+
+
+
+ 我的“青马”
+ 查看青马工程报名记录、培养信息与当前审核状态。
+
+
+ {{ records.length }}
+ 记录总数
+
+
+ {{ approvedCount }}
+ 已通过
+
+
+ {{ pendingCount }}
+ 待跟进
+
+
+
+
+
+ 正在加载青马数据...
+ 请稍候,正在同步你的青马工程记录。
+
+
+ 加载失败
+ {{ errorText }}
+
+
+ 暂未查询到青马记录
+ 当前账号还没有青马工程报名或培养数据,可前往申报页查看开放项目。
+ 查看申报列表
+
+
+
+
+
+ {{ item.name || '未命名学员' }}
+ {{ item.year || '未设置年度' }} · 青马工程
+
+
+ {{ getStatusMeta(item).text }}
+
+
+
+
+ 学校院系
+ {{ item.schoolInfo || '-' }}
+
+
+ 手机号码
+ {{ item.phone || '-' }}
+
+
+ 团学职务
+ {{ item.leaguePosition || '-' }}
+
+
+ 综合成绩
+ {{ item.academicPerformance || '-' }}
+
+
+
+ 复制电话
+ 复制院系
+
+
+
+
+
+
+
+
+
+
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..8dff76d
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,237 @@
+{
+ "easycom": {
+ "autoscan": true,
+ "custom": {
+ "^zero-markdown-view$": "@/uni_modules/zero-markdown-view/components/zero-markdown-view/zero-markdown-view.vue"
+ }
+ },
+ "pages": [
+ {
+ "path": "pages/index/index",
+ "style": {
+ "navigationBarTitleText": "首页",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/assistant/index",
+ "style": {
+ "navigationBarTitleText": "助手",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/mine/index",
+ "style": {
+ "navigationBarTitleText": "我的",
+ "navigationStyle": "custom"
+ }
+ }
+ ],
+ "subPackages": [
+ {
+ "root": "pages/gxmu",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "五四评优",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "form",
+ "style": {
+ "navigationBarTitleText": "申报表",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "tzbcy",
+ "style": {
+ "navigationBarTitleText": "挑战杯申报",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "qmgc",
+ "style": {
+ "navigationBarTitleText": "青马工程申报",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "wxxzx",
+ "style": {
+ "navigationBarTitleText": "未来学术之星申报",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "stats",
+ "style": {
+ "navigationBarTitleText": "数据统计与报表中心",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "cross-school-board",
+ "style": {
+ "navigationBarTitleText": "跨校活动情报看板",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "tzb-database",
+ "style": {
+ "navigationBarTitleText": "创新竞赛历史项目数据库",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "tzb-project-list",
+ "style": {
+ "navigationBarTitleText": "挑战杯项目库",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "tzb-talent-list",
+ "style": {
+ "navigationBarTitleText": "挑战杯人才库",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "review-list",
+ "style": {
+ "navigationBarTitleText": "审核列表",
+ "navigationStyle": "custom"
+ }
+ }
+ ]
+ },
+ {
+ "root": "packageMine",
+ "pages": [
+ {
+ "path": "profile",
+ "style": {
+ "navigationBarTitleText": "用户资料",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "qingma",
+ "style": {
+ "navigationBarTitleText": "我的青马",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "manuscripts",
+ "style": {
+ "navigationBarTitleText": "我的稿件",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "declare",
+ "style": {
+ "navigationBarTitleText": "我的申报",
+ "navigationStyle": "custom"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/tygl",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "团员档案管理",
+ "navigationStyle": "custom"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/manuscript",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "文稿工作台"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/activity-outline",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "活动策划大纲"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/creative-assistant",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "AI创意助手"
+ }
+ }
+ ]
+ },
+ {
+ "root": "pages/login",
+ "pages": [
+ {
+ "path": "index",
+ "style": {
+ "navigationBarTitleText": "登录"
+ }
+ }
+ ]
+ }
+ ],
+ "globalStyle": {
+ "navigationBarTextStyle": "white",
+ "navigationBarTitleText": "智慧团委",
+ "navigationBarBackgroundColor": "#1496F2",
+ "backgroundColor": "#F4FAFF"
+ },
+ "tabBar": {
+ "color": "#7D7672",
+ "selectedColor": "#1496F2",
+ "backgroundColor": "#FFFFFF",
+ "borderStyle": "black",
+ "list": [
+ {
+ "pagePath": "pages/index/index",
+ "iconPath": "static/tabbar/home.png",
+ "selectedIconPath": "static/tabbar/home-active.png",
+ "text": "首页"
+ },
+ {
+ "pagePath": "pages/assistant/index",
+ "iconPath": "static/tabbar/chat.png",
+ "selectedIconPath": "static/tabbar/chat-active.png",
+ "text": "助手"
+ },
+ {
+ "pagePath": "pages/mine/index",
+ "iconPath": "static/tabbar/user.png",
+ "selectedIconPath": "static/tabbar/user-active.png",
+ "text": "我的"
+ }
+ ]
+ },
+ "uniIdRouter": {}
+}
diff --git a/pages/activity-outline/index.vue b/pages/activity-outline/index.vue
new file mode 100644
index 0000000..d8f6fef
--- /dev/null
+++ b/pages/activity-outline/index.vue
@@ -0,0 +1,881 @@
+
+
+
+
+ AI EVENT PLANNING OUTLINE
+ 活动策划大纲生成
+
+ 输入活动主题、受众、时间和资金等信息,系统会调用 `/ai/activityOutlineGen`
+ 生成结构化活动策划大纲,适合方案初稿、汇报材料和执行拆解场景。
+
+
+ 志愿服务
+ 主题沙龙
+ 校园赛事
+
+
+
+
+ 活动信息
+
+
+ 活动主题
+
+
+
+ 面向受众
+
+
+
+ 活动时间
+
+
+
+ 活动资金
+
+
+
+ 活动形式
+
+
+
+ 活动地点
+
+
+
+ 备注
+
+
+
+
+
+ 重置
+
+ {{ loading ? '生成中' : '生成大纲' }}
+
+
+
+
+ 提交说明
+
+ 必填字段会直接作为 `inputs` 透传给 AI,后端固定触发“活动策划大纲生成”指令,并返回整理后的正文结果。
+
+
+
+
+
+
+ 生成结果
+
+ {{ loading ? '生成中' : hasOutlineContent ? '已生成' : '待生成' }}
+
+
+
+
+ OUTLINE GENERATING
+ AI 正在整理活动策划结构
+
+ 正在综合活动主题、受众、时间与经费信息,生成可直接二次编辑的策划大纲。
+
+
+
+
+
+ AI 正在生成正文内容,请稍候...
+
+
+
+ {{ resultSummary }}
+
+
+
+ 策划大纲
+
+
+
+
+ 填写左侧信息后开始生成活动策划大纲
+
+
+
+ 复制内容
+ 清空结果
+
+
+
+
+
+
+
+
+
diff --git a/pages/activity-outline/service.js b/pages/activity-outline/service.js
new file mode 100644
index 0000000..829caf5
--- /dev/null
+++ b/pages/activity-outline/service.js
@@ -0,0 +1,17 @@
+import {
+ API_BASE_URL,
+ apiRequest,
+ buildWebSocketUrl,
+ getCurrentUser
+} from '../assistant/chat-service'
+
+export { buildWebSocketUrl, getCurrentUser }
+
+export function activityOutlineGen(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/activityOutlineGen`,
+ method: 'POST',
+ data,
+ withTenant: true
+ })
+}
diff --git a/pages/assistant/chat-service.js b/pages/assistant/chat-service.js
new file mode 100644
index 0000000..ef5598f
--- /dev/null
+++ b/pages/assistant/chat-service.js
@@ -0,0 +1,447 @@
+import {
+ API_BASE_URL,
+ DEFAULT_TENANT_ID,
+ TOKEN_HEADER_NAME,
+ clearAuthStorage,
+ getStoredUserInfo,
+ getToken,
+ redirectToLogin
+} from '../../utils/request'
+
+export { API_BASE_URL, getToken }
+
+const MODULES_API_URL = API_BASE_URL
+const APP_SECRET = 'ffd6eee985af45e4a75098422d1decbb'
+const AI_REQUEST_TIMEOUT = 10 * 60 * 1000
+
+let realAtob
+const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
+const b64re = /^(?:[A-Za-z\d+/]{4})*?(?:[A-Za-z\d+/]{2}(?:==)?|[A-Za-z\d+/]{3}=?)?$/
+
+if (typeof atob !== 'function') {
+ realAtob = function(str) {
+ let input = String(str || '').replace(/[\t\n\f\r ]+/g, '')
+ if (!b64re.test(input)) {
+ throw new Error("Failed to execute 'atob': The string to be decoded is not correctly encoded.")
+ }
+ input += '=='.slice(2 - (input.length & 3))
+ let bitmap
+ let result = ''
+ let r1
+ let r2
+ let index = 0
+ for (; index < input.length;) {
+ bitmap =
+ (b64.indexOf(input.charAt(index++)) << 18) |
+ (b64.indexOf(input.charAt(index++)) << 12) |
+ ((r1 = b64.indexOf(input.charAt(index++))) << 6) |
+ (r2 = b64.indexOf(input.charAt(index++)))
+ result +=
+ r1 === 64
+ ? String.fromCharCode((bitmap >> 16) & 255)
+ : r2 === 64
+ ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
+ : String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255)
+ }
+ return result
+ }
+} else {
+ realAtob = atob
+}
+
+function b64DecodeUnicode(str) {
+ return decodeURIComponent(
+ realAtob(str)
+ .split('')
+ .map((char) => `%${`00${char.charCodeAt(0).toString(16)}`.slice(-2)}`)
+ .join('')
+ )
+}
+
+function parseTokenPayload(token) {
+ const rawToken = String(token || '').replace(/^Bearer\s+/i, '')
+ const parts = rawToken.split('.')
+ if (!rawToken || parts.length !== 3) {
+ return null
+ }
+ try {
+ const normalized = parts[1].replace(/-/g, '+').replace(/_/g, '/')
+ return JSON.parse(b64DecodeUnicode(normalized))
+ } catch (error) {
+ return null
+ }
+}
+
+function safeAdd(x, y) {
+ const lsw = (x & 0xffff) + (y & 0xffff)
+ const msw = (x >> 16) + (y >> 16) + (lsw >> 16)
+ return (msw << 16) | (lsw & 0xffff)
+}
+
+function bitRotateLeft(num, cnt) {
+ return (num << cnt) | (num >>> (32 - cnt))
+}
+
+function md5cmn(q, a, b, x, s, t) {
+ return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b)
+}
+
+function md5ff(a, b, c, d, x, s, t) {
+ return md5cmn((b & c) | (~b & d), a, b, x, s, t)
+}
+
+function md5gg(a, b, c, d, x, s, t) {
+ return md5cmn((b & d) | (c & ~d), a, b, x, s, t)
+}
+
+function md5hh(a, b, c, d, x, s, t) {
+ return md5cmn(b ^ c ^ d, a, b, x, s, t)
+}
+
+function md5ii(a, b, c, d, x, s, t) {
+ return md5cmn(c ^ (b | ~d), a, b, x, s, t)
+}
+
+function binlMD5(x, len) {
+ x[len >> 5] |= 0x80 << len % 32
+ x[(((len + 64) >>> 9) << 4) + 14] = len
+
+ let i
+ let olda
+ let oldb
+ let oldc
+ let oldd
+ let a = 1732584193
+ let b = -271733879
+ let c = -1732584194
+ let d = 271733878
+
+ for (i = 0; i < x.length; i += 16) {
+ olda = a
+ oldb = b
+ oldc = c
+ oldd = d
+
+ a = md5ff(a, b, c, d, x[i], 7, -680876936)
+ d = md5ff(d, a, b, c, x[i + 1], 12, -389564586)
+ c = md5ff(c, d, a, b, x[i + 2], 17, 606105819)
+ b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330)
+ a = md5ff(a, b, c, d, x[i + 4], 7, -176418897)
+ d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426)
+ c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341)
+ b = md5ff(b, c, d, a, x[i + 7], 22, -45705983)
+ a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416)
+ d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417)
+ c = md5ff(c, d, a, b, x[i + 10], 17, -42063)
+ b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162)
+ a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682)
+ d = md5ff(d, a, b, c, x[i + 13], 12, -40341101)
+ c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290)
+ b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329)
+
+ a = md5gg(a, b, c, d, x[i + 1], 5, -165796510)
+ d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632)
+ c = md5gg(c, d, a, b, x[i + 11], 14, 643717713)
+ b = md5gg(b, c, d, a, x[i], 20, -373897302)
+ a = md5gg(a, b, c, d, x[i + 5], 5, -701558691)
+ d = md5gg(d, a, b, c, x[i + 10], 9, 38016083)
+ c = md5gg(c, d, a, b, x[i + 15], 14, -660478335)
+ b = md5gg(b, c, d, a, x[i + 4], 20, -405537848)
+ a = md5gg(a, b, c, d, x[i + 9], 5, 568446438)
+ d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690)
+ c = md5gg(c, d, a, b, x[i + 3], 14, -187363961)
+ b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501)
+ a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467)
+ d = md5gg(d, a, b, c, x[i + 2], 9, -51403784)
+ c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473)
+ b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734)
+
+ a = md5hh(a, b, c, d, x[i + 5], 4, -378558)
+ d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463)
+ c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562)
+ b = md5hh(b, c, d, a, x[i + 14], 23, -35309556)
+ a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060)
+ d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353)
+ c = md5hh(c, d, a, b, x[i + 7], 16, -155497632)
+ b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640)
+ a = md5hh(a, b, c, d, x[i + 13], 4, 681279174)
+ d = md5hh(d, a, b, c, x[i], 11, -358537222)
+ c = md5hh(c, d, a, b, x[i + 3], 16, -722521979)
+ b = md5hh(b, c, d, a, x[i + 6], 23, 76029189)
+ a = md5hh(a, b, c, d, x[i + 9], 4, -640364487)
+ d = md5hh(d, a, b, c, x[i + 12], 11, -421815835)
+ c = md5hh(c, d, a, b, x[i + 15], 16, 530742520)
+ b = md5hh(b, c, d, a, x[i + 2], 23, -995338651)
+
+ a = md5ii(a, b, c, d, x[i], 6, -198630844)
+ d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415)
+ c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905)
+ b = md5ii(b, c, d, a, x[i + 5], 21, -57434055)
+ a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571)
+ d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606)
+ c = md5ii(c, d, a, b, x[i + 10], 15, -1051523)
+ b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799)
+ a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359)
+ d = md5ii(d, a, b, c, x[i + 15], 10, -30611744)
+ c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380)
+ b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649)
+ a = md5ii(a, b, c, d, x[i + 4], 6, -145523070)
+ d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379)
+ c = md5ii(c, d, a, b, x[i + 2], 15, 718787259)
+ b = md5ii(b, c, d, a, x[i + 9], 21, -343485551)
+
+ a = safeAdd(a, olda)
+ b = safeAdd(b, oldb)
+ c = safeAdd(c, oldc)
+ d = safeAdd(d, oldd)
+ }
+ return [a, b, c, d]
+}
+
+function binl2rstr(input) {
+ let index
+ let output = ''
+ const length32 = input.length * 32
+ for (index = 0; index < length32; index += 8) {
+ output += String.fromCharCode((input[index >> 5] >>> index % 32) & 0xff)
+ }
+ return output
+}
+
+function rstr2binl(input) {
+ const output = Array(input.length >> 2)
+ let index
+ for (index = 0; index < output.length; index += 1) {
+ output[index] = 0
+ }
+ const length8 = input.length * 8
+ for (index = 0; index < length8; index += 8) {
+ output[index >> 5] |= (input.charCodeAt(index / 8) & 0xff) << index % 32
+ }
+ return output
+}
+
+function rstrMD5(value) {
+ return binl2rstr(binlMD5(rstr2binl(value), value.length * 8))
+}
+
+function rstr2hex(input) {
+ const hexTab = '0123456789abcdef'
+ let output = ''
+ let index
+ let value
+ for (index = 0; index < input.length; index += 1) {
+ value = input.charCodeAt(index)
+ output += hexTab.charAt((value >>> 4) & 0x0f) + hexTab.charAt(value & 0x0f)
+ }
+ return output
+}
+
+function str2rstrUTF8(input) {
+ return unescape(encodeURIComponent(input))
+}
+
+function md5(value) {
+ return rstr2hex(rstrMD5(str2rstrUTF8(String(value || ''))))
+}
+
+function objKeySort(obj) {
+ const next = {}
+ Object.keys(obj || {})
+ .sort()
+ .forEach((key) => {
+ next[key] = obj[key]
+ })
+ return next
+}
+
+function addSignature(payload) {
+ const form = payload || {}
+ form.timestamp = Date.now()
+ form.version = 'v3'
+ let sign = ''
+ const sorted = objKeySort(form)
+ Object.keys(sorted).forEach((key) => {
+ const value = form[key]
+ if (value !== null && value !== undefined && value !== '') {
+ sign = `${sign}${value}-`
+ }
+ })
+ form.sign = md5(`${sign}${APP_SECRET}`)
+ return form
+}
+
+function getStorageValue(keys) {
+ for (let index = 0; index < keys.length; index += 1) {
+ const value = uni.getStorageSync(keys[index])
+ if (value) {
+ return value
+ }
+ }
+ return ''
+}
+
+export function getCurrentUser() {
+ const primaryToken = getToken()
+ const storedUser = getStoredUserInfo()
+ const tokenList = [
+ primaryToken,
+ uni.getStorageSync('uni_id_token'),
+ uni.getStorageSync('access_token')
+ ].filter(Boolean)
+ let payload = null
+
+ for (let index = 0; index < tokenList.length; index += 1) {
+ payload = parseTokenPayload(tokenList[index])
+ if (payload) {
+ break
+ }
+ }
+
+ if (!payload) {
+ return {
+ ...storedUser,
+ token: primaryToken || ''
+ }
+ }
+
+ return {
+ ...storedUser,
+ userId: Number(payload.userId || payload.uid || payload.id || 0) || null,
+ nickname: payload.nickname || payload.username || payload.nickName || '',
+ realName: payload.realName || payload.realname || payload.name || '',
+ token: primaryToken || ''
+ }
+}
+
+export function apiRequest({
+ url,
+ method = 'GET',
+ data,
+ withSignature = true,
+ withTenant = false,
+ timeout
+}) {
+ const token = getToken()
+ const requestData = data ? { ...data } : undefined
+ const headers = {}
+
+ if (token) {
+ headers[TOKEN_HEADER_NAME] = token
+ }
+
+ if (requestData && withTenant) {
+ requestData.tenantId = DEFAULT_TENANT_ID
+ }
+
+ if (requestData && withSignature) {
+ addSignature(requestData)
+ }
+
+ return uni.request({
+ url,
+ method,
+ data: requestData,
+ header: headers,
+ ...(timeout !== undefined && { timeout })
+ }).then((response) => {
+ const responseHeader = (response && response.header) || {}
+ const nextToken =
+ responseHeader[TOKEN_HEADER_NAME] ||
+ responseHeader[TOKEN_HEADER_NAME.toLowerCase()]
+ if (nextToken) {
+ uni.setStorageSync('access_token', nextToken)
+ }
+
+ const { statusCode } = response || {}
+ const body = (response && response.data) || {}
+ if (statusCode && statusCode >= 400) {
+ return Promise.reject(new Error(body.message || '请求失败'))
+ }
+ if (Number(body.code) === 401) {
+ clearAuthStorage()
+ redirectToLogin()
+ return Promise.reject(new Error(body.message || '登录已失效'))
+ }
+ if (body.code === 0) {
+ return body.data !== undefined ? body.data : body.message
+ }
+ return Promise.reject(new Error(body.message || '请求失败'))
+ })
+}
+
+export function listAiChatList(params) {
+ return apiRequest({
+ url: `${MODULES_API_URL}/ai/ai-chat-list`,
+ method: 'GET',
+ data: params
+ })
+}
+
+export function listAiChatHistory(params) {
+ return apiRequest({
+ url: `${MODULES_API_URL}/ai/ai-chat-history`,
+ method: 'GET',
+ data: params
+ })
+}
+
+export function removeAiChatList(id) {
+ return apiRequest({
+ url: `${MODULES_API_URL}/ai/ai-chat-list/${id}`,
+ method: 'DELETE',
+ withSignature: false
+ })
+}
+
+export function sendMessage(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/chat/message`,
+ method: 'POST',
+ data,
+ withTenant: true,
+ timeout: AI_REQUEST_TIMEOUT
+ })
+}
+
+export function manuscriptGen(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/manuscriptGen`,
+ method: 'POST',
+ data,
+ withTenant: true,
+ timeout: AI_REQUEST_TIMEOUT
+ })
+}
+
+export function creativeAssistant(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/creativeAssistant`,
+ method: 'POST',
+ data,
+ withTenant: true,
+ timeout: AI_REQUEST_TIMEOUT
+ })
+}
+
+export function activityOutlineGen(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/activityOutlineGen`,
+ method: 'POST',
+ data,
+ withTenant: true,
+ timeout: AI_REQUEST_TIMEOUT
+ })
+}
+
+export function buildWebSocketUrl(userId) {
+ const url = String(API_BASE_URL || '')
+ if (/^https?:\/\//.test(url)) {
+ return `${url
+ .replace(/^https:/, 'wss:')
+ .replace(/^http:/, 'ws:')
+ .replace(/\/api\/?$/, '')
+ .replace(/\/$/, '')}/chat/${userId}`
+ }
+ return `${url.replace(/\/api\/?$/, '')}/chat/${userId}`
+}
diff --git a/pages/assistant/index.vue b/pages/assistant/index.vue
new file mode 100644
index 0000000..de6041b
--- /dev/null
+++ b/pages/assistant/index.vue
@@ -0,0 +1,1725 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AI 助手
+
+ {{ activeChatTitle }} · {{ userName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 请先登录后使用 AI 助手
+ 当前页面已接入真实会话逻辑,发送消息和历史会话依赖登录态。
+
+
+
+ 你好,我是 AI 团委助手
+
+ 你可以直接提问团务流程问题,我会通过实时消息回复。
+
+
+
+
+
+ {{ isUserMessage(item) ? '我' : '助' }}
+
+
+
+
+
+ {{ ASSISTANT_PENDING_TEXT }}
+
+ {{ item.content }}
+
+
+
+ 复制
+
+ 重用
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+ {{ loading ? '···' : '发送' }}
+
+
+
+
+
+
+
+
+ 历史会话
+ 按最近更新时间展示
+
+ 关闭
+
+
+
+
+
+ {{ section.label }}
+
+
+ {{ getHistoryTitle(item) }}
+
+ {{ formatHistoryItemTime(item.createTime) }}
+
+
+
+ {{ deletingChatId === item.id ? '删除中' : '删除' }}
+
+
+
+
+ 暂无历史对话
+
+
+
+
+
+
+
+
+
diff --git a/pages/creative-assistant/index.vue b/pages/creative-assistant/index.vue
new file mode 100644
index 0000000..4efe242
--- /dev/null
+++ b/pages/creative-assistant/index.vue
@@ -0,0 +1,1038 @@
+
+
+
+
+ AI 创意助手
+
+ 支持文本指令与多类型附件联合驱动工作流,自动返回视频、脚本 Markdown 或图像 / 排版结果。
+
+
+ 短视频创意
+ 脚本创作
+ 海报排版
+
+
+
+
+ 输入配置
+
+
+ 文本指令
+
+
+
+
+ 上传附件
+
+ {{ uploading ? '上传中...' : '添加附件' }}
+ 支持图片、视频、音频和常见文档类型。
+
+
+
+
+ {{ getFileTypeLabel(item) }}
+
+ {{ item.name || getFileName(item) }}
+ {{ resolveFileUrl(item) || '-' }}
+
+
+ 移除
+
+
+
+
+
+
+ 重置
+
+ {{ loading ? '执行中' : '生成' }}
+
+
+
+
+
+
+ 工作流结果
+
+ {{ loading ? '执行中' : hasAnyResult ? '已完成' : '待执行' }}
+
+
+
+
+ WORKFLOW RUNNING
+ {{ loadingTitle }}
+ {{ loadingDescription }}
+
+
+ 0{{ index + 1 }}
+
+ {{ item.title }}
+ {{ item.desc }}
+
+
+
+
+
+
+ 填写文本指令并上传附件后执行工作流
+
+
+
+
+ {{ statusMessage }}
+
+
+
+ 视频生成结果
+
+
+
+
+ {{ item.name || getFileName(item) }}
+ 复制链接
+
+
+
+
+
+
+ 脚本创作结果
+
+
+
+
+ 图像 / 排版结果
+
+
+
+
+ {{ getFileTypeLabel(item) }}
+ 复制结果链接
+
+
+ {{ item.name || getFileName(item) }}
+ 复制链接
+
+
+
+
+
+
+
+ 复制脚本
+ 清空结果
+
+
+
+
+
+
+
+
+
diff --git a/pages/creative-assistant/service.js b/pages/creative-assistant/service.js
new file mode 100644
index 0000000..40cfeab
--- /dev/null
+++ b/pages/creative-assistant/service.js
@@ -0,0 +1,45 @@
+import { API_BASE_URL, apiRequest, getToken } from '../assistant/chat-service'
+
+export function creativeAssistant(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/creativeAssistant`,
+ method: 'POST',
+ data,
+ withTenant: true,
+ timeout: 600000
+ })
+}
+
+export function uploadAiFile(file) {
+ const token = getToken()
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ url: `${API_BASE_URL}/ai/file/upload`,
+ filePath: file.path,
+ name: 'file',
+ header: token
+ ? {
+ Authorization: token
+ }
+ : {},
+ formData: {
+ tenantId: '10049'
+ },
+ success: (response) => {
+ try {
+ const result = JSON.parse(response.data || '{}')
+ if (result.code === 0 && result.data) {
+ resolve(result.data)
+ return
+ }
+ reject(new Error(result.message || '上传失败'))
+ } catch (error) {
+ reject(new Error('上传响应解析失败'))
+ }
+ },
+ fail: (error) => {
+ reject(new Error(error.errMsg || '上传失败'))
+ }
+ })
+ })
+}
diff --git a/pages/gxmu/config.js b/pages/gxmu/config.js
new file mode 100644
index 0000000..4eec0de
--- /dev/null
+++ b/pages/gxmu/config.js
@@ -0,0 +1,395 @@
+const GENDER_OPTIONS = ['男', '女']
+const YES_NO_OPTIONS = ['是', '否']
+
+export const GXMU_MODULES = [
+ {
+ title: '十佳青年岗位能手',
+ code: 'gxmu_sjqn',
+ icon: '青',
+ group: '个人奖项',
+ desc: '面向青年岗位骨干与先进典型的申报入口。'
+ },
+ {
+ title: '十佳团支部书记',
+ code: 'gxmu_sjtbzbsj',
+ icon: '书',
+ group: '个人奖项',
+ desc: '聚焦基层团支部书记的履职表现与带动成效。'
+ },
+ {
+ title: '五四红旗团委',
+ code: 'gxmu_wshqtw',
+ icon: '委',
+ group: '组织奖项',
+ desc: '用于先进团委集体申报与材料汇总展示。'
+ },
+ {
+ title: '五四红旗团支部',
+ code: 'gxmu_wshqtzb',
+ icon: '支',
+ group: '组织奖项',
+ desc: '聚焦先进团支部建设成果与品牌工作展示。'
+ },
+ {
+ title: '优秀共青团干部',
+ code: 'gxmu_yxgqtdgb',
+ icon: '干',
+ group: '个人奖项',
+ desc: '面向团学骨干和团务干部的申报入口。'
+ },
+ {
+ title: '优秀共青团员',
+ code: 'gxmu_yxgqty',
+ icon: '员',
+ group: '个人奖项',
+ desc: '面向优秀团员个人事迹与成长表现申报。'
+ },
+ {
+ title: '挑战杯',
+ code: 'gxmu_tzbcy_form',
+ icon: '挑',
+ group: '竞赛项目',
+ desc: '面向挑战杯项目材料填报与过程归档。'
+ },
+ {
+ title: '青马工程',
+ code: 'gxmu_qmgc_form',
+ icon: '青',
+ group: '培养项目',
+ desc: '用于青马工程学员培养信息和成果申报。'
+ },
+ {
+ title: '未来学术之星',
+ code: 'gxmu_wxxzx_project',
+ icon: '星',
+ group: '创新项目',
+ desc: '用于未来学术之星项目申报和材料整理。'
+ }
+]
+
+const createFields = (fields) =>
+ fields.map((field) => ({
+ required: false,
+ placeholder: `请输入${field.label}`,
+ ...field
+ }))
+
+export const GXMU_FORM_MAP = {
+ gxmu_sjqn: {
+ title: '十佳青年岗位能手申报表',
+ subtitle: '参考后台 SJQNForm 字段结构,适用于个人申报信息填写。',
+ sections: [
+ {
+ title: '基础信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'applyType', label: '申报类别', required: true },
+ { key: 'name', label: '姓名', required: true },
+ { key: 'gender', label: '性别', type: 'select', options: GENDER_OPTIONS },
+ { key: 'birthMonth', label: '出生年月', type: 'month' },
+ { key: 'nation', label: '民族' },
+ { key: 'politics', label: '政治面貌' },
+ { key: 'education', label: '学历' },
+ { key: 'position', label: '职务' },
+ { key: 'title', label: '职称' },
+ { key: 'unit', label: '所在单位' }
+ ])
+ },
+ {
+ title: '申报内容',
+ fields: createFields([
+ { key: 'awards', label: '近三年曾获校级及以上奖励', type: 'textarea' },
+ { key: 'experience', label: '工作(学习)经历', type: 'textarea' },
+ { key: 'mainStory', label: '主要事迹', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_sjtbzbsj: {
+ title: '十佳团支部书记申报表',
+ subtitle: '参考后台 SJTBZBSJForm 字段结构,适用于个人申报信息填写。',
+ sections: [
+ {
+ title: '基础信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'name', label: '姓名', required: true },
+ { key: 'gender', label: '性别', type: 'select', options: GENDER_OPTIONS },
+ { key: 'birthMonth', label: '出生年月', type: 'month' },
+ { key: 'nation', label: '民族' },
+ { key: 'politics', label: '政治面貌' },
+ { key: 'collegeClass', label: '学院班级/单位科室' },
+ { key: 'branch', label: '所在团支部' },
+ { key: 'eduEval', label: '上一年度团员教育评议等次' }
+ ])
+ },
+ {
+ title: '申报内容',
+ fields: createFields([
+ { key: 'awards', label: '近三年曾获校级及以上奖励', type: 'textarea' },
+ { key: 'experience', label: '工作(学习)经历', type: 'textarea' },
+ { key: 'mainStory', label: '主要事迹', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_wshqtw: {
+ title: '五四红旗团委申报表',
+ subtitle: '参考后台 WSHQTWForm 字段结构,适用于组织集体申报。',
+ sections: [
+ {
+ title: '组织基本信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'orgName', label: '二级团组织全称', required: true },
+ { key: 'leader', label: '负责人' },
+ { key: 'phone', label: '联系电话', type: 'phone' },
+ { key: 'memberTotal', label: '现有团员总数', type: 'number' },
+ { key: 'memberDeveloped2024', label: '上一年度发展团员人数', type: 'number' },
+ { key: 'smartSystemLogin', label: '是否已登录智慧团建系统', type: 'select', options: YES_NO_OPTIONS },
+ { key: 'committeeCount', label: '团委委员人数', type: 'number' },
+ { key: 'fulltimeCadreCount', label: '专职团干部数(其中教师/学生)' },
+ { key: 'parttimeCadreCount', label: '兼职团干部数(其中教师/学生)' },
+ { key: 'lastElectionTime', label: '团委最近一次换届时间', type: 'date' },
+ { key: 'branchCount', label: '团支部数', type: 'number' }
+ ])
+ },
+ {
+ title: '年度建设情况',
+ fields: createFields([
+ { key: 'feeReceivable2024', label: '上一年度应收团费', type: 'number' },
+ { key: 'feeReceived2024', label: '上一年度实收团费', type: 'number' },
+ { key: 'feePayable2024', label: '上一年度应上缴团费', type: 'number' },
+ { key: 'feePaid2024', label: '上一年度实际上缴团费', type: 'number' },
+ { key: 'standardizedWork2024', label: '是否开展规范化建设工作', type: 'select', options: YES_NO_OPTIONS },
+ { key: 'recommendActivist2024', label: '推荐入党积极分子人数', type: 'number' },
+ { key: 'activistConfirmed', label: '确定为入党积极分子数', type: 'number' },
+ { key: 'recommendDevTarget2024', label: '推荐党的发展对象人数', type: 'number' },
+ { key: 'devTargetConfirmed', label: '确定为党的发展对象数', type: 'number' }
+ ])
+ },
+ {
+ title: '主要成果',
+ fields: createFields([
+ { key: 'honorsFiveYears', label: '近五年获得校级及以上荣誉情况', type: 'textarea' },
+ { key: 'workSummaryThreeYears', label: '近三年开展的主要工作及取得的效果', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_wshqtzb: {
+ title: '五四红旗团支部申报表',
+ subtitle: '参考后台 WSHQTZBForm 字段结构,适用于基层团支部集体申报。',
+ sections: [
+ {
+ title: '组织基本信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'branchName', label: '团支部全称', required: true },
+ { key: 'secondOrg', label: '所属二级团组织' },
+ { key: 'secretary', label: '团支部书记' },
+ { key: 'politics', label: '政治面貌' },
+ { key: 'contact', label: '联系方式', type: 'phone' },
+ { key: 'establishTime', label: '成立时间', type: 'date' },
+ { key: 'lastElectionTime', label: '最近一次换届时间', type: 'date' },
+ { key: 'smartSystemLogin', label: '是否已登录智慧团建系统', type: 'select', options: YES_NO_OPTIONS },
+ { key: 'memberTotal', label: '现有团员总数', type: 'number' },
+ { key: 'memberDeveloped2024', label: '上一年度发展团员数', type: 'number' }
+ ])
+ },
+ {
+ title: '年度建设情况',
+ fields: createFields([
+ { key: 'feeReceivable2024', label: '上一年度应收团费', type: 'number' },
+ { key: 'feeReceived2024', label: '上一年度实收团费', type: 'number' },
+ { key: 'feePayable2024', label: '上一年度应上缴团费', type: 'number' },
+ { key: 'feePaid2024', label: '上一年度实际上缴团费', type: 'number' },
+ { key: 'recommendActivist2024', label: '推荐入党积极分子人数', type: 'number' },
+ { key: 'activistConfirmed', label: '确定为入党积极分子数', type: 'number' },
+ { key: 'recommendDevTarget2024', label: '推荐党的发展对象人数', type: 'number' },
+ { key: 'devTargetConfirmed', label: '确定为党的发展对象数', type: 'number' },
+ { key: 'branchCommitteeMeetingCount', label: '团支部委员会会议召开次数', type: 'number' },
+ { key: 'branchMemberMeetingCount', label: '团支部团员大会召开次数', type: 'number' },
+ { key: 'eduEvalDone', label: '是否开展团员教育评议', type: 'select', options: YES_NO_OPTIONS },
+ { key: 'annualRegDone', label: '是否开展团员年度团籍注册', type: 'select', options: YES_NO_OPTIONS },
+ { key: 'classCount', label: '开展团课次数', type: 'number' },
+ { key: 'smartSystem100', label: '是否100%录入智慧团建', type: 'select', options: YES_NO_OPTIONS }
+ ])
+ },
+ {
+ title: '主要成果',
+ fields: createFields([
+ { key: 'honorsFiveYears', label: '近五年获得院级及以上荣誉情况', type: 'textarea' },
+ { key: 'workSummaryThreeYears', label: '近三年开展的主要工作及取得的效果', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_yxgqtdgb: {
+ title: '优秀共青团干部申报表',
+ subtitle: '参考后台 YXGQTDGBForm 字段结构,适用于团干部个人申报。',
+ sections: [
+ {
+ title: '基础信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'name', label: '姓名', required: true },
+ { key: 'gender', label: '性别', type: 'select', options: GENDER_OPTIONS },
+ { key: 'nation', label: '民族' },
+ { key: 'birthMonth', label: '出生年月', type: 'month' },
+ { key: 'politics', label: '政治面貌' },
+ { key: 'position', label: '职务' },
+ { key: 'identity', label: '身份' },
+ { key: 'organization', label: '所在团组织' },
+ { key: 'contact', label: '联系方式', type: 'phone' },
+ { key: 'memberNo', label: '发展团员编号' },
+ { key: 'currentDutyTime', label: '任现团内职务时间', type: 'month' },
+ { key: 'cadreYears', label: '担任团干部年限' },
+ { key: 'assessment2024', label: '上一年度工作考核结果' },
+ { key: 'volunteerRegTime', label: '成为注册志愿者时间', type: 'month' }
+ ])
+ },
+ {
+ title: '申报内容',
+ fields: createFields([
+ { key: 'cadreExperience', label: '从事团干部经历', type: 'textarea' },
+ { key: 'honorsFiveYears', label: '近五年获得校级及以上荣誉情况', type: 'textarea' },
+ { key: 'mainStory', label: '主要事迹', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_yxgqty: {
+ title: '优秀共青团员申报表',
+ subtitle: '参考后台 YXGQTYForm 字段结构,适用于团员个人申报。',
+ sections: [
+ {
+ title: '基础信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'name', label: '姓名', required: true },
+ { key: 'gender', label: '性别', type: 'select', options: GENDER_OPTIONS },
+ { key: 'nation', label: '民族' },
+ { key: 'politics', label: '政治面貌' },
+ { key: 'birthMonth', label: '出生年月', type: 'month' },
+ { key: 'joinTime', label: '入团时间', type: 'month' },
+ { key: 'collegeMajorClass', label: '所在学院、专业、班级' },
+ { key: 'position', label: '职务' },
+ { key: 'volunteerRegTime', label: '成为注册志愿者时间', type: 'month' },
+ { key: 'eduEval2024', label: '上一年度团员教育评议等次' },
+ { key: 'smartSystem', label: '是否已登录智慧团建系统', type: 'select', options: YES_NO_OPTIONS },
+ { key: 'contact', label: '联系电话', type: 'phone' },
+ { key: 'totalVolunteerHours', label: '累计志愿服务时长' },
+ { key: 'volunteerHours2024', label: '上一年度志愿服务时长' },
+ { key: 'memberNo', label: '发展团员编号' }
+ ])
+ },
+ {
+ title: '申报内容',
+ fields: createFields([
+ { key: 'honorsFiveYears', label: '近五年获得荣誉情况', type: 'textarea' },
+ { key: 'mainStory', label: '主要事迹', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_tzbcy_form: {
+ title: '挑战杯申报表',
+ subtitle: '面向挑战杯项目申报、团队信息和成果材料整理。',
+ sections: [
+ {
+ title: '项目信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'projectName', label: '项目名称', required: true },
+ { key: 'projectType', label: '项目类型', required: true },
+ { key: 'projectGroup', label: '项目分组', required: true },
+ { key: 'leaderName', label: '项目负责人', required: true },
+ { key: 'leaderCollege', label: '负责人学院' },
+ { key: 'leaderPhone', label: '负责人电话', type: 'phone' },
+ { key: 'guidanceTeacher', label: '指导老师' }
+ ])
+ },
+ {
+ title: '项目内容',
+ fields: createFields([
+ { key: 'projectSummary', label: '项目简介', type: 'textarea', required: true },
+ { key: 'innovationPoint', label: '创新亮点', type: 'textarea' },
+ { key: 'teamMembers', label: '团队成员', type: 'textarea' },
+ { key: 'honors', label: '已有成果与奖励', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_qmgc_form: {
+ title: '青马工程申报表',
+ subtitle: '用于青马工程学员基础信息、培养情况和成果申报。',
+ sections: [
+ {
+ title: '基础信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'name', label: '姓名', required: true },
+ { key: 'gender', label: '性别', type: 'select', options: GENDER_OPTIONS },
+ { key: 'college', label: '学院', required: true },
+ { key: 'className', label: '班级' },
+ { key: 'phone', label: '联系电话', type: 'phone' },
+ { key: 'politics', label: '政治面貌' }
+ ])
+ },
+ {
+ title: '培养情况',
+ fields: createFields([
+ { key: 'trainingExperience', label: '培养经历', type: 'textarea', required: true },
+ { key: 'practiceExperience', label: '实践经历', type: 'textarea' },
+ { key: 'mainAchievement', label: '主要成果', type: 'textarea' },
+ { key: 'selfEvaluation', label: '个人总结', type: 'textarea' }
+ ])
+ }
+ ]
+ },
+ gxmu_wxxzx_project: {
+ title: '未来学术之星申报表',
+ subtitle: '用于未来学术之星项目申报、课题信息和支撑材料整理。',
+ sections: [
+ {
+ title: '项目基础信息',
+ fields: createFields([
+ { key: 'year', label: '年份', type: 'year', required: true },
+ { key: 'projectName', label: '项目名称', required: true },
+ { key: 'applicantName', label: '申请人', required: true },
+ { key: 'college', label: '学院', required: true },
+ { key: 'major', label: '专业' },
+ { key: 'phone', label: '联系电话', type: 'phone' },
+ { key: 'guidanceTeacher', label: '指导老师' }
+ ])
+ },
+ {
+ title: '申报内容',
+ fields: createFields([
+ { key: 'researchDirection', label: '研究方向', type: 'textarea' },
+ { key: 'projectBasis', label: '项目基础', type: 'textarea', required: true },
+ { key: 'researchPlan', label: '研究计划', type: 'textarea' },
+ { key: 'expectedResult', label: '预期成果', type: 'textarea' }
+ ])
+ }
+ ]
+ }
+}
+
+export const getModuleMeta = (code) => GXMU_MODULES.find((item) => item.code === code)
+
+export const getFormConfig = (code) => GXMU_FORM_MAP[code]
+
+export const createInitialFormData = (code) => {
+ const config = getFormConfig(code)
+ if (!config) {
+ return {}
+ }
+ return config.sections.reduce((result, section) => {
+ section.fields.forEach((field) => {
+ result[field.key] = field.defaultValue || ''
+ })
+ return result
+ }, {})
+}
diff --git a/pages/gxmu/cross-school-board.vue b/pages/gxmu/cross-school-board.vue
new file mode 100644
index 0000000..afb8fb4
--- /dev/null
+++ b/pages/gxmu/cross-school-board.vue
@@ -0,0 +1,886 @@
+
+
+
+
+
+
+ 跨校活动情报看板
+ 把兄弟高校的活动打法,整理成一眼可读的案例板
+
+ 以信息流和案例卡片形式集中展示同类活动的公开线索,方便快速判断选题趋势、包装方式和传播动作。
+
+
+ 本周热点
+ 拟办活动对标
+
+
+
+
+
+ 案例总量
+ {{ totalCount }}
+ 当前静态示例数据
+
+
+ 高热案例
+ {{ highHeatCount }}
+ 适合优先拆解传播路径
+
+
+ 覆盖类型
+ {{ categoryCount }}
+ 品牌活动 / 实践 / 科创 / 文体
+
+
+ 来源院校
+ {{ schoolCount }}
+ 按院校公开渠道聚合
+
+
+
+
+
+
+ 活动类型
+
+
+
+ {{ item }}
+
+
+
+
+
+
+ 热度等级
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+ 清空
+
+
+
+
+
+ 情报信息流
+
+
+
+ {{ item.category }}
+ {{ item.school }}
+
+
+
+ {{ item.title }}
+ {{ item.heat }}
+
+ {{ item.school }} · {{ item.source }} · {{ item.publishAt }}
+ {{ item.summary }}
+
+ {{ tag }}
+
+
+
+
+
+
+
+ 策略信号
+
+
+ {{ item.title }}
+ {{ item.desc }}
+
+
+
+ 建议关注
+
+ {{ item }}
+
+
+
+
+
+
+ 案例卡片墙
+ 共 {{ filteredCases.length }} 条
+
+
+
+
+
+ {{ item.school }}
+ {{ item.highlight }}
+
+
+
+
+ {{ item.category }}
+ {{ item.heat }}
+
+ {{ item.title }}
+ {{ item.summary }}
+ 来源:{{ item.source }}
+ 发布时间:{{ item.publishAt }}
+
+ # {{ tag }}
+
+
+
+
+
+
+ 暂无匹配的案例
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/declare-service.js b/pages/gxmu/declare-service.js
new file mode 100644
index 0000000..68e39b1
--- /dev/null
+++ b/pages/gxmu/declare-service.js
@@ -0,0 +1,10 @@
+import { API_BASE_URL } from '../../utils/request'
+import { apiRequest } from '../assistant/chat-service'
+
+export function listDeclare(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/declare`,
+ method: 'GET',
+ data: params
+ })
+}
diff --git a/pages/gxmu/form.vue b/pages/gxmu/form.vue
new file mode 100644
index 0000000..7d9a181
--- /dev/null
+++ b/pages/gxmu/form.vue
@@ -0,0 +1,892 @@
+
+
+
+
+
+
+ {{ pageTitle }}
+ {{ moduleMeta && moduleMeta.desc ? moduleMeta.desc : '按模块维护申报记录,支持新增、编辑和提交。' }}
+
+ 立即申报
+ 刷新列表
+
+
+
+
+
+ 正在加载申报记录...
+
+
+ 暂无申报记录
+ 点击上方“立即申报”开始填写当前模块。
+
+
+
+
+
+ {{ getRecordTitle(item) }}
+ {{ getRecordSubtitle(item) }}
+
+ {{ item.year || fixedYear || '-' }}
+
+ {{ getRecordMeta(item) }}
+
+
+
+
+
+
+
+ {{ formData.id ? `编辑${pageTitle}` : `新增${pageTitle}` }}
+ 关闭
+
+
+
+
+
+ 申报年度
+ {{ fixedYear || formData.year || '-' }}
+
+
+ 草稿状态
+ {{ draftSavedAt ? '已保存' : '未保存' }}
+
+
+
+
+
+ {{ section.title }}
+
+
+
+
+ {{ field.label }}
+ *
+
+
+
+
+
+
+ {{ formData[field.key] || field.placeholder }}
+
+
+
+
+
+
+
+ {{ formData[field.key] || (nationOptions.length ? '请选择民族' : '民族加载中') }}
+
+
+
+
+
+
+
+ {{ getPickerDisplayText(field) }}
+
+
+
+
+
+ {{ formData[field.key] || getDatePlaceholder(field) }}
+
+
+
+
+
+
+
+
+
+
+ 保存草稿
+ 提交申报
+
+
+
+
+
+
+
+ 未找到对应表单
+ 请返回上一页重新选择申报模块。
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/index.vue b/pages/gxmu/index.vue
new file mode 100644
index 0000000..5c36866
--- /dev/null
+++ b/pages/gxmu/index.vue
@@ -0,0 +1,697 @@
+
+
+
+
+
+
+
+
+ 项目列表
+ 当前仅展示可申报项目
+
+
+ {{ loading ? '刷新中' : '刷新' }}
+
+
+
+
+ 正在加载申报项目...
+ 请稍候,正在同步后台开放的申报配置。
+
+
+
+ 加载失败
+ {{ loadError }}
+ 重新加载
+
+
+
+ 当前暂无可申报项目
+ 后台还没有开放可申报数据,稍后再来查看。
+
+
+
+
+
+
+ {{ selectedYear ? `${selectedYear} 年` : '全部年份' }}
+ ▼
+
+
+
+
+ {{ selectedModule ? getDeclareModuleLabel(selectedModule) : '全部模块' }}
+ ▼
+
+
+
+
+
+
+
+
+ {{ getDeclareTitle(item) }}
+ {{ getDeclareModuleLabel(item.module) }}
+
+
+ {{ isModuleSupported(item.module) ? '可申报' : '待支持' }}
+
+
+
+
+ {{ item.year ? `${item.year} 年` : '未设置年度' }}
+
+
+ {{ getDeclareDescription(item.module) }}
+
+
+
+ 开始时间
+ {{ formatDateTime(item.startTime) }}
+
+
+ 结束时间
+ {{ formatDateTime(item.endTime) }}
+
+
+
+
+
+
+
+ 暂无匹配项目
+ 请调整年份或模块筛选条件后重试。
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/module-form-service.js b/pages/gxmu/module-form-service.js
new file mode 100644
index 0000000..a42adc0
--- /dev/null
+++ b/pages/gxmu/module-form-service.js
@@ -0,0 +1,212 @@
+import { API_BASE_URL } from '../../utils/request'
+import { apiRequest, getToken } from '../assistant/chat-service'
+
+function request(url, method = 'GET', data) {
+ return apiRequest({
+ url: `${API_BASE_URL}${url}`,
+ method,
+ data
+ })
+}
+
+export function userPageTzbcyForm(params) {
+ return request('/gxmu/tzbcy-form/userPage', 'GET', params)
+}
+
+export function getTzbcyForm(id) {
+ return request(`/gxmu/tzbcy-form/${id}`, 'GET')
+}
+
+export function addTzbcyForm(data) {
+ return request('/gxmu/tzbcy-form', 'POST', data)
+}
+
+export function updateTzbcyForm(data) {
+ return request('/gxmu/tzbcy-form', 'PUT', data)
+}
+
+export function removeTzbcyForm(id) {
+ return request(`/gxmu/tzbcy-form/${id}`, 'DELETE')
+}
+
+export function userPageSjqnForm(params) {
+ return request('/gxmu/sjqn-form/userPage', 'GET', params)
+}
+
+export function getSjqnForm(id) {
+ return request(`/gxmu/sjqn-form/${id}`, 'GET')
+}
+
+export function addSjqnForm(data) {
+ return request('/gxmu/sjqn-form', 'POST', data)
+}
+
+export function updateSjqnForm(data) {
+ return request('/gxmu/sjqn-form', 'PUT', data)
+}
+
+export function removeSjqnForm(id) {
+ return request(`/gxmu/sjqn-form/${id}`, 'DELETE')
+}
+
+export function getDeclare(id) {
+ return request(`/gxmu/declare/${id}`, 'GET')
+}
+
+export function listDictData(params) {
+ return request('/system/dict-data', 'GET', params)
+}
+
+export function userPageQmgcForm(params) {
+ return request('/gxmu/qmgc-form/userPage', 'GET', params)
+}
+
+export function getQmgcForm(id) {
+ return request(`/gxmu/qmgc-form/${id}`, 'GET')
+}
+
+export function addQmgcForm(data) {
+ return request('/gxmu/qmgc-form', 'POST', data)
+}
+
+export function updateQmgcForm(data) {
+ return request('/gxmu/qmgc-form', 'PUT', data)
+}
+
+export function removeQmgcForm(id) {
+ return request(`/gxmu/qmgc-form/${id}`, 'DELETE')
+}
+
+export function userPageWxxzxForm(params) {
+ return request('/gxmu/wxxzx-form/userPage', 'GET', params)
+}
+
+export function getWxxzxForm(id) {
+ return request(`/gxmu/wxxzx-form/${id}`, 'GET')
+}
+
+export function addWxxzxForm(data) {
+ return request('/gxmu/wxxzx-form', 'POST', data)
+}
+
+export function updateWxxzxForm(data) {
+ return request('/gxmu/wxxzx-form', 'PUT', data)
+}
+
+export function removeWxxzxForm(id) {
+ return request(`/gxmu/wxxzx-form/${id}`, 'DELETE')
+}
+
+export function userPageSjtbzbsjForm(params) {
+ return request('/gxmu/sjtbzbsj-form/userPage', 'GET', params)
+}
+
+export function getSjtbzbsjForm(id) {
+ return request(`/gxmu/sjtbzbsj-form/${id}`, 'GET')
+}
+
+export function addSjtbzbsjForm(data) {
+ return request('/gxmu/sjtbzbsj-form', 'POST', data)
+}
+
+export function updateSjtbzbsjForm(data) {
+ return request('/gxmu/sjtbzbsj-form', 'PUT', data)
+}
+
+export function userPageWshqtwForm(params) {
+ return request('/gxmu/wshqtw-form/userPage', 'GET', params)
+}
+
+export function getWshqtwForm(id) {
+ return request(`/gxmu/wshqtw-form/${id}`, 'GET')
+}
+
+export function addWshqtwForm(data) {
+ return request('/gxmu/wshqtw-form', 'POST', data)
+}
+
+export function updateWshqtwForm(data) {
+ return request('/gxmu/wshqtw-form', 'PUT', data)
+}
+
+export function userPageWshqtzbForm(params) {
+ return request('/gxmu/wshqtzb-form/userPage', 'GET', params)
+}
+
+export function getWshqtzbForm(id) {
+ return request(`/gxmu/wshqtzb-form/${id}`, 'GET')
+}
+
+export function addWshqtzbForm(data) {
+ return request('/gxmu/wshqtzb-form', 'POST', data)
+}
+
+export function updateWshqtzbForm(data) {
+ return request('/gxmu/wshqtzb-form', 'PUT', data)
+}
+
+export function userPageYxgqtdgbForm(params) {
+ return request('/gxmu/yxgqtdgb-form/userPage', 'GET', params)
+}
+
+export function getYxgqtdgbForm(id) {
+ return request(`/gxmu/yxgqtdgb-form/${id}`, 'GET')
+}
+
+export function addYxgqtdgbForm(data) {
+ return request('/gxmu/yxgqtdgb-form', 'POST', data)
+}
+
+export function updateYxgqtdgbForm(data) {
+ return request('/gxmu/yxgqtdgb-form', 'PUT', data)
+}
+
+export function userPageYxgqtyForm(params) {
+ return request('/gxmu/yxgqty-form/userPage', 'GET', params)
+}
+
+export function getYxgqtyForm(id) {
+ return request(`/gxmu/yxgqty-form/${id}`, 'GET')
+}
+
+export function addYxgqtyForm(data) {
+ return request('/gxmu/yxgqty-form', 'POST', data)
+}
+
+export function updateYxgqtyForm(data) {
+ return request('/gxmu/yxgqty-form', 'PUT', data)
+}
+
+export function uploadTempFile(file) {
+ const token = getToken()
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ url: `${API_BASE_URL}/file/upload`,
+ filePath: file.path,
+ name: 'file',
+ header: token
+ ? {
+ Authorization: token
+ }
+ : {},
+ formData: {
+ tenantId: '10049'
+ },
+ success: (response) => {
+ try {
+ const result = JSON.parse(response.data || '{}')
+ if (result.code === 0 && result.data) {
+ resolve(result.data)
+ return
+ }
+ reject(new Error(result.message || '上传失败'))
+ } catch (error) {
+ reject(new Error('上传响应解析失败'))
+ }
+ },
+ fail: (error) => {
+ reject(new Error(error.errMsg || '上传失败'))
+ }
+ })
+ })
+}
diff --git a/pages/gxmu/qmgc.vue b/pages/gxmu/qmgc.vue
new file mode 100644
index 0000000..070e620
--- /dev/null
+++ b/pages/gxmu/qmgc.vue
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+ {{ pageTitle }}
+
+
+ 立即申报
+ 刷新列表
+
+
+
+ 正在加载申报记录...
+ 暂无申报记录
+
+
+
+ {{ item.name || '未命名学员' }}{{ item.schoolInfo || '-' }}
+ {{ item.year || '-' }}
+
+ 手机号:{{ item.phone || '-' }}
+ 团学职务:{{ item.leaguePosition || '-' }}
+
+
+
+
+
+
+ {{ current.id ? '编辑青马工程申报' : '新增青马工程申报' }}关闭
+
+
+ 登记表
+ 年份
+ 姓名
+
+ 性别
+
+ {{ current.gender || '请选择性别' }}
+
+
+
+ 民族
+
+
+ {{ current.nation || (nationOptions.length ? '请选择民族' : '民族加载中') }}
+
+
+
+
+ 出生年月
+
+ {{ current.birthMonth || '请选择出生年月' }}
+
+
+
+ 政治面貌
+
+ {{ current.politics || (politicsOptions.length ? '请选择政治面貌' : '政治面貌加载中') }}
+
+
+ 籍贯
+ 手机号码
+ 微信号
+ 电子邮箱
+ QQ号
+ 身份证号
+ 爱好特长
+
+ 是否有志到广西基层工作
+
+ {{ current.willingToWorkInGuangxi || '请选择' }}
+
+
+ 学校、院系、年级、专业
+ 担任团学职务情况
+ 个人简历
+ 奖惩情况
+ 综合成绩情况
+
+
+ 取消保存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/review-list.vue b/pages/gxmu/review-list.vue
new file mode 100644
index 0000000..9a2c49f
--- /dev/null
+++ b/pages/gxmu/review-list.vue
@@ -0,0 +1,1297 @@
+
+
+
+
+
+
+ 审核列表
+ 统一处理稿件、评优申报、挑战杯、青马工程、未来学术之星和团员管理审核。
+
+
+ {{ total }}
+ 全部记录
+
+
+ {{ pendingCount }}
+ 待处理
+
+
+
+
+
+
+
+
+ {{ selectedModuleLabel }}
+ ▼
+
+
+ {{ selectedStatusLabel }}
+ ▼
+
+
+ {{ loading ? '刷新中' : '刷新' }}
+
+
+
+
+ 清除
+ 搜索
+
+
+
+
+ 正在加载审核列表...
+ 请稍候,正在同步后台聚合审核记录。
+
+
+
+ 加载失败
+ {{ loadError }}
+ 重新加载
+
+
+
+ 暂无审核记录
+ 当前筛选条件下没有待展示的数据。
+
+
+
+
+
+
+ {{ item.businessName || '未命名业务' }}
+ {{ item.moduleName || getModuleName(item.module) }}
+
+
+ {{ getStatusMeta(item.status).text }}
+
+
+
+
+ 提交时间
+ {{ formatDateTime(item.createTime) }}
+
+
+ 当前审核人
+ {{ getReviewerName(item) }}
+
+
+ 最新意见:{{ item.content }}
+
+ 查看数据
+ 审核流
+
+
+
+
+ 正在加载更多...
+ 点击加载更多
+ 没有更多数据了
+
+
+
+
+
+
+
+
+
+ {{ detailTitle }}
+ 业务ID:{{ dataCurrent && dataCurrent.pk ? dataCurrent.pk : '-' }}
+
+ 关闭
+
+
+
+ 正在加载详情...
+
+
+ 详情加载失败
+ {{ detailError }}
+
+
+ 暂无可展示数据
+
+
+
+ {{ item.label }}
+
+
+
+
+
+ {{ file.name }}
+
+
+
+
+ 第{{ index + 1 }}项
+
+ {{ line }}
+
+
+
+
+
+ {{ line }}
+
+
+ {{
+ formatDisplayValue(dataCurrent.module, item.key, item.value)
+ }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ flowTitle }}
+ 业务ID:{{ flowCurrent && flowCurrent.pk ? flowCurrent.pk : '-' }}
+
+ 关闭
+
+
+
+ 正在加载审核流...
+
+
+ 审核流加载失败
+ {{ flowError }}
+
+
+ 暂无审核流数据
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+ {{ getReviewerName(item) }}
+
+ {{ getStatusMeta(item.status).text }}
+
+
+ 创建时间:{{ formatDateTime(item.createTime) }}
+ 审核意见:{{ item.content }}
+
+ 通过
+ 拒绝
+
+
+
+
+
+
+
+
+
+
+ {{ actionType === 'approve' ? '审核通过' : '审核拒绝' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/stats-service.js b/pages/gxmu/stats-service.js
new file mode 100644
index 0000000..6eb1a18
--- /dev/null
+++ b/pages/gxmu/stats-service.js
@@ -0,0 +1,10 @@
+import { API_BASE_URL, apiRequest } from '../assistant/chat-service'
+
+export function getChallengeCupStatistics(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/tzbcy-form/statistics`,
+ method: 'GET',
+ data: params,
+ withSignature: false
+ })
+}
diff --git a/pages/gxmu/stats.vue b/pages/gxmu/stats.vue
new file mode 100644
index 0000000..39f11d9
--- /dev/null
+++ b/pages/gxmu/stats.vue
@@ -0,0 +1,735 @@
+
+
+
+
+
+ 挑战杯数据统计
+
+
+
+ {{ selectedYear ? `${selectedYear} 年` : '全部年份' }}
+ ▼
+
+
+
+ {{ loading ? '刷新中' : '刷新数据' }}
+
+
+
+
+
+ i
+ {{ stats.awardCountDescription }}
+
+
+
+ 正在加载统计数据...
+ 请稍候,正在同步挑战杯报表中心数据。
+
+
+
+ 加载失败
+ {{ loadError }}
+ 重新加载
+
+
+
+
+
+ 申报作品数量
+ {{ summary.declarationCount }}
+
+
+
+ 参与申报人数
+ {{ summary.participantCount }}
+
+
+
+ 指导老师数量
+ {{ summary.advisorCount }}
+
+
+
+ 获奖数量
+ {{ summary.awardCount }}
+
+
+
+
+
+
+ 申报学校数量
+ {{ summary.schoolCount }}
+
+
+ 项目类型数
+ {{ stats.typeDistribution.length }}
+
+
+ 项目分组数
+ {{ stats.groupDistribution.length }}
+
+
+
+
+
+
+ 年度申报趋势
+ 展示各年度挑战杯作品申报数量变化
+
+
+
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+
+
+
+
+ 暂无年度数据
+
+
+
+
+
+ 项目类型分布
+ 按项目类型统计申报数量
+
+
+
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+
+
+
+
+ 暂无类型分布
+
+
+
+
+
+ 项目分组分布
+ 按项目分组统计申报数量
+
+
+
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+
+
+
+
+ 暂无分组分布
+
+
+
+
+
+ 学校申报排行
+ 展示学校维度的申报数量排名
+
+
+
+
+ {{ index + 1 }}
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+
+
+
+
+
+ 暂无学校排行
+
+
+
+
+
+ 分布明细
+ {{ selectedYear ? `${selectedYear} 年` : '全部年份' }}统计口径下的分类数量
+
+
+
+
+ 项目类型
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+ 暂无数据
+
+
+ 项目分组
+
+
+ {{ item.label }}
+ {{ item.value }}
+
+
+ 暂无数据
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/tzb-database-service.js b/pages/gxmu/tzb-database-service.js
new file mode 100644
index 0000000..1d1eeed
--- /dev/null
+++ b/pages/gxmu/tzb-database-service.js
@@ -0,0 +1,19 @@
+import { API_BASE_URL, apiRequest } from '../assistant/chat-service'
+
+export function pageTzbProjectList(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/tzb-project-list/page`,
+ method: 'GET',
+ data: params,
+ withSignature: false
+ })
+}
+
+export function pageTzbTalentList(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/tzb-talent-list/page`,
+ method: 'GET',
+ data: params,
+ withSignature: false
+ })
+}
diff --git a/pages/gxmu/tzb-database.vue b/pages/gxmu/tzb-database.vue
new file mode 100644
index 0000000..c032ed0
--- /dev/null
+++ b/pages/gxmu/tzb-database.vue
@@ -0,0 +1,205 @@
+
+
+
+
+
+ 项目库与人才库
+
+ 沉淀挑战杯历史项目案例、获奖信息与参赛人才画像,支持按项目和人才两个维度快速检索与复用。
+
+
+
+
+
+
+
+
+
+
+ 项
+ 项目库
+
+ 挑战杯项目库
+ 查看历届项目名称、学校、奖项、比赛级别、届次与详情链接。
+
+
+
+
+
+ 才
+ 人才库
+
+ 挑战杯人才库
+ 查看参赛人才、学校、人才类型、参赛项目、获奖情况与原始详情链接。
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/tzb-project-list.vue b/pages/gxmu/tzb-project-list.vue
new file mode 100644
index 0000000..ecf4e8f
--- /dev/null
+++ b/pages/gxmu/tzb-project-list.vue
@@ -0,0 +1,661 @@
+
+
+
+
+
+ 创新竞赛历史项目数据库
+
+ 按项目名称、学校、奖项、年份和比赛级别查看历届挑战杯案例,支持复制详情链接用于进一步追踪原始页面。
+
+
+
+ {{ list.length }}
+ 当前已加载
+
+
+ {{ yearOptions.length }}
+ 年份筛选
+
+
+ {{ levelOptions.length }}
+ 级别筛选
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+ {{ filters.matchYear ? `${filters.matchYear}年` : '参赛年份' }}
+
+
+ {{ filters.matchLevel || '比赛级别' }}
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+ 正在加载项目库...
+ 请稍候,正在同步挑战杯历史项目数据。
+
+
+
+ 加载失败
+ {{ loadError }}
+ 重新加载
+
+
+
+ 暂无匹配项目
+ 请调整搜索条件后重新查询。
+
+
+
+
+
+
+ {{ item.matchLevel || '未分类' }}
+
+
+ {{ item.projectName || '未命名项目' }}
+ {{ item.schoolName || '未知学校' }}
+
+ {{ item.awardName || '未录入奖项' }}
+ {{ item.matchYear || '-' }}年
+ {{ item.matchTerm || '未知届次' }}
+
+
+
+
+
+
+ 来源ID
+ {{ item.sourceId || '-' }}
+
+
+ 来源页码
+ {{ item.pageNo || '-' }}
+
+
+ 同步时间
+ {{ formatDateTime(item.lastSyncTime) }}
+
+
+
+
+
+
+
+
+ 正在加载更多...
+ 点击加载更多
+ 没有更多数据了
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/tzb-talent-list.vue b/pages/gxmu/tzb-talent-list.vue
new file mode 100644
index 0000000..1248310
--- /dev/null
+++ b/pages/gxmu/tzb-talent-list.vue
@@ -0,0 +1,680 @@
+
+
+
+
+
+ 创新竞赛历史人才数据库
+
+ 按姓名、学校、人才类型、参赛项目和比赛级别查看历届挑战杯人才线索,支持复制详情链接用于进一步跟踪。
+
+
+
+ {{ list.length }}
+ 当前已加载
+
+
+ {{ levelOptions.length }}
+ 级别筛选
+
+
+ {{ talentTypeCount }}
+ 人才类型
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ filters.matchLevel || '比赛级别' }}
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+ 正在加载人才库...
+ 请稍候,正在同步挑战杯历史人才数据。
+
+
+
+ 加载失败
+ {{ loadError }}
+ 重新加载
+
+
+
+ 暂无匹配人才
+ 请调整搜索条件后重新查询。
+
+
+
+
+
+
+ {{ getAvatarText(item.personName) }}
+
+
+
+ {{ item.personName || '未命名人才' }}
+ {{ item.talentType || '未分类' }}
+
+ {{ item.schoolName || '未知学校' }}
+ {{ item.projectName || '未录入项目名称' }}
+
+ {{ item.awardName || '未录入奖项' }}
+ {{ item.matchLevel || '未知级别' }}
+ {{ item.matchTerm || '未知届次' }}
+
+
+
+
+
+
+ 来源ID
+ {{ item.sourceId || '-' }}
+
+
+ 来源页码
+ {{ item.pageNo || '-' }}
+
+
+ 同步时间
+ {{ formatDateTime(item.lastSyncTime) }}
+
+
+
+
+
+
+
+
+ 正在加载更多...
+ 点击加载更多
+ 没有更多数据了
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/tzbcy.vue b/pages/gxmu/tzbcy.vue
new file mode 100644
index 0000000..5e88343
--- /dev/null
+++ b/pages/gxmu/tzbcy.vue
@@ -0,0 +1,787 @@
+
+
+
+
+
+ 挑战杯
+ {{ pageTitle }}
+ 按后台完整字段拆分为项目申报表、项目说明、公开展示信息表。
+
+ 立即申报
+ 刷新列表
+
+
+
+
+ 正在加载申报记录...
+
+
+ 暂无申报记录
+ 点击上方“立即申报”开始填写挑战杯项目。
+
+
+
+
+
+ {{ item.projectName || '未命名项目' }}
+ {{ item.projectType || '-' }} · {{ item.projectGroup || '-' }}
+
+ {{ item.year || '-' }}
+
+ 学校:{{ item.schoolName || '-' }}
+ 负责人:{{ getLeaderInfo(item).leader || '-' }} / {{ getLeaderInfo(item).phone || '-' }}
+
+
+
+
+
+
+
+ {{ current.id ? '编辑挑战杯申报' : '新增挑战杯申报' }}
+ 关闭
+
+
+
+
+ 项目申报表
+ 项目说明
+ 公开展示信息表
+
+
+
+
+ 年份
+
+
+
+
+ 所在省(区、市)
+
+
+
+ 学校名称(全称)
+
+
+
+
+ 项目名称
+
+
+
+ 项目类型
+
+
+ {{ getOptionLabel(current.projectType, formProjectTypeOptions) || '请选择项目类型' }}
+
+
+
+
+
+ 项目分组
+ 仅可选择 1 个组别,按后台申报配置提供选项。
+
+
+
+ {{ getOptionLabel(current.projectGroup, formProjectGroupOptions) || '请选择项目分组' }}
+
+
+
+
+
+ 暂无团队成员,请手动新增。
+
+
+ 成员 {{ index + 1 }}
+ 删除
+
+
+ 姓名
+ 性别
+ 学院
+ 年级、专业
+ 手机
+ 备注
+
+
+
+
+ 暂无指导教师,请手动新增。
+
+
+ 指导教师 {{ index + 1 }}
+ 删除
+
+
+ 姓名
+ 性别
+ 学院
+ 职称
+ 职务
+ 手机
+
+
+
+
+ 项目简介(500 字以内)
+
+
+
+
+
+ 社会价值(500 字以内)
+ 实践过程(500 字以内)
+ 创新意义(500 字以内)
+ 发展前景(500 字以内)
+ 团队协作(500 字以内)
+ 项目介绍材料
+ 其他相关证明材料
+
+
+
+
+ 项目名称
+
+
+
+ 参赛学校
+
+
+
+ 项目类型
+
+
+ {{ getOptionLabel(current.publicProjectType, publicProjectTypeOptions) || '请选择项目类型' }}
+
+
+
+
+ 项目分组
+
+
+ {{ getOptionLabel(current.publicProjectGroup, publicProjectGroupOptions) || '请选择项目分组' }}
+
+
+
+
+ 我们的项目
+
+
+
+ 我们的团队
+
+
+ 请上传团队图片
+
+ 上传图片
+ 移除
+
+
+
+ 我们的口号
+
+ 我们的实践日志(选填)
+
+
+
+
+ 请上传实践日志视频
+
+ 上传视频
+ 移除
+
+
+
+
+
+
+
+ 取消
+ 保存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/gxmu/wxxzx.vue b/pages/gxmu/wxxzx.vue
new file mode 100644
index 0000000..d4cb980
--- /dev/null
+++ b/pages/gxmu/wxxzx.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+ {{ pageTitle }}
+
+
+ 立即申报
+ 刷新列表
+
+
+
+ 正在加载申报记录...
+ 暂无申报记录
+
+
+
+ {{ item.topicName || '未命名课题' }}{{ item.collegeGradeClass || '-' }}
+ {{ item.year || '-' }}
+
+ 负责人:{{ item.leader || '-' }}
+ 联系电话:{{ item.phone || '-' }}
+
+
+
+
+
+
+ {{ current.id ? '编辑未来学术之星申报' : '新增未来学术之星申报' }}关闭
+
+
+ 基本信息
+ 年份
+ 课题名称
+ 课题负责人
+ 学院、年级、班别
+ 联系电话
+ 指导老师
+ 课题类型
+ 立论依据
+
+
+
+
+
+
+
+
+
+ 取消保存
+
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..848ae6f
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,568 @@
+
+
+
+
+
+
+
+
+ 关键字搜索
+
+ 搜索
+
+
+
+
+
+
+
+
+
+ 资讯:
+ {{ notice.title }}
+
+ ›
+
+
+
+
+ 核心业务
+
+
+
+ {{ item.icon }}
+ {{ item.tag }}
+
+ {{ item.title }}
+ {{ item.desc }}
+
+
+
+
+
+
+
+ 申报系统
+ 当前开放的申报项目入口
+
+ 查看全部
+
+
+
+
+ 进入系统
+
+
+ 正在加载申报项目...
+ {{ declareError }}
+ 当前暂无可申报项目
+
+
+
+
+ {{ getDeclareTitle(item) }}
+
+ {{ getDeclareGroup(item.module) }} · {{ item.year ? `${item.year}年` : '未设置年度' }}
+
+
+ 可申报
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/login/index.vue b/pages/login/index.vue
new file mode 100644
index 0000000..021a62b
--- /dev/null
+++ b/pages/login/index.vue
@@ -0,0 +1,298 @@
+
+
+
+ 进入智慧团委小程序
+ 支持手机号密码登录,也支持微信手机号授权登录。
+
+
+
+
+
+ 手机号密码登录
+
+
+ 微信授权登录
+
+
+
+
+
+
+
+ {{ loading ? '登录中...' : '立即登录' }}
+
+
+
+
+ 授权后将使用微信手机号完成登录。
+
+
+
+
+
+
+
+
+
diff --git a/pages/login/service.js b/pages/login/service.js
new file mode 100644
index 0000000..3a67fc9
--- /dev/null
+++ b/pages/login/service.js
@@ -0,0 +1,21 @@
+import { DEFAULT_TENANT_ID, post } from '../../utils/request'
+
+export function loginByPassword(data) {
+ return post(
+ '/login',
+ {
+ tenantId: DEFAULT_TENANT_ID,
+ isMiniApp: 1,
+ ...data
+ },
+ {
+ auth: false
+ }
+ )
+}
+
+export function loginByMpWxPhone(data) {
+ return post('/wx-login/loginByMpWxPhone', data, {
+ auth: false
+ })
+}
diff --git a/pages/manuscript/index.vue b/pages/manuscript/index.vue
new file mode 100644
index 0000000..32d7dbb
--- /dev/null
+++ b/pages/manuscript/index.vue
@@ -0,0 +1,1112 @@
+
+
+
+
+ AI CONTENT STUDIO
+ AI 内容创作与宣传助手
+
+ 面向团委宣传、活动报道、新闻稿和推文草稿的快速生成场景。填写创作条件后,页面会调用
+ `/ai/manuscriptGen` 并通过 WebSocket 实时接收生成内容。
+
+
+ 活动新闻稿
+ 公众号推文
+ 发言稿提纲
+ 进入问答助手
+
+
+
+
+ 创作配置
+
+
+ 稿件标题
+
+
+
+
+ 稿件类型
+
+
+ {{ form.docType || '请选择稿件类型' }}
+
+
+
+
+
+ 活动类型
+
+
+ {{ form.eventType || '请选择活动类型' }}
+
+
+
+
+
+ 活动时间
+
+
+
+
+ 活动地点
+
+
+
+
+ 参与人员
+
+
+
+
+ 建议篇幅
+
+
+
+
+ 亮点内容
+
+
+
+
+ 附件材料
+
+ {{ uploading ? '上传中...' : '选择附件' }}
+ 支持图片、文档等附件,上传后将按 `files` 字段提交。
+
+
+
+
+ 附件
+
+ {{ item.name || '未命名文件' }}
+ {{ item.url || item.path || '-' }}
+
+
+ 移除
+
+
+
+
+
+
+ 重置
+
+ {{ loading ? '生成中' : '生成内容' }}
+
+
+
+
+ 提交说明
+
+ 页面会先提交 `POST /ai/manuscriptGen`,再通过 WebSocket 流式接收生成结果;如果后端直接返回正文,也会自动兼容显示。
+
+
+
+
+
+
+ 生成结果
+
+ {{ loading ? '生成中' : markdownContent ? '已生成' : '待生成' }}
+
+
+
+
+ 生成标题
+
+
+
+
+ 正文内容
+
+
+ {{ markdownContent || 'AI 正在生成内容...' }}
+
+
+ 填写左侧创作条件后开始生成
+
+
+
+
+ 接口摘要
+ {{ responseSummary }}
+
+
+
+ 复制正文
+ 复制标题
+ 清空结果
+
+
+
+
+
+
+
+
+
diff --git a/pages/manuscript/service.js b/pages/manuscript/service.js
new file mode 100644
index 0000000..a4d0969
--- /dev/null
+++ b/pages/manuscript/service.js
@@ -0,0 +1,52 @@
+import {
+ API_BASE_URL,
+ apiRequest,
+ buildWebSocketUrl,
+ getCurrentUser,
+ getToken
+} from '../assistant/chat-service'
+
+export { buildWebSocketUrl, getCurrentUser }
+
+export function manuscriptGen(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/ai/manuscriptGen`,
+ method: 'POST',
+ data,
+ withTenant: true
+ })
+}
+
+export function uploadTempFile(file) {
+ const token = getToken()
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ url: `${API_BASE_URL}/file/upload`,
+ filePath: file.path,
+ name: 'file',
+ header: token
+ ? {
+ Authorization: token
+ }
+ : {},
+ formData: {
+ tenantId: '10049'
+ },
+ success: (response) => {
+ try {
+ const result = JSON.parse(response.data || '{}')
+ if (result.code === 0 && result.data) {
+ resolve(result.data)
+ return
+ }
+ reject(new Error(result.message || '上传失败'))
+ } catch (error) {
+ reject(new Error('上传响应解析失败'))
+ }
+ },
+ fail: (error) => {
+ reject(new Error(error.errMsg || '上传失败'))
+ }
+ })
+ })
+}
diff --git a/pages/mine/declare.vue b/pages/mine/declare.vue
new file mode 100644
index 0000000..994b1eb
--- /dev/null
+++ b/pages/mine/declare.vue
@@ -0,0 +1,355 @@
+
+
+
+
+ 我的申报
+ 汇总本地草稿、已提交记录和当前开放的申报项目。
+
+
+ {{ localRecords.length }}
+ 本地记录
+
+
+ {{ submittedCount }}
+ 已提交
+
+
+ {{ openDeclareList.length }}
+ 开放项目
+
+
+
+
+
+
+ 本地申报记录
+ 刷新
+
+
+ 当前还没有本地草稿或提交记录,可先前往申报页填写。
+
+
+
+
+
+ {{ item.title }}
+ {{ item.year || '未设置年度' }} · {{ item.group }}
+
+
+ {{ item.status }}
+
+
+ 保存时间:{{ item.savedAt || '-' }}
+
+ 继续编辑
+ 复制标题
+
+
+
+
+
+
+
+ 当前开放项目
+ 全部查看
+
+ 正在加载开放项目...
+ {{ errorText }}
+ 当前暂无开放的申报项目。
+
+
+
+
+ {{ getDeclareTitle(item) }}
+ {{ getDeclareGroup(item.module) }} · {{ item.year || '未设置年度' }}
+
+ 可申报
+
+ 时间范围:{{ formatDateTime(item.startTime) }} 至 {{ formatDateTime(item.endTime) }}
+
+ 进入申报
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/mine/index.vue b/pages/mine/index.vue
new file mode 100644
index 0000000..3d4ec50
--- /dev/null
+++ b/pages/mine/index.vue
@@ -0,0 +1,501 @@
+
+
+
+
+
+
+
+
+
+ {{ avatarText }}
+
+ {{ displayName }}
+ {{ profileRole }}
+
+
+
+
+ {{ item.value }}
+ {{ item.label }}
+
+
+ 退出登录
+
+
+
+
+
+ 常用入口
+
+
+ {{ item.icon }}
+ {{ item.title }}
+ {{ item.desc }}
+
+
+
+
+
+ 最近状态
+
+
+
+ {{ item.title }}
+ {{ item.desc }}
+
+ {{ item.tag }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/mine/manuscripts.vue b/pages/mine/manuscripts.vue
new file mode 100644
index 0000000..7e708a6
--- /dev/null
+++ b/pages/mine/manuscripts.vue
@@ -0,0 +1,422 @@
+
+
+
+
+ 我的稿件
+ 汇总当前账号创建或参与的稿件记录,可查看状态和内容摘要。
+
+
+ {{ manuscripts.length }}
+ 稿件总数
+
+
+ {{ publishedCount }}
+ 已通过/发布
+
+
+ {{ pendingCount }}
+ 待处理
+
+
+
+
+
+
+
+ 刷新
+ 去创作
+
+
+
+
+ 正在加载稿件...
+ 请稍候,正在同步当前账号的稿件记录。
+
+
+ 加载失败
+ {{ errorText }}
+
+
+ 暂无稿件
+ 当前账号还没有可展示的稿件,可前往文稿工作台开始生成。
+
+
+
+
+
+ {{ item.title || '未命名稿件' }}
+
+ 创建时间:{{ formatDateTime(item.createTime) }} · 更新时间:{{ formatDateTime(item.updateTime) }}
+
+
+
+ {{ getStatusMeta(item).text }}
+
+
+
+
+
+ {{ getContentPreview(item.content) }}
+
+ {{ expandedId === item.id ? '收起内容' : '查看内容' }}
+ 复制标题
+
+ {{ item.content || '暂无正文内容' }}
+
+
+
+
+
+
+
+
+
diff --git a/pages/mine/profile.vue b/pages/mine/profile.vue
new file mode 100644
index 0000000..30d4899
--- /dev/null
+++ b/pages/mine/profile.vue
@@ -0,0 +1,566 @@
+
+
+
+
+ 基础信息
+
+
+
+
+
+
+
+
+
+ 姓名
+
+
+
+
+
+ 昵称
+
+
+ 读取微信昵称
+
+
+
+ 性别
+
+
+ {{ editingGender || '请选择性别' }}
+
+
+
+
+
+
+ 手机号码
+ {{ profile.phone || '-' }}
+
+ 复制
+
+
+
+ 保存基础信息
+
+
+
+
+
+
+
+
+
diff --git a/pages/mine/qingma.vue b/pages/mine/qingma.vue
new file mode 100644
index 0000000..8b512e9
--- /dev/null
+++ b/pages/mine/qingma.vue
@@ -0,0 +1,344 @@
+
+
+
+
+ 我的“青马”
+ 查看青马工程报名记录、培养信息与当前审核状态。
+
+
+ {{ records.length }}
+ 记录总数
+
+
+ {{ approvedCount }}
+ 已通过
+
+
+ {{ pendingCount }}
+ 待跟进
+
+
+
+
+
+ 正在加载青马数据...
+ 请稍候,正在同步你的青马工程记录。
+
+
+ 加载失败
+ {{ errorText }}
+
+
+ 暂未查询到青马记录
+ 当前账号还没有青马工程报名或培养数据,可前往申报页查看开放项目。
+ 查看申报列表
+
+
+
+
+
+ {{ item.name || '未命名学员' }}
+ {{ item.year || '未设置年度' }} · 青马工程
+
+
+ {{ getStatusMeta(item).text }}
+
+
+
+
+ 学校院系
+ {{ item.schoolInfo || '-' }}
+
+
+ 手机号码
+ {{ item.phone || '-' }}
+
+
+ 团学职务
+ {{ item.leaguePosition || '-' }}
+
+
+ 综合成绩
+ {{ item.academicPerformance || '-' }}
+
+
+
+ 复制电话
+ 复制院系
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/mine/service.js b/pages/mine/service.js
new file mode 100644
index 0000000..6137145
--- /dev/null
+++ b/pages/mine/service.js
@@ -0,0 +1,187 @@
+import {
+ API_BASE_URL,
+ apiRequest,
+ getCurrentUser
+} from '../assistant/chat-service'
+import { clearAuthStorage, ensureLoggedIn, get, hasToken } from '../../utils/request'
+import { getModuleMeta } from '../../utils/gxmu/config'
+
+const LOCAL_DECLARE_PREFIX = 'gxmu_form_draft_'
+const LOCAL_PROFILE_OVERRIDE_PREFIX = 'mine_profile_override_'
+
+export { getCurrentUser }
+export { hasToken, ensureLoggedIn }
+
+export function logout() {
+ clearAuthStorage()
+}
+
+function getProfileOverrideStorageKey(userId) {
+ const normalizedUserId = String(userId || '').trim()
+ return `${LOCAL_PROFILE_OVERRIDE_PREFIX}${normalizedUserId || 'default'}`
+}
+
+export function getLocalProfileOverride(userId) {
+ try {
+ return uni.getStorageSync(getProfileOverrideStorageKey(userId)) || {}
+ } catch (error) {
+ return {}
+ }
+}
+
+export function saveLocalProfileOverride(userId, payload) {
+ const value = payload && typeof payload === 'object' ? payload : {}
+ uni.setStorageSync(getProfileOverrideStorageKey(userId), value)
+ return value
+}
+
+export function getUserProfile() {
+ return apiRequest({
+ url: `${API_BASE_URL}/auth/user`,
+ method: 'GET'
+ })
+}
+
+export function updateUserProfileData(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/system/user/update-data`,
+ method: 'POST',
+ data
+ })
+}
+
+export function listOrganizations(params) {
+ return get('/system/organization', params)
+}
+
+export function listManuscript(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/cms/manuscript`,
+ method: 'GET',
+ data: params
+ })
+}
+
+export function userPageQmgcForm(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/qmgc-form/userPage`,
+ method: 'GET',
+ data: params
+ })
+}
+
+export function listAvailableDeclare(params) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/declare`,
+ method: 'GET',
+ data: params
+ })
+}
+
+export function formatDateTime(value) {
+ if (!value) {
+ return '-'
+ }
+ const date = new Date(String(value).replace(/-/g, '/'))
+ if (Number.isNaN(date.getTime())) {
+ return value
+ }
+ const pad = (item) => String(item).padStart(2, '0')
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
+}
+
+export function getLatestReview(reviewList) {
+ if (!Array.isArray(reviewList) || !reviewList.length) {
+ return null
+ }
+ return reviewList[reviewList.length - 1] || null
+}
+
+export function getReviewStatusMeta(reviewList) {
+ const latest = getLatestReview(reviewList)
+ if (!latest) {
+ return {
+ text: '未审核',
+ tone: 'default'
+ }
+ }
+ if (latest.status === 1) {
+ return {
+ text: '通过',
+ tone: 'success'
+ }
+ }
+ if (latest.status === 0 || latest.status === 2) {
+ return {
+ text: '不通过',
+ tone: 'danger'
+ }
+ }
+ return {
+ text: '待审核',
+ tone: 'warning'
+ }
+}
+
+export function getManuscriptStatusMeta(record) {
+ const reviewMeta = getReviewStatusMeta(record && record.reviewList)
+ if (reviewMeta.text !== '未审核') {
+ return reviewMeta
+ }
+ if (record && Number(record.status) === 1) {
+ return {
+ text: '已发布',
+ tone: 'success'
+ }
+ }
+ if (record && Number(record.status) === 0) {
+ return {
+ text: '待审核',
+ tone: 'warning'
+ }
+ }
+ return {
+ text: '未审核',
+ tone: 'default'
+ }
+}
+
+export function getLocalDeclareRecords() {
+ try {
+ const storageInfo = uni.getStorageInfoSync()
+ const keys = (storageInfo.keys || []).filter((key) => key.indexOf(LOCAL_DECLARE_PREFIX) === 0)
+ return keys
+ .map((key) => {
+ const draft = uni.getStorageSync(key)
+ if (!draft || !draft.formData) {
+ return null
+ }
+ const moduleCode = draft.moduleCode || ''
+ if (!moduleCode) {
+ return null
+ }
+ const moduleMeta = getModuleMeta(moduleCode)
+ const year = String((draft.formData && draft.formData.year) || '').trim()
+ return {
+ key,
+ moduleCode,
+ title: (moduleMeta && moduleMeta.title) || '未命名申报',
+ group: (moduleMeta && moduleMeta.group) || '申报项目',
+ icon: (moduleMeta && moduleMeta.icon) || '申',
+ year,
+ savedAt: draft.savedAt || '',
+ status: draft.status === 'submitted' ? '已提交' : '草稿',
+ formData: draft.formData,
+ route: `/pages/gxmu/form?code=${encodeURIComponent(moduleCode)}&year=${encodeURIComponent(year)}&declareTitle=${encodeURIComponent((moduleMeta && moduleMeta.title) || '申报表')}`
+ }
+ })
+ .filter(Boolean)
+ .sort((left, right) => {
+ const leftTime = new Date(String((left && left.savedAt) || '').replace(/-/g, '/')).getTime()
+ const rightTime = new Date(String((right && right.savedAt) || '').replace(/-/g, '/')).getTime()
+ return (Number.isNaN(rightTime) ? 0 : rightTime) - (Number.isNaN(leftTime) ? 0 : leftTime)
+ })
+ } catch (error) {
+ return []
+ }
+}
diff --git a/pages/tygl/index.vue b/pages/tygl/index.vue
new file mode 100644
index 0000000..e9b6ea2
--- /dev/null
+++ b/pages/tygl/index.vue
@@ -0,0 +1,1260 @@
+
+
+
+
+
+
+
+ 基础信息表单
+
+
+
+
+
+ {{ field.label }}
+ *
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || (nationOptions.length ? field.placeholder : '民族加载中') }}
+
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+
+ {{ getFieldDisplayValue(field) || field.placeholder }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/tygl/service.js b/pages/tygl/service.js
new file mode 100644
index 0000000..5ae9c95
--- /dev/null
+++ b/pages/tygl/service.js
@@ -0,0 +1,47 @@
+import { get } from '../../utils/request'
+import { API_BASE_URL, apiRequest, getCurrentUser } from '../assistant/chat-service'
+
+export { getCurrentUser }
+
+export function listDictData(params) {
+ return get('/system/dict-data', params)
+}
+
+export function listOrganizations(params) {
+ return get('/system/organization', params)
+}
+
+export function listColleges(params) {
+ return get('/gxmu/college', params)
+}
+
+export function listClasses(params) {
+ return get('/gxmu/class', params)
+}
+
+export function getUserProfile() {
+ return apiRequest({
+ url: `${API_BASE_URL}/auth/user`,
+ method: 'GET'
+ })
+}
+
+export function getCurrentTyglForm() {
+ return get('/gxmu/tygl-form/current')
+}
+
+export function saveTyglForm(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/tygl-form`,
+ method: 'POST',
+ data
+ })
+}
+
+export function updateTyglForm(data) {
+ return apiRequest({
+ url: `${API_BASE_URL}/gxmu/tygl-form`,
+ method: 'PUT',
+ data
+ })
+}
diff --git a/static/indexBg.jpg b/static/indexBg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..0637d7b61d87696118021bd119cf190cedbf7c50
GIT binary patch
literal 3701
zcmah~O>87b6|O1oqE@e$^(;<|9OM-3B-`}j>7E&ny)%mOT05~=2}jPd5C_>@DDT4UGAhWL3AG0sMblkej*v*>`GuTYV|6uw0QSPFIPBG2
zw=*a-4!U>zLbKa;j~hL=Snyo-;`VW`(LD5r;*S4XtFvYO>z#Kk(K^_&zE#=t_Ifw`
zd#$fO>ige(^z!ZIqr+zPz}o(rc=5P)-0rpgVM83Z?{@~Z<1I@&uVGAT*AjZm@Nmo8
zp{U~3y?t?`+xJDaP+V(zURi8b3)PLP*SNNMxA|33@=6ugE4$vtTFI+byjpQXq+%gp
z|KM)zR(&@OhuM~up6kJb2ZaaaLbv~#TdY>Au2*tPr8VqW8$9d`8^>#%!Ro|A-5)gj
zt=_QJ?FjPNxYIovZdm}EoTA;Ex;>Sy%*MUF|Gl-{CJwaQ!SI$p!+WaZ!R?1V-@WAz
zx<~z{kL{~u+^gN_`;B3@f4kegKOu7eUU%3X-0Sv4X|qri_Fkje>X7Cu+GKC9cC#}W
zHaboJW_`AAZN1w(YWtnx
z#P(ojyK|;36-2v-$aTNp`hkD2+wZo8K6R~iHkQpZ{iU`CXJff`rmYJwF6B0p>xl{l
zM8j$EVlpj%zk{0ZqqxWaWS`e1%MMP^M7i-t?1yaO!i5X-7Z&E{7nUwvytMSp;=;n>
zGtVxOJiD^A3|U%PS$+P>^Q$YaTQ0lq^(Q5lzjP`8h5S>OFF&=I$Fscn^wW#WFDx&A
zX?ghtZ*>K->Rl~dxpJj&wNmlCO6B_X?W~LO3CkNfasJ#~&SE^Do6G0Me`K$+9Leko
z0A4=#xlijzyP$Vwx8^SAci`z$_AGxnH~uS|pUWZ4T%K*S|ETc9P|TEeHqI$ynbD2*
zU&-$*oZneI$Ik87bNjfGW^(?MZ~yzfmwrF|#bNyS=e~RN(cAq`Dz^$h|Iyl?A1{4p
zxV!Prmw&VV*8Rs9zyI5xyfHfb>5o6Gy!@x-?yujd<<~#_+3(IfQZO^Lxpo*U!6KV+
zlQG4(Z8$URG%`cRLunh##KTw|
z0T6^oGL+C5u?Z{=07#~6lSZ~t3d8p}Ib*^mP-hFQ7^5#l!(j$jOfY64F0BMo;(sDI
zdl=FY6y?X1ZzjArfad_lloiEnB~5}-e&u^t1pxs3geQ^xX|2P&5&ML;;pGSkS^g
zun6nS3E9B`A1Q>JsrAVWy~ZpoAsrzKjVhOF&_rZ>ptS=T$n^O7IO&<}w3Qs&qP(Do
zOw9)9fmhU*e4VYoPZbFH3=ewKY{fylXhh&bmrW2U#KyruQ_QB#B*`Q_oYG^itC)sp
zV8%yDf+Fy&{UMGmBCtY71<+Kaq7)}GEgREus2aF5C_)2yW2V5f+g
zNd$tPv~(S9gI<{!XAP(0U;b@Air!8e4tSp^HSj2HsxN#pWu~UqG>9p*zU~sJ%tEFt
zNnrF7;~rB_V4(NqXXFno0g}`o8f&s+LLug+!Z$#$`!4@%u+h(dYPYru>C66_Q~
Tw~|D73&eVq{W010`0;-M-+YJ7
literal 0
HcmV?d00001
diff --git a/static/logo.png b/static/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..b5771e209bb677e2ebd5ff766ad5ee11790f305a
GIT binary patch
literal 4023
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