shang %!s(int64=2) %!d(string=hai) anos
achega
dfa24b538e
Modificáronse 100 ficheiros con 23336 adicións e 0 borrados
  1. 4 0
      .gitignore
  2. 93 0
      App.vue
  3. 535 0
      README.md
  4. 50 0
      chuanCheng_fenbao/search/search.vue
  5. 184 0
      colorui/animation.css
  6. 76 0
      colorui/components/cu-custom.vue
  7. 139 0
      colorui/components/curry-slide.vue
  8. 410 0
      colorui/components/curry-swiper.vue
  9. 1226 0
      colorui/icon.css
  10. 4037 0
      colorui/main.css
  11. 35 0
      common/WXBizDataCrypt.js
  12. 0 0
      common/app.css
  13. 75 0
      common/cache.js
  14. 4 0
      common/city.area.js
  15. 187 0
      common/common.css
  16. 146 0
      common/common.scss
  17. 102 0
      common/dateTimePicker.js
  18. 493 0
      common/fa.mixin.js
  19. 40 0
      common/fa.style.mixin.js
  20. 63 0
      common/fa.weixin.mixin.js
  21. 352 0
      common/html-parser.js
  22. 157 0
      common/iconfont.css
  23. 72 0
      common/share.js
  24. 1448 0
      common/uni.css
  25. 466 0
      common/util.js
  26. 202 0
      components/course-item/course-item.vue
  27. 73 0
      components/mn_yindaoye.vue
  28. 78 0
      components/mntabBar/mntabBar.vue
  29. 153 0
      components/quick-cart/quick-cart.vue
  30. 209 0
      components/schedule-item/schedule-item.vue
  31. 385 0
      config/api.js
  32. 647 0
      config/common.js
  33. 19 0
      config/config.js
  34. 83 0
      config/db.js
  35. 129 0
      index_fenbao/cs_liebiao/cs_liebiao.vue
  36. 215 0
      index_fenbao/feiyi/feiyi.vue
  37. 124 0
      index_fenbao/jianzhu/jianzhu.vue
  38. 216 0
      index_fenbao/minNanyu/minNanyu.vue
  39. 197 0
      index_fenbao/minNanyu/yinPinLieBiao.vue
  40. 213 0
      index_fenbao/minsu/minsu.vue
  41. 264 0
      index_fenbao/minsu/ms_wenZhang.vue
  42. 86 0
      index_fenbao/mn_jingshen/mn_jingshen.vue
  43. 614 0
      index_fenbao/mn_wenhua/mn_wenhua.vue
  44. 20 0
      jiyi_fenbao/aaa.vue
  45. 22 0
      jiyi_fenbao/bb/bb.vue
  46. 147 0
      main.js
  47. 170 0
      manifest.json
  48. 14 0
      mixins/auth.js
  49. 102 0
      mixins/common.js
  50. 31 0
      mixins/goods.js
  51. 30 0
      node_modules/jweixin-module/README.md
  52. 1 0
      node_modules/jweixin-module/lib/index.js
  53. 26 0
      node_modules/jweixin-module/package.json
  54. 418 0
      pages.json
  55. 199 0
      pages/chuanCheng/chuanCheng.vue
  56. 1094 0
      pages/course/detail.vue
  57. 373 0
      pages/course/index.vue
  58. 726 0
      pages/index/index.vue
  59. 362 0
      pages/jiyi/jiyi.vue
  60. 369 0
      pages/order/preview.vue
  61. 698 0
      pages/schedule/detail.vue
  62. 636 0
      pages/schedule/index.vue
  63. 205 0
      pages/teacher/detail.vue
  64. 912 0
      pages/user/index.vue
  65. 435 0
      pages/user/learn.vue
  66. 420 0
      pages/user/login.vue
  67. 735 0
      pages/xueYuan/xueYuan.vue
  68. 57 0
      service/api/common.js
  69. 105 0
      service/api/examine.js
  70. 98 0
      service/api/gift.js
  71. 57 0
      service/api/mock.js
  72. 13 0
      service/api/page.js
  73. 163 0
      service/api/user.js
  74. 7 0
      service/config.js
  75. 234 0
      service/request/main.js
  76. 156 0
      service/request/request.js
  77. BIN=BIN
      static/image/13-系统消息-icon.png
  78. BIN=BIN
      static/image/2019-07-03000000000018.png
  79. BIN=BIN
      static/image/BSV.png
  80. BIN=BIN
      static/image/baseLogo.png
  81. BIN=BIN
      static/image/cs_bjx.png
  82. BIN=BIN
      static/image/flower.png
  83. BIN=BIN
      static/image/fx.png
  84. BIN=BIN
      static/image/hd.png
  85. BIN=BIN
      static/image/hh.png
  86. BIN=BIN
      static/image/home_a.png
  87. BIN=BIN
      static/image/hs.png
  88. BIN=BIN
      static/image/jf.png
  89. BIN=BIN
      static/image/kctp.png
  90. BIN=BIN
      static/image/mn.png
  91. BIN=BIN
      static/image/star.png
  92. BIN=BIN
      static/image/sz.png
  93. BIN=BIN
      static/image/tg.png
  94. BIN=BIN
      static/image/传统吉祥纹样17.png
  95. BIN=BIN
      static/image/余额.png
  96. BIN=BIN
      static/image/圆角矩形 840 拷贝.png
  97. BIN=BIN
      static/image/椭圆 839.png
  98. BIN=BIN
      static/image/账期 拷贝.png
  99. BIN=BIN
      static/image/账期(1).png
  100. 0 0
      static/image/账期(2).png

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+.DS_Store
+/dist
+/unpackage
+/.hbuilderx/

+ 93 - 0
App.vue

@@ -0,0 +1,93 @@
+<script>
+import md5Libs from '@/uni_modules/uview-ui/libs/function/md5';
+import Vue from 'vue';
+import { getConfig } from '@/service/api/common.js';
+export default {
+	created() {
+		// #ifdef APP-PLUS
+		plus.navigator.closeSplashscreen();
+		// #endif
+	},
+	onLaunch: async function () {
+		// console.log('App Launch');
+		/* 隐藏默认tabBar */
+		uni.hideTabBar();
+
+		//加载配置
+
+		uni.getSystemInfo({
+			success: function (e) {
+				// #ifndef MP
+				Vue.prototype.StatusBar = e.statusBarHeight;
+				if (e.platform == 'android') {
+					Vue.prototype.CustomBar = e.statusBarHeight + 50;
+				} else {
+					Vue.prototype.CustomBar = e.statusBarHeight + 45;
+				}
+				// #endif
+
+				// #ifdef MP-WEIXIN
+				Vue.prototype.StatusBar = e.statusBarHeight;
+				let custom = wx.getMenuButtonBoundingClientRect();
+				Vue.prototype.Custom = custom;
+				Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
+				// #endif
+
+				// #ifdef MP-ALIPAY
+				Vue.prototype.StatusBar = e.statusBarHeight;
+				Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
+				// #endif
+			}
+		});
+		// getConfig().then(([err, res]) => {
+		// 	// console.log('getConfig', err, res);
+		// 	if (!err) {
+		// 		this.$store.commit('setGlobalConfig', res);
+		// 		// 当前活动无效
+		// 		if (res.activity_invalid) {
+		// 			this.$store.commit('delActivityId'); // 删除活动ID
+		// 			// 重新加载配置
+		// 			getConfig().then(([err, res]) => {
+		// 				// console.log('getConfig reload', err, res);
+		// 				if (!err) {
+		// 					this.$store.commit('setGlobalConfig', res);
+		// 				}
+		// 			});
+		// 		}
+		// 	}
+		// });
+
+		// let res = await this.$api.getConfig();
+		//console.log(res);
+		// if (!res.code) {
+		// 	return;
+		// }
+		// Vue.prototype.vuex_config = res.data;
+		// this.vuex_config = res.data;
+	},
+	onShow: function () {
+		// console.log('App 开启');
+	},
+	onHide: function () {
+		console.log('App 关闭');
+	},
+	/* 隐藏默认tabBar */
+	onLoad: function () {
+		uni.hideTabBar();
+	}
+};
+</script>
+
+<style lang="scss">
+@import 'colorui/main.css';
+@import 'colorui/icon.css';
+// @import '@/uni_modules/uview-ui/index.scss';
+// // @import './GraceUI5/css/graceUI.css';
+// // @import './GraceUI5/skin/black.css';
+// /* 加载图标字体 - 条件编译模式 */
+// /* #ifdef APP-PLUS-NVUE */
+// // .gui-icons {
+// // 	font-family: graceIconfont;
+// // }
+// /* #endif */
+</style>

+ 535 - 0
README.md

@@ -0,0 +1,535 @@
+# maramlee-waterfalls-flow-nav 使用
+
+## 前言
+
+maramlee-waterfalls-flow-nav 是基于 maramlee-waterfalls-flow 为了解决很多小伙伴儿实际场景使用瀑布流需要使用 nav 切换数据而封装的插件。
+
+没错,使用这个插件,原来的 [maramlee-waterfalls-flow](https://ext.dcloud.net.cn/plugin?id=2714#rating) 插件也是可以继续用的。
+
+## 使用方式
+
+我的插件代码中有详细的说明,如果想要了解更多,请查看插件代码中的注释。
+
+### 首先在 `script` 中定义数据和方法等
+
+```javascript
+import waterfallsFlowNav from "@/components/maramlee-waterfalls-flow-nav/maramlee-waterfalls-flow-nav.vue";
+export default {
+  components: { waterfallsFlowNav },
+  data() {
+    return {
+      navIndex: 0, // 默认获取的第几项数据
+      navData: [
+        /**
+         * nav 对应的数据
+         * 注意插件里面下面两个 prop 值的设置:
+         *   |- list_key: { type: String, default: "key" },
+         *   |- list_label: { type: String, default: "label" },
+         */
+        { key: "one", label: "nav 1" },
+        { key: "two", label: "nav 2" },
+        { key: "three", label: "nav 3" },
+      ],
+    };
+  },
+  /**
+   * 上拉加载 这很重要
+   */
+  onReachBottom() {
+    /**
+     * 这里的 waterfalls_flow_nav 值记得与你定义的 ref 值对应
+     */
+    this.$refs.waterfalls_flow_nav.getList();
+  },
+
+  methods: {
+    /**
+     * 此方法为 视图层响应子组件 add-data 事件 的方法
+     */
+    getListHandle() {
+      /**
+       * mockData 为模拟数据
+       * 实际应为接口返回的数据
+       */
+      const mockData = {
+        total_page: 1,
+        list: [
+          {
+            id: 1,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599475741266&di=e36d6c01c93320e2ba1504d8357248f4&imgtype=0&src=http%3A%2F%2Fa0.att.hudong.com%2F30%2F29%2F01300000201438121627296084016.jpg",
+            title: "可爱的小猫咪呀",
+            text:
+              "小小的猫咪,甚是呆萌,呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌",
+          },
+        ],
+      };
+      /**
+       * ================= !important =================
+       * 模拟请求成功
+       * 实际场景中是 request 请求哈
+       */
+      setTimeout(() => {
+        this.$refs.waterfalls_flow_nav.successSetData(
+          mockData.list,
+          mockData.total_page
+        );
+      }, 1000);
+      /**
+       * ================= !important =================
+       * 若失败,记得调用失败回调方法
+       * 此例如下:
+       *   this.$refs.waterfalls_flow_nav.failMoreBack();
+       */
+    },
+  },
+};
+```
+
+### 再在 `template` 中使用组件
+
+注意,下面的数据使用,都是基于上一条的数据定义,记得对照着看。
+
+#### 可以只是渲染图片,不需要其他
+
+```vue
+<template>
+  <waterfallsFlowNav
+    ref="waterfalls_flow_nav"
+    v-model="navIndex"
+    :navData="navData"
+    :single="true"
+    @add-data="getListHandle"
+  />
+</template>
+```
+
+#### 有插槽(自定义内容)的情况要分情况使用
+
+##### 若只适配 app、h5 端,利用作用域插槽
+
+注意:`item` 包含 `list` 对应的数据项,可以随意搭配、自定义使用。
+
+```vue
+<template>
+  <waterfallsFlowNav
+    ref="waterfalls_flow_nav"
+    v-model="navIndex"
+    :navData="navData"
+    :single="true"
+    @add-data="getListHandle"
+  >
+    <template v-slot:default="item">
+      <!-- 此处添加插槽内容 -->
+      <!-- <view class="cnt">
+          <view class="title">{{item.title}}</view>
+          <view class="text">{{item.text}}</view>
+        </view> -->
+    </template>
+  </waterfallsFlowNav>
+</template>
+```
+
+##### 若只适配微信小程序,利用小程序插槽
+
+注意:微信小程序没有动态模板,也和 vue 的插槽使用方式不一样。
+
+由于小程序的复杂性,又不想数据提到外层,我在插件里面定义了一个 `weixin_type` prop ,用于小程序不同模板控制。小程序使用时,需使用者自己去配置 maramlee-waterfalls-flow-nav 插件的模板内容。
+
+小程序使用步骤如下:
+
+1. 第一步:页面中 template 应用插件
+
+```vue
+<template>
+  <waterfallsFlowNav
+    ref="waterfalls_flow_nav"
+    v-model="navIndex"
+    :navData="navData"
+    @add-data="getListHandle"
+  />
+</template>
+```
+
+2. 第二步:修改 maramlee-waterfalls-flow-nav 插件图片下方模板
+
+**注意:这里修改的是插件 components/maramlee-waterfalls-flow-nav/maramlee-waterfalls-flow-nav.vue**
+
+如插件中 53 行注释的类似,script 标签中 116-126 行有详细注释,请自行查看。
+
+```vue
+<!--
+  取自 maramlee-waterfalls-flow-nav 组件中 36-56 行代码
+ -->
+<!--  #ifdef  MP-WEIXIN -->
+<template v-if="!single">
+  <view v-for="(item, index2) of obj.list" :key="index2" slot="slot{{index2}}">
+    <view v-if="weixin_type === 'default'" class="cnt">
+      <view class="title">{{ item.title }}</view>
+      <view class="text">{{ item.text }}</view>
+    </view>
+    <!-- 
+          ==========================================
+          weixin_type 为 "two" 时样例代码新增示例
+          用时记得取消注释
+          ==========================================
+         -->
+    <!-- <view v-else-if="weixin_type === 'two'">我是类型为 two 的样子哟</view> -->
+  </view>
+</template>
+<!--  #endif -->
+```
+
+```javascript
+// 取自 maramlee-waterfalls-flow-nav 组件 116-133 行代码
+/**
+ * =================================================
+ * 微信小程序特殊自定义不同类型下方内容
+ * 默认为 "default"
+ * 使用示例,例如新增一个 "two" 类型:
+ *   1.修改 weixin_type 的 validator:
+ *     |- validator: (value) => ["default","two"].indexOf(value) !== -1,
+ *
+ *   2. 上方代码块处新增类型为 two 的结构代码,详情请看上方代码处
+ * =================================================
+ */
+// #ifdef MP-WEIXIN
+weixin_type: {
+  type: String,
+  default: "default",
+  validator: (value) => ["default"].indexOf(value) !== -1,
+},
+// #endif
+```
+
+##### 若需要同时兼容 app、h5、微信小程序,则需条件渲染
+
+1. 首先使用 适配 app、h5 的方式模板。
+
+```vue
+<template>
+  <waterfallsFlowNav
+    ref="waterfalls_flow_nav"
+    v-model="navIndex"
+    :navData="navData"
+    :single="true"
+    @add-data="getListHandle"
+  >
+    <!-- #ifndef  MP-WEIXIN -->
+    <template v-slot:default="item">
+      <!-- 此处添加插槽内容 -->
+      <!-- <view class="cnt">
+          <view class="title">{{item.title}}</view>
+          <view class="text">{{item.text}}</view>
+        </view> -->
+    </template>
+    <!-- #endif -->
+  </waterfallsFlowNav>
+</template>
+```
+
+2. 再与上一条小程序适配一样的方式适配即可,这里不再赘述。
+
+## 属性说明
+
+| 属性名      | 类型    | 默认值    | 是否必传 | 说明                                                        | 平台支持         |
+| ----------- | ------- | --------- | -------- | ----------------------------------------------------------- | ---------------- |
+| navData     | Array   | -         | 是       | 渲染 nav 的列表,一般格式为:[{ key: "one", label: "nav" }] | 全               |
+| navIndex    | Number  | -         | 是       | nav 高亮的 index,一般页面中设置 0                          | 全               |
+| list_key    | String  | key       | 否       | 与 navData 项的 key 对应                                    | 全               |
+| list_label  | String  | label     | 否       | 与 navData 项的 label 对应                                  | 全               |
+| mountedGet  | Boolean | true      | 否       | 插件 mounted 时是否请求数据                                 | 全               |
+| offset      | Number  | 10        | 否       | 单位是 px                                                   | 全               |
+| idKey       | String  | id        | 否       | 列表渲染的 key 的键名,值必须唯一                           | 全               |
+| imageSrcKey | String  | image_url | 否       | 图片 src 的键名                                             | 全               |
+| cols        | Number  | 2         | 否       | 列数,值必须不小于 2                                        | 全               |
+| single      | Boolean | false     | 否       | 是否是单独的渲染图片,只控制图片圆角而已                    | 全               |
+| listStyle   | Object  | -         | 否       | 单个展示项的样式                                            | 微信小程序不支持 |
+| imageStyle  | Object  | -         | 否       | 图片的样式                                                  | 全               |
+
+## 事件说明
+
+| 事件名       | 说明                           | 返回值           |
+| ------------ | ------------------------------ | ---------------- |
+| @add-data    | 加载数据事件,很重要的一个事件 | 无               |
+| @nav-click   | nav 点击时触发                 | 点击项对应 index |
+| @wapper-lick | 单项点击事件                   | 单项对应数据     |
+| @image-click | 图片点击事件                   | 单项对应数据     |
+| @image-load  | 所有图片渲染完成触发           | -                |
+
+### add-data 事件详解
+
+此事件为解决不同的人封装的请求方法不同,不同接口请求的数据不同而产生。必需要配合很重要的两个组件方法:`successSetData`、`failMoreBack` 使用。
+
+```javascript
+getListHandle() {
+  const mockData = {
+    total_page: 1,
+    list: [
+      {
+        id: 1,
+        image_url:
+          "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599475741266&di=e36d6c01c93320e2ba1504d8357248f4&imgtype=0&src=http%3A%2F%2Fa0.att.hudong.com%2F30%2F29%2F01300000201438121627296084016.jpg",
+        title: "可爱的小猫咪呀",
+        text:
+          "小小的猫咪,甚是呆萌,呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌",
+      },
+    ],
+  };
+  /**
+   * ================= !important =================
+   * 模拟请求成功
+   * 实际场景中是 request 请求哈
+   */
+  setTimeout(() => {
+    this.$refs.waterfalls_flow_nav.successSetData(
+      mockData.list,
+      mockData.total_page
+    );
+  }, 1000);
+  /**
+   * ================= !important =================
+   * 若失败,记得调用失败回调方法
+   * 此例如下:
+   *   this.$refs.waterfalls_flow_nav.failMoreBack();
+   */
+},
+```
+
+## 组件方法
+
+| 方法名         | 说明                           | 参数                | 使用场景                            |
+| -------------- | ------------------------------ | ------------------- | ----------------------------------- |
+| getList        | 获取列表                       | isRefresh, navClick | 数据获取                            |
+| refresh        | 刷新对应的 moreNavIndex 数据   | -                   | 下拉刷新                            |
+| successSetData | 数据请求获取成功后设置组件数据 | list, total_page    | add-data 事件中,数据请求成功后调用 |
+| failMoreBack   | 数据请求获取失败后设置组件数据 | -                   | add-data 事件中,数据请求失败后调用 |
+| initNavLists   | 初始化插件内 moreNavLists 数据 | -                   | 使用情况比较少,需要时即调用        |
+
+### getList 方法说明
+
+获取列表方法
+
+`this.$refs.waterfalls_flow_nav.getList();`
+
+#### 参数
+
+1. isRefresh
+
+   默认 `false`
+
+   是否强制刷新,若为 `true`,即请求之前先把 `moreNavIndex` 对应的原来的数据清空,常用在下拉刷新
+
+2. navClick
+
+   默认 `false`
+
+   是否是 nav 点击,此值区分一般的加载和点击 nav 加载,由于 nav 点击,如果已经有数据,即无需加载数据
+
+#### 用法示例
+
+1. 页面中用于上拉加载更多(`onReachBottom`)中:`this.$refs.waterfalls_flow_nav.getList();`
+2. 页面中用于重新加载此项:`this.$refs.waterfalls_flow_nav.getList(true);`
+
+### successSetData 使用
+
+**注意查看 add-data 事件详解**
+
+请求数据成功后调用
+
+`this.$refs.waterfalls_flow_nav.successSetData(list, total_page);`
+
+#### 参数
+
+1. list
+
+   必传
+
+   请求返回需要渲染的 list 数据
+
+2. total_page
+
+   必传
+
+   请求返回的总页数
+
+### initNavLists 与 refresh 比较
+
+initNavLists 是初始化 `moreNavLists` 的数据,即所有的数据清空。
+
+refresh 只清空 `moreNavIndex` 对应即当前选择的 nav 项的数据。
+
+## 提示
+
+如果你看到了这里,还有以下情况:
+
+1. 插件使用方法有不懂的地方;
+2. 插件本身研究不明白的地方;
+3. 觉得插件有待提高的建议;
+4. 或者其他你遇到的问题;
+5. 纯粹想前端技术交流也行。
+
+可以加我微信,微信号:`ml-maramlee`,备注以`ml-${姓名}-${1}`的形式,其中 1、2、3、4 对应前面的情况(前端都看得懂哈),例如:`ml-maram-1`。
+
+**注:人家是有脾气的,不这样备注不给加哟~**
+
+**再注:觉得好用记得收藏、评论,这样可以让更多人看到,让更多人受益。当然,解答不易,欢迎赞赏。**
+
+**申明:主要是看到评论里有或多或少的问题,加微信有助于解决问题,只接受技术交流,其他请勿扰。**
+
+## 使用样例
+
+pages/nav/nav.vue
+
+```vue
+<template>
+  <view class="content">
+    <waterfallsFlowNav
+      ref="waterfalls_flow_nav"
+      v-model="navIndex"
+      :navData="navData"
+      @add-data="getListHandle"
+    >
+      <template v-slot:default="item">
+        <view class="cnt">
+          <view class="title">{{ item.title }}</view>
+          <view class="text">{{ item.text }}</view>
+        </view>
+      </template>
+    </waterfallsFlowNav>
+  </view>
+</template>
+<script>
+import waterfallsFlowNav from "@/components/maramlee-waterfalls-flow-nav/maramlee-waterfalls-flow-nav.vue";
+export default {
+  components: { waterfallsFlowNav },
+  data() {
+    return {
+      navIndex: 0,
+      navData: [
+        { key: "one", label: "nav 1" },
+        { key: "two", label: "nav 2" },
+        { key: "three", label: "nav 3" },
+      ],
+    };
+  },
+  /**
+   * 上拉加载
+   * 这很重要
+   */
+  onReachBottom() {
+    this.$refs.waterfalls_flow_nav.getList();
+  },
+  methods: {
+    getListHandle() {
+      const mockData = {
+        total_page: 1,
+        list: [
+          {
+            id: 1,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599475741266&di=e36d6c01c93320e2ba1504d8357248f4&imgtype=0&src=http%3A%2F%2Fa0.att.hudong.com%2F30%2F29%2F01300000201438121627296084016.jpg",
+            title: "可爱的小猫咪呀",
+            text:
+              "小小的猫咪,甚是呆萌,呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌呆萌",
+          },
+          {
+            id: 2,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599475934834&di=7a37b8d628252c4aced6ed0decba9442&imgtype=0&src=http%3A%2F%2Fa3.att.hudong.com%2F43%2F74%2F01300000164151121808741085971.jpg",
+            title: "迪士尼动画",
+            text: "迪士尼动画之……",
+          },
+          {
+            id: 3,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476083909&di=a5debff35edec5de105bc105d6fdbce3&imgtype=0&src=http%3A%2F%2Fa2.att.hudong.com%2F77%2F77%2F01300000336597125202779973172.jpg",
+            title: "火箭",
+            text: "火箭升空瞬间,宏伟壮观啊",
+          },
+          {
+            id: 5,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476129760&di=7a3db0b14f6a74240bbfa7922ba22f45&imgtype=0&src=http%3A%2F%2Fa4.att.hudong.com%2F82%2F55%2F01300000349330124003555691086.jpg",
+            title: "华佗",
+            text: "华佗人物画像 中国画 线条画 毛笔画 彩色画",
+          },
+          {
+            id: 6,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476215687&di=97c2bbf6f3a1a3e2a6a2dc77dfe4bea7&imgtype=0&src=http%3A%2F%2Fa4.att.hudong.com%2F72%2F82%2F19300000009075130804824786610.jpg",
+            title: "恐龙",
+            text: "恐龙来啦",
+          },
+          {
+            id: 7,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476258176&di=29622b0f0cfd659aecebabaae352d02c&imgtype=0&src=http%3A%2F%2F1882.img.pp.sohu.com.cn%2Fimages%2Fblog%2F2011%2F3%2F25%2F13%2F13%2Fu48513077_12fa4ba953ag213.jpg",
+            title: "手",
+            text: "什么?",
+          },
+          {
+            id: 8,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476300222&di=49712f992d8f7bbb1a5851eced71cbe2&imgtype=0&src=http%3A%2F%2Fa2.att.hudong.com%2F71%2F56%2F16300000988660128426569668958.jpg",
+            title: "百年好合",
+            text: "百年好合 结婚 庚帖 二次元",
+          },
+          {
+            id: 9,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476416001&di=ea1a1f8f9b1274d39c05af3e48041e6a&imgtype=0&src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F12420002963%2F641",
+            title: "5G",
+            text: "5G 来啦",
+          },
+          {
+            id: 12,
+            image_url:
+              "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599476567983&di=040976a1cd1a6e5510a237c57bdcff06&imgtype=0&src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F12421051168%2F641",
+            title: "王者荣耀",
+            text: "王者荣耀 龙 快来打龙 请求集合",
+          },
+        ],
+      };
+      /**
+       * ================= !important =================
+       * 模拟请求成功
+       * 实际场景中是 request 请求哈
+       */
+      setTimeout(() => {
+        this.$refs.waterfalls_flow_nav.successSetData(
+          mockData.list,
+          mockData.total_page
+        );
+      }, 1000);
+      /**
+       * ================= !important =================
+       * 若失败,记得调用失败回调方法
+       * 此例如下:
+       *   this.$refs.waterfalls_flow_nav.failMoreBack();
+       */
+    },
+  },
+};
+</script>
+<style>
+page {
+  background-color: #eee;
+}
+</style>
+<style lang="scss" scoped>
+.content {
+  padding: 10px;
+  .cnt {
+    padding: 10px;
+    .title {
+      font-size: 16px;
+    }
+    .text {
+      font-size: 14px;
+      margin-top: 5px;
+    }
+  }
+}
+</style>
+```

+ 50 - 0
chuanCheng_fenbao/search/search.vue

@@ -0,0 +1,50 @@
+<template>
+	<view class="box">
+		<u-navbar title="搜索" :autoBack="true" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="box_search" @click="searchBtn">
+			<u-search :shape="square" v-model="val" bgColor="#efefef" :showAction="false" height="70rpx"></u-search>
+			<view class="sousuo">搜索</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			val: ''
+		};
+	},
+	methods: {
+		searchBtn() {}
+	}
+};
+</script>
+
+<style>
+.box {
+	height: auto;
+	width: 100%;
+	background-color: #f8f8f8;
+	background-attachment: fixed;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+.box_search {
+	display: flex;
+	margin: 20rpx 32rpx 0 46rpx;
+	width: 650rpx;
+	height: 80rpx;
+}
+
+.sousuo {
+	width: 118rpx;
+	height: 80rpx;
+	text-align: center;
+	color: #ffffff;
+	line-height: 80rpx;
+	background: #ca5642;
+	border-radius: 20rpx;
+}
+</style>

+ 184 - 0
colorui/animation.css

@@ -0,0 +1,184 @@
+/* 
+  Animation 微动画  
+  基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
+ */
+
+/* css 滤镜 控制黑白底色gif的 */
+.gif-black{  
+  mix-blend-mode: screen;  
+}
+.gif-white{  
+  mix-blend-mode: multiply; 
+}
+
+
+/* Animation css */
+[class*=animation-] {
+    animation-duration: .5s;
+    animation-timing-function: ease-out;
+    animation-fill-mode: both
+}
+
+.animation-fade {
+    animation-name: fade;
+    animation-duration: .8s;
+    animation-timing-function: linear
+}
+
+.animation-scale-up {
+    animation-name: scale-up
+}
+
+.animation-scale-down {
+    animation-name: scale-down
+}
+
+.animation-slide-top {
+    animation-name: slide-top
+}
+
+.animation-slide-bottom {
+    animation-name: slide-bottom
+}
+
+.animation-slide-left {
+    animation-name: slide-left
+}
+
+.animation-slide-right {
+    animation-name: slide-right
+}
+
+.animation-shake {
+    animation-name: shake
+}
+
+.animation-reverse {
+    animation-direction: reverse
+}
+
+@keyframes fade {
+    0% {
+        opacity: 0
+    }
+
+    100% {
+        opacity: 1
+    }
+}
+
+@keyframes scale-up {
+    0% {
+        opacity: 0;
+        transform: scale(.2)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes scale-down {
+    0% {
+        opacity: 0;
+        transform: scale(1.8)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes slide-top {
+    0% {
+        opacity: 0;
+        transform: translateY(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes slide-bottom {
+    0% {
+        opacity: 0;
+        transform: translateY(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes shake {
+
+    0%,
+    100% {
+        transform: translateX(0)
+    }
+
+    10% {
+        transform: translateX(-9px)
+    }
+
+    20% {
+        transform: translateX(8px)
+    }
+
+    30% {
+        transform: translateX(-7px)
+    }
+
+    40% {
+        transform: translateX(6px)
+    }
+
+    50% {
+        transform: translateX(-5px)
+    }
+
+    60% {
+        transform: translateX(4px)
+    }
+
+    70% {
+        transform: translateX(-3px)
+    }
+
+    80% {
+        transform: translateX(2px)
+    }
+
+    90% {
+        transform: translateX(-1px)
+    }
+}
+
+@keyframes slide-left {
+    0% {
+        opacity: 0;
+        transform: translateX(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}
+
+@keyframes slide-right {
+    0% {
+        opacity: 0;
+        transform: translateX(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}

+ 76 - 0
colorui/components/cu-custom.vue

@@ -0,0 +1,76 @@
+<template>
+	<view>
+		<view class="cu-custom" :style="[{height:CustomBar + 'px'}]">
+			<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
+				<view class="action" @tap="BackPage" v-if="isBack">
+					<text class="cuIcon-back"></text>
+					<slot name="backText"></slot>
+				</view>
+				<view class="content" :style="[{top:StatusBar + 'px'}]">
+					<slot name="content"></slot>
+				</view>
+				<slot name="right"></slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				StatusBar: this.StatusBar,
+				CustomBar: this.CustomBar
+			};
+		},
+		name: 'cu-custom',
+		computed: {
+			style() {
+				var StatusBar= this.StatusBar;
+				var CustomBar= this.CustomBar;
+				var bgImage = this.bgImage;
+				var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
+				if (this.bgImage) {
+					style = `${style}background-image:url(${bgImage});`;
+				}
+				return style
+			}
+		},
+		props: {
+			bgColor: {
+				type: String,
+				default: ''
+			},
+			isBack: {
+				type: [Boolean, String],
+				default: false
+			},
+			bgImage: {
+				type: String,
+				default: ''
+			},
+			// backIndex: {
+			// 	type: bool,
+			// 	default: false
+			// }
+		},
+		methods: {
+			BackPage() {
+				// if (this.backIndex) {
+				// 	uni.switchTab({
+				// 		url: 'pages/user/index'
+				// 	});
+				// }else {
+					uni.navigateBack({
+						delta: 1
+					});
+				// } 
+		
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 139 - 0
colorui/components/curry-slide.vue

@@ -0,0 +1,139 @@
+<template>
+  <view class="carousel-3d-slide" :style="slideStyle" :class="computedClasses" @click="goTo()">
+    <slot :index="index" :isCurrent="isCurrent" :leftIndex="leftIndex" :rightIndex="rightIndex"/>
+  </view>
+</template>
+
+<script>
+/* eslint-disable */
+export default {
+  name: 'curry-slide',
+  props: {
+    index: {
+      type: Number
+    }
+  },
+  data () {
+    return {
+      parent: this.$parent,
+      styles: {},
+      zIndex: 999
+    }
+  },
+  computed: {
+    isCurrent () {
+      return this.index === this.parent.currentIndex
+    },
+    leftIndex () {
+      return this.getSideIndex(this.parent.leftIndices)
+    },
+    rightIndex () {
+      return this.getSideIndex(this.parent.rightIndices)
+    },
+    slideStyle () {
+      let styles = {}
+      if (!this.isCurrent) {
+        const rIndex = this.leftIndex
+        const lIndex = this.rightIndex
+        if (rIndex >= 0 || lIndex >= 0) {
+          styles = rIndex >= 0 ? this.calculatePosition(rIndex, true, this.zIndex) : this.calculatePosition(lIndex, false, this.zIndex)
+          styles.opacity = 1
+          styles.visibility = 'visible'
+        }
+        if (this.parent.hasHiddenSlides) {
+          if (this.matchIndex(this.parent.leftOutIndex)) {
+            styles = this.calculatePosition(this.parent.leftIndices.length - 1, false, this.zIndex)
+          } else if (this.matchIndex(this.parent.rightOutIndex)) {
+            styles = this.calculatePosition(this.parent.rightIndices.length - 1, true, this.zIndex)
+          }
+        }
+      }
+      return Object.assign(styles, {
+        'border-width': this.parent.border + 'px',
+        'width': this.parent.slideWidth + 'px',
+        'height': this.parent.slideHeight + 'px',
+        'transition': ' transform ' + this.parent.animationSpeed + 'ms, ' +
+        '               opacity ' + this.parent.animationSpeed + 'ms, ' +
+        '               visibility ' + this.parent.animationSpeed + 'ms'
+      })
+    },
+    computedClasses () {
+      return {
+        [`left-${this.leftIndex + 1}`]: this.leftIndex >= 0,
+        [`right-${this.rightIndex + 1}`]: this.rightIndex >= 0,
+        'current': this.isCurrent
+      }
+    }
+  },
+  methods: {
+    getSideIndex (array) {
+      let index = -1
+      array.forEach((pos, i) => {
+        if (this.matchIndex(pos)) {
+          index = i
+        }
+      })
+      return index
+    },
+    matchIndex (index) {
+      return (index >= 0) ? this.index === index : (this.parent.total + index) === this.index
+    },
+    calculatePosition (i, positive, zIndex) {
+      const z = !this.parent.disable3d ? parseInt(this.parent.inverseScaling) + ((i + 1) * 100) : 0
+      const y = !this.parent.disable3d ? parseInt(this.parent.perspective) : 0
+      const leftRemain = (this.parent.space === 'auto')
+        ? parseInt((i + 1) * (this.parent.width / 1.2), 10) // 1.5
+        : parseInt((i + 1) * (this.parent.space), 10)
+      const transform = (positive)
+        ? 'translateX(' + (leftRemain) + 'px) translateZ(-' + z + 'px) ' +
+        'rotateY(-' + y + 'deg)'
+        : 'translateX(-' + (leftRemain) + 'px) translateZ(-' + z + 'px) ' +
+        'rotateY(' + y + 'deg)'
+      const top = this.parent.space === 'auto' ? 0 : parseInt((i + 1) * (this.parent.space))
+      return {
+        transform: transform,
+        top: top,
+        zIndex: zIndex - (Math.abs(i) + 1)
+      }
+    },
+    goTo () {
+      if (!this.isCurrent) {
+        if (this.parent.clickable === true) {
+          this.parent.goFar(this.index)
+        }
+      } else {
+        this.parent.onMainSlideClick()
+      }
+    }
+  }
+}
+</script>
+
+<style>
+  .carousel-3d-slide {
+    position: absolute;
+    opacity: 0;
+    visibility: hidden;
+    overflow: hidden;
+    top: 0;
+    border-color: #023c41;
+    border-style: solid;
+    background-size: cover;
+    background-color: #ccc;
+    display: block;
+    margin: 0;
+    box-sizing: border-box;
+  }
+  .carousel-3d-slide {
+    text-align: left;
+  }
+  .carousel-3d-slide img {
+    width: 100%;
+  }
+  .carousel-3d-slide.current {
+    opacity: 1 !important;
+    visibility: visible !important;
+    transform: none !important;
+    z-index: 999;
+  }
+</style>

+ 410 - 0
colorui/components/curry-swiper.vue

@@ -0,0 +1,410 @@
+<template>
+  <view class="carousel-3d-container" :style="{height: this.slideHeight + 'px'}">
+    <view class="carousel-3d-slider" :style="{width: this.slideWidth + 'px', height: this.slideHeight + 'px'}">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+/* eslint-disable */
+  const noop = () => {
+  }
+  export default {
+    name: 'curry-swiper',
+    props: {
+      // Number of slides
+      count: {
+        type: [Number, String],
+        default: 0
+      },
+      // Slides perspective position
+      perspective: {
+        type: [Number, String],
+        default: 35
+      },
+      // Number of slides displayed on each page
+      display: {
+        type: [Number, String],
+        default: 3
+      },
+      loop: {
+        type: Boolean,
+        default: true
+      },
+      // Animation between slides in milliseconds
+      animationSpeed: {
+        type: [Number, String],
+        default: 500
+      },
+      // Animation direction
+      dir: {
+        type: String,
+        default: 'ltr'
+      },
+      width: {
+        type: [Number, String],
+        default: 360
+      },
+      height: {
+        type: [Number, String],
+        default: 270
+      },
+      border: {
+        type: [Number, String],
+        default: 1
+      },
+      // Space between slides in pixels
+      space: {
+        type: [Number, String],
+        default: 'auto'
+      },
+      // Start slide index. First slide has 0 index
+      startIndex: {
+        type: [Number, String],
+        default: 0
+      },
+      // Enable navigation by clicking on slide
+      clickable: {
+        type: Boolean,
+        default: true
+      },
+      disable3d: {
+        type: Boolean,
+        default: false
+      },
+      // Minimum distance in pixels to swipe before a slide advance is triggered
+      minSwipeDistance: {
+        type: Number,
+        default: 10
+      },
+      // Slide inverse scaling
+      inverseScaling: {
+        type: [Number, String],
+        default: 300
+      },
+      onLastSlide: {
+        type: Function,
+        default: noop
+      },
+      onSlideChange: {
+        type: Function,
+        default: noop
+      },
+      bias: {
+        type: String,
+        default: 'left'
+      },
+      onMainSlideClick: {
+        type: Function,
+        default: noop
+      }
+    },
+    data () {
+      return {
+        viewport: 0,
+        currentIndex: 0,
+        total: 0,
+        dragOffset: 0,
+        dragStartX: 0,
+        mousedown: false,
+        zIndex: 998
+      }
+    },
+    watch: {
+      count () {
+        this.computeData()
+      }
+    },
+    computed: {
+      isLastSlide () {
+        return this.currentIndex === this.total - 1
+      },
+      isFirstSlide () {
+        return this.currentIndex === 0
+      },
+      isNextPossible () {
+        return !(!this.loop && this.isLastSlide)
+      },
+      isPrevPossible () {
+        return !(!this.loop && this.isFirstSlide)
+      },
+      slideWidth () {
+        const vw = this.viewport
+        const sw = parseInt(this.width) + (parseInt(this.border, 10) * 2)
+        return vw < sw ? vw : sw
+      },
+      slideHeight () {
+        const sw = parseInt(this.width, 10) + (parseInt(this.border, 10) * 2)
+        const sh = parseInt(parseInt(this.height) + (this.border * 2), 10)
+        const ar = this.calculateAspectRatio(sw, sh)
+        return this.slideWidth / ar
+      },
+      visible () {
+        const v = (this.display > this.total) ? this.total : this.display
+        return v
+      },
+      hasHiddenSlides () {
+        return this.total > this.visible
+      },
+      leftIndices () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'left' ? Math.ceil(n) : Math.floor(n))
+        const indices = []
+        for (let m = 1; m <= n; m++) {
+          indices.push((this.dir === 'ltr')
+            ? (this.currentIndex + m) % (this.total)
+            : (this.currentIndex - m) % (this.total))
+        }
+        return indices
+      },
+      rightIndices () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'right' ? Math.ceil(n) : Math.floor(n))
+        const indices = []
+        for (let m = 1; m <= n; m++) {
+          indices.push((this.dir === 'ltr')
+            ? (this.currentIndex - m) % (this.total)
+            : (this.currentIndex + m) % (this.total))
+        }
+        return indices
+      },
+      leftOutIndex () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'left' ? Math.ceil(n) : Math.floor(n))
+        n++
+        if (this.dir === 'ltr') {
+          return ((this.total - this.currentIndex - n) <= 0)
+            ? (-parseInt(this.total - this.currentIndex - n))
+            : (this.currentIndex + n)
+        } else {
+          return (this.currentIndex - n)
+        }
+      },
+      rightOutIndex () {
+        let n = (this.visible - 1) / 2
+        n = (this.bias.toLowerCase() === 'right' ? Math.ceil(n) : Math.floor(n))
+        n++
+        if (this.dir === 'ltr') {
+          return (this.currentIndex - n)
+        } else {
+          return ((this.total - this.currentIndex - n) <= 0)
+            ? (-parseInt(this.total - this.currentIndex - n, 10))
+            : (this.currentIndex + n)
+        }
+      }
+    },
+    methods: {
+      /**
+       * Go to next slide
+       */
+      goNext () {
+        if (this.isNextPossible) {
+          this.isLastSlide ? this.goSlide(0) : this.goSlide(this.currentIndex + 1)
+        }
+      },
+      /**
+       * Go to previous slide
+       */
+      goPrev () {
+        if (this.isPrevPossible) {
+          this.isFirstSlide ? this.goSlide(this.total - 1) : this.goSlide(this.currentIndex - 1)
+        }
+      },
+      /**
+       * Go to slide
+       * @param  {String} index of slide where to go
+       */
+      goSlide (index) {
+        this.currentIndex = (index < 0 || index > this.total - 1) ? 0 : index
+        if (this.isLastSlide) {
+          if (this.onLastSlide !== noop) {
+            console.warn('onLastSlide deprecated, please use @last-slide')
+          }
+          this.onLastSlide(this.currentIndex)
+          this.$emit('last-slide', this.currentIndex)
+        }
+        this.$emit('before-slide-change', this.currentIndex)
+        setTimeout(() => this.animationEnd(), this.animationSpeed)
+      },
+      /**
+       * Go to slide far slide
+       */
+      goFar (index) {
+        let diff = (index === this.total - 1 && this.isFirstSlide) ? -1 : (index - this.currentIndex)
+        if (this.isLastSlide && index === 0) {
+          diff = 1
+        }
+        const diff2 = (diff < 0) ? -diff : diff
+        let timeBuff = 0
+        let i = 0
+        while (i < diff2) {
+          i += 1
+          const timeout = (diff2 === 1) ? 0 : (timeBuff)
+          setTimeout(() => (diff < 0) ? this.goPrev(diff2) : this.goNext(diff2), timeout)
+          timeBuff += (this.animationSpeed / (diff2))
+        }
+      },
+      /**
+       * Trigger actions when animation ends
+       */
+      animationEnd () {
+        if (this.onSlideChange !== noop) {
+          console.warn('onSlideChange deprecated, please use @after-slide-change')
+        }
+        this.onSlideChange(this.currentIndex)
+        this.$emit('after-slide-change', this.currentIndex)
+      },
+      /**
+       * Trigger actions when mouse is released
+       * @param  {Object} e The event object
+       */
+      handleMouseup () {
+        this.mousedown = false
+        this.dragOffset = 0
+      },
+      /**
+       * Trigger actions when mouse is pressed
+       * @param  {Object} e The event object
+       */
+      handleMousedown (e) {
+        if (!e.touches) {
+          e.preventDefault()
+        }
+        this.mousedown = true
+        this.dragStartX = ('ontouchstart' in window) ? e.touches[0].clientX : e.clientX
+      },
+      /**
+       * Trigger actions when mouse is pressed and then moved (mouse drag)
+       * @param  {Object} e The event object
+       */
+      handleMousemove (e) {
+          if (!this.mousedown) {
+            return
+          }
+          const eventPosX = ('ontouchstart' in window) ? e.touches[0].clientX : e.clientX
+          const deltaX = (this.dragStartX - eventPosX)
+          this.dragOffset = deltaX
+          if (this.dragOffset > this.minSwipeDistance) {
+            this.handleMouseup()
+            this.goNext()
+          } else if (this.dragOffset < -this.minSwipeDistance) {
+            this.handleMouseup()
+            this.goPrev()
+          }
+      },
+      /**
+       * A mutation observer is used to detect changes to the containing node
+       * in order to keep the magnet container in sync with the height its reference node.
+       */
+      attachMutationObserver () {
+        const MutationObserver = window.MutationObserver ||
+          window.WebKitMutationObserver ||
+          window.MozMutationObserver
+        if (MutationObserver) {
+          const config = {
+            attributes: true,
+            childList: true,
+            characterData: true
+          }
+          this.mutationObserver = new MutationObserver(() => {
+            this.$nextTick(() => {
+              this.computeData()
+            })
+          })
+          if (this.$el) {
+            this.mutationObserver.observe(this.$el, config)
+          }
+        }
+      },
+      /**
+       * Stop listening to mutation changes
+       */
+      detachMutationObserver () {
+        if (this.mutationObserver) {
+          this.mutationObserver.disconnect()
+        }
+      },
+      /**
+       * Get the number of slides
+       * @return {Number} Number of slides
+       */
+      getSlideCount () {
+        if (this.$slots.default !== undefined) {
+          return this.$slots.default.filter((value) => {
+            return value.tag !== void 0
+          }).length
+        }
+        return 0
+      },
+      /**
+       * Calculate slide with and keep defined aspect ratio
+       * @return {Number} Aspect ratio number
+       */
+      calculateAspectRatio (width, height) {
+        return Math.min(width / height)
+      },
+      /**
+       * Re-compute the number of slides and current slide
+       */
+      computeData (firstRun) {
+        this.total = this.getSlideCount()
+        if (firstRun || this.currentIndex >= this.total) {
+          this.currentIndex = parseInt(this.startIndex) > this.total - 1 ? this.total - 1 : parseInt(this.startIndex)
+        }
+        this.viewport = this.$el.clientWidth
+      },
+      setSize () {
+        this.$el.style.cssText += 'height:' + this.slideHeight + 'px;'
+        this.$el.childNodes[0].style.cssText += 'width:' + this.slideWidth + 'px;' + ' height:' + this.slideHeight + 'px;'
+      }
+    },
+    mounted () {
+      this.computeData(true)
+      this.attachMutationObserver()
+      if (!this.$isServer) {
+        window.addEventListener('resize', this.setSize)
+        if ('ontouchstart' in window) {
+          this.$el.addEventListener('touchstart', this.handleMousedown)
+          this.$el.addEventListener('touchend', this.handleMouseup)
+          this.$el.addEventListener('touchmove', this.handleMousemove)
+        } else {
+          this.$el.addEventListener('mousedown', this.handleMousedown)
+          this.$el.addEventListener('mouseup', this.handleMouseup)
+          this.$el.addEventListener('mousemove', this.handleMousemove)
+        }
+      }
+    },
+    beforeDestroy () {
+      if (!this.$isServer) {
+        this.detachMutationObserver()
+        if ('ontouchstart' in window) {
+          this.$el.removeEventListener('touchmove', this.handleMousemove)
+        } else {
+          this.$el.removeEventListener('mousemove', this.handleMousemove)
+        }
+        window.removeEventListener('resize', this.setSize)
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .carousel-3d-container {
+    min-height: 1px;
+    width: 100%;
+    position: relative;
+    z-index: 0;
+    overflow: hidden;
+    margin: 0px auto;
+    box-sizing: border-box;
+  }
+  .carousel-3d-slider {
+    position: relative;
+    margin: 0 auto;
+    transform-style: preserve-3d;
+    -webkit-perspective: 1000px;
+    -moz-perspective: 1000px;
+    perspective: 1000px;
+  }
+</style>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1226 - 0
colorui/icon.css


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 4037 - 0
colorui/main.css


+ 35 - 0
common/WXBizDataCrypt.js

@@ -0,0 +1,35 @@
+var crypto = require('crypto')
+
+function WXBizDataCrypt(appId, sessionKey) {
+  this.appId = appId
+  this.sessionKey = sessionKey
+}
+
+WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
+  // base64 decode
+  var sessionKey = new Buffer(this.sessionKey, 'base64')
+  encryptedData = new Buffer(encryptedData, 'base64')
+  iv = new Buffer(iv, 'base64')
+
+  try {
+     // 解密
+    var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
+    // 设置自动 padding 为 true,删除填充补位
+    decipher.setAutoPadding(true)
+    var decoded = decipher.update(encryptedData, 'binary', 'utf8')
+    decoded += decipher.final('utf8')
+    
+    decoded = JSON.parse(decoded)
+
+  } catch (err) {
+    throw new Error('Illegal Buffer')
+  }
+
+  if (decoded.watermark.appid !== this.appId) {
+    throw new Error('Illegal Buffer')
+  }
+
+  return decoded
+}
+
+module.exports = WXBizDataCrypt

+ 0 - 0
common/app.css


+ 75 - 0
common/cache.js

@@ -0,0 +1,75 @@
+// 缓存前缀 
+var postfix = 'yuncache';
+
+/**
+ * 设置缓存 
+ * 
+ * @param  {[type]} k [键名]
+ * @param  {[type]} v [键值]
+ * @param  {[type]} t [时间、单位秒]
+ */
+function put(k, v, t) {
+	uni.setStorageSync(k, v)
+	var seconds = parseInt(t);
+	if (seconds > 0) {
+		var timestamp = Date.parse(new Date());
+		timestamp = timestamp / 1000 + seconds;
+		uni.setStorageSync(k + postfix, timestamp + "")
+	} else {
+		uni.removeStorageSync(k + postfix)
+	}
+}
+
+/**
+ * 获取缓存 
+ * 
+ * @param  {[type]} k   [键名]
+ * @param  {[type]} def [获取为空时默认]
+ */
+function get(k, def) {
+	var deadtime = parseInt(uni.getStorageSync(k + postfix))
+	if (deadtime) {
+		if (parseInt(deadtime) < Date.parse(new Date()) / 1000) {
+			if (def) {
+				return def;
+			} else {
+				return false;
+			}
+		}
+	}
+	var res = uni.getStorageSync(k);
+	if (res) {
+		return res;
+	} else {
+		if (def == undefined || def == "") {
+			def = false;
+		}
+		return def;
+	}
+}
+
+/**
+ * 清理指定缓存
+ * 
+ * @return {[type]} [description]
+ */
+function remove(k) {
+	uni.removeStorageSync(k);
+	uni.removeStorageSync(k + postfix);
+}
+
+/**
+ * 清理所有缓存
+ * 
+ * @return {[type]} [description]
+ */
+function clear() {
+	uni.clearStorageSync();
+}
+
+export default {
+	put,
+	get,
+	remove,
+	clear,
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 4 - 0
common/city.area.js


+ 187 - 0
common/common.css

@@ -0,0 +1,187 @@
+.flex_layout{display: flex; align-items: center; flex-wrap: wrap;}
+.flex_between{ display: flex; align-items: center; flex-wrap: wrap; justify-content: space-between;}
+.nodata{padding: 50rpx 30rpx;text-align: center;color: #999;font-size: 24rpx;text-align: center;background: #fff;}
+.submit_btn{padding: 30upx 85upx; margin-top: 20upx;}
+.submit_btn button{width: 100%; height: 80upx; line-height: 80upx; border-radius: 80upx; background: rgba(36,255,255,0.2); font-size: 30upx; color: #fff;}
+a{text-decoration: none;}
+.noresult{ color: #fff; text-align: center; font-size: 24upx;}
+
+/*弹窗样式*/
+    .Appointment_failed{position: fixed; left: 60upx; right: 60upx; top: 50%; transform: translateY(-50%); background: #fff; border-radius: 10px; overflow: hidden; z-index: 100;}
+    .notice_title{color: #fff; font-size: 30upx; text-align: center; padding: 30upx; background: #4a85b2;}
+    .notice_content{padding: 30upx;}
+    .notice_item{padding: 15upx 0;}
+    .notice_item view{color: #333; font-size: 30upx;}
+    .notice_item view{color: #333; font-size: 24upx;}
+    .notice_btn{padding-bottom: 30upx;}
+    .notice_btn button{width: 450upx; height: 75upx; line-height: 75upx; border-radius: 75upx; background: #4a85b2; color: #fff; display: block; margin: 0 auto;}
+  .ornament{position: relative;}
+    .ornament>image{width: 100%; height: 257upx; display: block;}
+    .ornament_pos{position: absolute; width: 114upx; height: 114upx; left: 50%; top: 50%; transform: translate(-50%,-50%);}
+    .ornament_pos image{width: 114upx; height: 114upx; display: block;}
+    .ornament_delete{position: absolute; padding: 20upx; top: 0upx; right: 0upx; width: 70upx; height: 70upx;}
+    .ornament_delete i{display: block; font-size: 30upx;}
+    .ornament_delete image{width: 30upx; height: 30upx; display: block;}
+    .ornament_title{color: #4A85B2; font-size: 36upx; text-align: center; margin-top: 60upx;}
+    .ornament_text{color: #999; font-size: 30upx; text-align: center; margin-top: 30upx; margin-bottom: 60upx; padding: 0 30upx;}
+/*弹窗样式end*/
+    .pull-up {
+        width: 100%;
+        margin-bottom: 20upx;
+        text-align: center;
+        height: 80upx;
+        color: #c1c1c1;
+    }
+    .rect-text {
+        height: 100%;
+        line-height: 80upx;
+    }
+    .rect-wrap {
+        margin: 0 auto;
+        width: 100upx;
+        height: 60upx;
+        text-align: center;
+        font-size: 8upx;
+        margin-top: 8upx;
+    }
+    .rect-wrap .rect {
+        background-color: #7ad237;
+    height: 100%;
+    width: 6upx;
+    display: inline-block;
+    -webkit-animation: stretchdelay 1.2s infinite ease-in-out;
+    animation: stretchdelay 1.2s infinite ease-in-out;
+    }
+    .rect-wrap .rect {
+        margin: 4upx;
+    }
+    .rect-wrap .rect2 {
+    -webkit-animation-delay: -1.1s;
+    animation-delay: -1.1s;
+  }
+  .rect-wrap .rect3 {
+    -webkit-animation-delay: -1.0s;
+    animation-delay: -1.0s;
+  }
+  .rect-wrap .rect4 {
+    -webkit-animation-delay: -0.9s;
+    animation-delay: -0.9s;
+  }
+  .rect-wrap .rect5 {
+    -webkit-animation-delay: -0.8s;
+    animation-delay: -0.8s;
+  }
+    @keyframes stretchdelay {
+        0%, 40%, 100% {
+            transform: scaleY(0.4);
+            -webkit-transform: scaleY(0.4);
+        }
+        20% {
+            transform: scaleY(1.0);
+            -webkit-transform: scaleY(1.0);
+        }
+    }
+    @-webkit-keyframes stretchdelay {
+        0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
+        20% { -webkit-transform: scaleY(1.0) }
+     }
+/* #ifdef H5 */
+    .positionFixe {
+        padding-top: 90upx;
+    }
+    /* #endif */
+    
+    /* #ifdef MP-WEIXIN */
+    .positionFixe {
+        padding-top: 130upx;
+    }
+    /* #endif */
+    .positionFixe{position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: -1; box-sizing: border-box; background: #4a85b2;}
+    .positionFixe image{display: block; width: 100%; height: 1108upx;}
+
+/*iconfont文件*/
+@font-face {
+  font-family: 'iconfont';  /* project id 1340048 */
+  src: url('//at.alicdn.com/t/font_1340048_2mrk0i19u8d.eot');
+  src: url('//at.alicdn.com/t/font_1340048_2mrk0i19u8d.eot?#iefix') format('embedded-opentype'),
+  url('//at.alicdn.com/t/font_1340048_2mrk0i19u8d.woff2') format('woff2'),
+  url('//at.alicdn.com/t/font_1340048_2mrk0i19u8d.woff') format('woff'),
+  url('//at.alicdn.com/t/font_1340048_2mrk0i19u8d.ttf') format('truetype'),
+  url('//at.alicdn.com/t/font_1340048_2mrk0i19u8d.svg#iconfont') format('svg');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;   
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-jinru:before {
+  content: "\e615";
+}
+
+.icon-zhuangtai:before {
+  content: "\e634";
+}
+
+.icon-icon:before {
+  content: "\e630";
+}
+
+.icon-right:before {
+  content: "\e63b";
+}
+
+.icon-hide:before {
+  content: "\e600";
+}
+
+.icon-address:before {
+  content: "\e62a";
+}
+
+.icon-dianhua:before {
+  content: "\e61b";
+}
+
+.icon-dianhua1:before {
+  content: "\e601";
+}
+
+.icon-biao:before {
+  content: "\e6d5";
+}
+
+.icon-rili:before {
+  content: "\e642";
+}
+
+.icon-add:before {
+  content: "\e6ab";
+}
+
+.icon-liaotian:before {
+  content: "\e610";
+}
+
+.icon-fabu:before {
+  content: "\e60d";
+}
+
+.icon-aiqingmiao:before {
+  content: "\e602";
+}
+
+.icon-shezhi:before {
+  content: "\e72c";
+}
+
+.icon-date:before {
+  content: "\e607";
+}
+
+.icon-zxt:before {
+  content: "\e627";
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 146 - 0
common/common.scss


+ 102 - 0
common/dateTimePicker.js

@@ -0,0 +1,102 @@
+// JavaScript Document
+/**
+ * 自定义多列时间选择器
+ */
+function withData(param) {
+  return param < 10 ? '0' + param : '' + param;
+}
+function getLoopArray(start, end) {
+  var start = start || 0;
+  var end = end || 1;
+  var array = [];
+  for (var i = start; i <= end; i++) {
+    array.push(withData(i));
+  }
+  return array;
+}
+function getMonthDay(year, month) {
+  var flag = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0), array = null;
+ 
+  switch (month) {
+    case '01':
+    case '03':
+    case '05':
+    case '07':
+    case '08':
+    case '10':
+    case '12':
+      array = getLoopArray(1, 31)
+      break;
+    case '04':
+    case '06':
+    case '09':
+    case '11':
+      array = getLoopArray(1, 30)
+      break;
+    case '02':
+      array = flag ? getLoopArray(1, 29) : getLoopArray(1, 28)
+      break;
+    default:
+      array = '月份格式不正确,请重新输入!'
+  }
+  return array;
+}
+function getNewDateArry() {
+  // 当前时间的处理
+  var newDate = new Date();
+  var year = withData(newDate.getFullYear()),
+    mont = withData(newDate.getMonth() + 1),
+    date = withData(newDate.getDate()),
+    hour = withData(newDate.getHours()),
+    minu = withData(newDate.getMinutes()),
+    seco = withData(newDate.getSeconds());
+ 
+  return [year, mont, date, hour, minu, seco];
+}
+function dateTimePicker(startYear, endYear, date) {
+  // 返回默认显示的数组和联动数组的声明
+  var dateTime = [], dateTimeArray = [[], [], [], []];
+  var start = startYear || 2020;
+  var end = endYear || 2100;
+  // 默认开始显示数据
+  var defaultDate = date ? [...date.split(' ')[0].split('-'), ...date.split(' ')[1].split(':')] : getNewDateArry();
+	console.log(defaultDate);
+  //console.log("defaultDate: ",defaultDate);
+  // 处理联动列表数据
+  /*年月日 时分秒*/
+  dateTimeArray[0] = getLoopArray(start, end);
+  dateTimeArray[1] = getLoopArray(1, 12);
+  dateTimeArray[2] = getMonthDay(defaultDate[0], defaultDate[1]);
+  //dateTimeArray[3] = getLoopArray(0, 23);
+	dateTimeArray[3] =['9时','11时','14时','16时']
+  //dateTimeArray[4] = getLoopArray(0, 59);
+  //dateTimeArray[5] = getLoopArray(0, 59);
+ // console.log(dateTimeArray[0]);
+ // console.log(dateTimeArray[1]);
+ // console.log(dateTimeArray[2]);
+ 
+  dateTimeArray.forEach((current, index) => {
+    dateTime.push(current.indexOf(defaultDate[index]));
+  });
+  //处理数据加上年月日时的单位
+  for(var i=0; i<dateTimeArray[0].length;i++){
+  	dateTimeArray[0][i]= dateTimeArray[0][i]+'年';
+  }
+  for(var j=0; j<dateTimeArray[1].length;j++){
+  	dateTimeArray[1][j]= dateTimeArray[1][j]+'月';
+  }
+  for(var k=0; k<dateTimeArray[2].length;k++){
+  	dateTimeArray[2][k]= dateTimeArray[2][k]+'日';
+  }
+  //
+  dateTime[3]=0
+  //console.log(dateTime);
+  return {
+    dateTimeArray: dateTimeArray,
+    dateTime: dateTime
+  }
+}
+module.exports = {
+  dateTimePicker: dateTimePicker,
+  getMonthDay: getMonthDay
+}

+ 493 - 0
common/fa.mixin.js

@@ -0,0 +1,493 @@
+export const tools = {
+	filters: {
+
+	},
+	computed: {
+
+	},
+	methods: {
+		//富文本的回调
+		navigate(e) {
+			if (e.href && e.href.indexOf('http') == -1) { //不完整的链接						
+				//详情				
+				let res = e.href.match(new RegExp("(a)|(\\d+)", 'g'));
+				if (res.length == 2) {
+					this.$u.route('/pages/article/detail', {
+						id: res[1]
+					});
+					return;
+				}
+				// #ifdef MP
+				this.$util.uniCopy({
+					content: this.vuex_config.upload.cdnurl + e.href,
+					success: () => {
+						this.$u.toast('链接已复制,请在浏览器中打开')
+					}
+				})
+				// #endif
+				// #ifndef MP				
+				window.open(this.vuex_config.upload.cdnurl + e.href);
+				// #endif
+			}
+		},
+		//预览图片
+		lookImage(index) {
+			uni.previewImage({
+				current: index,
+				urls: this.imagesList,
+				longPressActions: {
+					itemList: ['发送给朋友', '保存图片', '收藏'],
+					success: function(data) {
+						console.log(data)
+					},
+					fail: function(err) {
+						console.log(err.errMsg);
+					}
+				}
+			});
+		},
+		//复制url
+		copyUrl() {
+			this.$util.uniCopy({
+				content: window.location.href,
+				success: () => {
+					this.$u.toast('复制成功,请去粘贴发送给好友吧');
+				},
+				error: () => {
+					console.log('复制失败!')
+				}
+			})
+		},
+		//cdnurl
+		cdnurl(url) {
+			if (!/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/.test(url)) {
+				return this.vuex_config.upload.cdnurl + url;
+			};
+			return url;
+		},
+		//页面跳转
+		goPage(path, auth) {
+			if (path == 'out') {
+				this.$u.vuex('vuex_token', '');
+				this.$u.vuex('vuex_user', {});
+				return;
+			}
+			if (auth && !this.vuex_token) {
+				this.$u.route('/pages/login/mobilelogin');
+				return;
+			}
+			let type = 'navigateTo';
+			
+			// #ifdef MP-WEIXIN
+			//优化当pages超过5个时的处理
+			let pages = getCurrentPages();
+			type = pages.length >= 4 ? 'redirectTo' : type;
+			// #endif
+			
+			uni.$u.route({
+				url: path,
+				type: type,
+				complete(e) {
+					console.log(e, path)
+				}
+			})
+		}
+	}
+}
+//点赞
+export const vote = {
+	methods: {
+		likes: async function() {
+			const value = uni.getStorageSync(`${this.id}_${this.vuex_user.id}`);
+			if (value == this.id) {
+				this.$u.toast('您已经点过赞了')
+				return;
+			}
+			let res = await this.$api.getArchivesVote({
+				id: this.id,
+				type: 'like'
+			})
+			this.$u.toast(res.msg);
+			if (!res.code) {
+				return;
+			};
+			//先在前端限制
+			uni.setStorageSync(`${this.id}_${this.vuex_user.id}`, this.id);
+			this.$set(this.archivesInfo, 'likes', res.data.likes)
+		},
+		collection(id, type) {
+			this.$api.addCollection({
+				aid: id,
+				type: type
+			}).then(res => {
+				this.$u.toast(res.msg)
+			})
+		}
+	}
+}
+//修改头像的事件
+export const avatar = {
+	methods: {
+		chooseAvatar() {
+			uni.$on('uAvatarCropper', this.upload);
+			this.$u.route({
+				// 关于此路径,请见下方"注意事项"
+				url: '/uview-ui/components/u-avatar-cropper/u-avatar-cropper',
+				// 内部已设置以下默认参数值,可不传这些参数
+				params: {
+					// 输出图片宽度,高等于宽,单位px
+					destWidth: 300,
+					// 裁剪框宽度,高等于宽,单位px
+					rectWidth: 300,
+					// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
+					fileType: 'jpg'
+				}
+			});
+		},
+		upload: async function(path) {
+			uni.$off('uAvatarCropper', this.upload);
+			// 可以在此上传到服务端
+			try {
+				let res = await this.$api.goUpload({
+					filePath: path
+				});
+				if (!res.code) {
+					this.$u.toast(res.msg);
+				};
+				this.form.avatar = res.data.url;
+				this.url = res.data.fullurl;
+				if (typeof this.editAvatar == 'function') {
+					this.editAvatar();
+				}
+			} catch (e) {
+				console.error(e);
+				this.$u.toast('图片上传失败!');
+			}
+		}
+	}
+}
+
+//form
+export const formRule = {
+	methods: {
+		//表单验证
+		getRules(row) {
+			let arr = row.rule.split(';');
+			let rule_arr = [];
+
+			arr.forEach(item => {
+				item = this.$u.trim(item);
+				switch (item) {
+					case 'required':
+					case 'checked':
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								if (typeof value == 'string') {
+									value = value.replace(/<[^>]+>/g, "").replace(/\s/ig, "");
+								}
+								return !(this.$u.test.empty(value));
+							},
+							message: row.title + '不能为空',
+							// 可以单个或者同时写两个触发验证方式
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'digits': //数字校验
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.digits(value);
+							},
+							message: '请填写数字',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'letters': //字母校验
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.letter(value);
+							},
+							message: '请填写字母',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'date': //日期校验
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.date(value);
+							},
+							message: '请填写正确日期格式',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'time': //时间校验
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return /^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/.test(value);
+							},
+							message: '请填写正确时间格式',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'email': //邮箱校验
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.email(value);
+							},
+							message: '请填写正确邮箱',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'url': //网址
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.url(value);
+							},
+							message: '请填写正确网址',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'qq': //qq
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return /^[1-9][0-9]{4,10}$/.test(value);
+							},
+							message: '请填写正确QQ号码',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'IDcard': //身份证
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.idCard(value);
+							},
+							message: '请填写正确身份证件号',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'tel': //电话
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return /^\d{3}-\d{8}$|^\d{4}-\d{7,8}$/.test(value);
+							},
+							message: '请填写正确电话号码',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'mobile': //手机
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return this.$u.test.mobile(value);
+							},
+							message: '请填写正确手机号码',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'zipcode': //邮编
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/
+									.test(value);
+							},
+							message: '请填写正确邮编',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'chinese': //中文
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/
+									.test(
+										value
+									);
+							},
+							message: '请填写中文',
+							trigger: ['change', 'blur']
+						});
+						break;
+					case 'username': //用户名
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								return /^[a-zA-Z0-9_]{3,12}$/.test(value);
+							},
+							message: '请填写3-12位数字、字母、下划线',
+							trigger: ['change', 'blur']
+						});
+
+						break;
+					case 'password': //密码
+						rule_arr.push({
+							validator: (rule, value, callback) => {
+								let val = this.$u.trim(value, 'all');
+								if (val != value) {
+									return false;
+								}
+								return /^[0-9a-zA-Z!@#$%^&*?]{6,16}$/.test(value);
+							},
+							message: '请填写6-16位字符,不能包含空格',
+							trigger: ['change', 'blur']
+						});
+						break;
+				}
+			});
+
+
+			//多选额外的判断
+			if (row.type == 'checkbox') {
+				//最少
+				if (row.minimum > 0) {
+					rule_arr.push({
+						validator: (rule, value, callback) => {
+							if (!value) {
+								return false;
+							}
+							let arr = value.split(',')
+							return arr.length >= row.minimum;
+						},
+						message: '最少必须选择' + row.minimum + '项',
+						// 可以单个或者同时写两个触发验证方式
+						trigger: ['change', 'blur']
+					});
+				}
+			}
+			if (['checkbox', 'selects', 'images', 'files'].indexOf(row.type) != -1) {
+				//最多
+				if (row.maximum > 0) {
+					rule_arr.push({
+						validator: (rule, value, callback) => {
+							if (!value) {
+								return false;
+							}
+							let arr = value.split(',')
+							return arr.length <= row.maximum;
+						},
+						message: '最多只能选择' + row.maximum + '项',
+						// 可以单个或者同时写两个触发验证方式
+						trigger: ['change', 'blur']
+					});
+				}
+			}
+
+			return rule_arr;
+		}
+	}
+}
+
+//登录成功跳转
+export const loginfunc = {
+	methods: {
+		//登录成功
+		success(index = 1) {
+			//不在H5
+			// #ifndef H5
+			uni.$u.route({
+				type: 'back',
+				delta: index
+			})
+			// #endif
+			// 在H5 刷新导致路由丢失
+			// #ifdef H5
+			var pages = getCurrentPages();
+			//有上次页面,关闭所有页面,到此页面,是从授权的,授权页面被刷新过,路由栈丢失
+			if (pages.length <= 1 || pages[0].route == 'pages/login/auth') {
+				//默认到首页
+				uni.reLaunch({
+					url: (this.vuex_lasturl || '/pages/index/index'),
+					complete(res) {
+						console.log(res)
+					}
+				})
+				return;
+			}
+			uni.$u.route({
+				type: 'back',
+				delta: index
+			})
+			// #endif
+		},
+		// #ifdef H5
+		async goAuth() {
+			if (this.$util.isWeiXinBrowser()) {
+				let url = '';
+				if (window.location.hash != '') {
+					url = window.location.origin + window.location.pathname + '?hashpath=/pages/login/auth'
+				} else {
+					url = window.location.origin + window.location.pathname.replace(/pages.*/,
+						'pages/login/auth');
+				};
+				let res = await this.$api.getAuthUrl({
+					platform: 'wechat',
+					url: url
+				});
+				if (!res.code) {
+					this.$u.toast(res.msg);
+					return;
+				}
+				var pages = getCurrentPages();
+				let len = pages.length;
+				if (len > 1) {
+					let url = pages[len - 1].route;
+					if (url.includes('login')) {
+						//找到上一个不是登录页面
+						for (let i = len - 1; i >= 0; i--) {
+							if (!pages[i].route.includes('login')) {
+								this.$u.vuex('vuex_lasturl', '/' + pages[i].route + this.$u.queryParams(pages[i]
+									.options));
+								break;
+							}
+						}
+					} else {
+						this.$u.vuex('vuex_lasturl', '/' + url + this.$u.queryParams(pages[pages.length - 1]
+							.options))
+					}
+				}
+				window.location.href = res.data;
+			}
+		},
+		// #endif
+		// #ifdef APP-PLUS
+		goAppLogin(index = 1) {
+			let that = this;
+			var all, Service;
+			// 1.发送请求获取code
+			plus.oauth.getServices(
+				function(Services) {
+					all = Services;
+					Object.keys(all).some(key => {
+						if (all[key].id == 'weixin') {
+							Service = all[key];
+						}
+					});
+					Service.authorize(
+						async function(e) {
+								console.log(e);
+								let res = await that.$api.goAppLogin({
+									code: e.code,
+									scope: e.scope
+								});
+								if (!res.code) {
+									that.$u.toast(res.msg);
+									return;
+								}
+								if (res.data.user) {
+									that.$u.vuex('vuex_token', res.data.user.token);
+									that.$u.vuex('vuex_user', res.data.user || {});
+									that.success(index);
+									return;
+								}
+								that.$u.vuex('vuex_third', res.data.third);
+								that.$u.route('/pages/login/register?bind=bind');
+							},
+							function(e) {
+								that.$u.toast('授权失败!');
+							}
+					);
+				},
+				function(err) {
+					console.log(err);
+					that.$u.toast('授权失败!');
+				}
+			);
+		}
+		// #endif
+	}
+}

+ 40 - 0
common/fa.style.mixin.js

@@ -0,0 +1,40 @@
+module.exports = {
+	computed: {
+		cmsTitleStyle() {
+			return val => {
+				let style = {};
+				if (val && val.includes('b')) {
+					style.fontWeight = 'bold';
+				}
+				if (val && val.includes('#')) {
+					style.color = val.replace('b', '').replace('|', '');
+				}
+				return style;
+			}
+		},
+		theme() {
+			if (this.vuex_theme.value) {
+				return this.vuex_theme.value;
+			}
+			return {};
+		},
+		lightColor() {
+			let color = '#f5f5f5';
+			if (this.vuex_theme.value) {
+				let theme = this.vuex_theme.value;
+				let colorArr = this.$u.colorGradient(theme.bgColor, theme.color, 10);
+				color = colorArr[9] || '#f5f5f5';
+			}
+			return color;
+		},
+		faBorderColor() {
+			let color = '#f5f5f5';
+			if (this.vuex_theme.value) {
+				let theme = this.vuex_theme.value;
+				let colorArr = this.$u.colorGradient(theme.bgColor, theme.color, 10);
+				color = colorArr[5] || '#f5f5f5';
+			}
+			return color;
+		},
+	},
+}

+ 63 - 0
common/fa.weixin.mixin.js

@@ -0,0 +1,63 @@
+//微信网页分享
+var jweixin = require('jweixin-module')  
+export const weixinShare = {
+	methods: {
+		//初始化sdk配置  
+		initJssdk: function(callback) {
+			let url = '';
+			if(window.location.hash != ''){
+			  url = window.location.origin+window.location.pathname;
+			}else{
+			  url = window.location.href;
+			}
+			this.$api.getSigned({url:url}).then(res=>{
+				if (res.code) {
+					jweixin.config({
+						debug: false,
+						appId: res.data.appId,
+						timestamp: res.data.timestamp,
+						nonceStr: res.data.nonceStr,
+						signature: res.data.signature,
+						jsApiList: [
+							'checkJsApi',
+							'updateAppMessageShareData',
+							'updateTimelineShareData',
+							'onMenuShareWeibo'
+						]
+					});
+					//配置完成后,再执行分享等功能  
+					if (typeof callback == 'function') {
+						callback();
+					}
+				}else{
+					this.$u.toast(res.msg)
+				}
+			})
+		},
+		//在需要自定义分享的页面中调用  
+		wxShare: function(data) {		
+			//每次都需要重新初始化配置,才可以进行分享  
+			this.initJssdk(function() {
+				jweixin.ready(function() {
+					var shareData = {
+						title: data && data.title ? data.title : '分享标题',
+						desc: data && data.desc ? data.desc : '分享内容',
+						link: data && data.url?data.url:window.location.origin,
+						imgUrl: data && data.img ? data.img : '',
+						success: function(res) {
+							
+						},
+						cancel: function(res) {}
+					};				
+					//自定义“分享给朋友”及“分享到QQ”按钮的分享内容;
+					jweixin.updateAppMessageShareData(shareData)
+					//自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容;
+					jweixin.updateTimelineShareData(shareData)
+					//分享到腾讯微博
+					jweixin.onMenuShareWeibo(shareData);
+				
+				});
+			});
+		}
+	}
+}

+ 352 - 0
common/html-parser.js

@@ -0,0 +1,352 @@
+/*
+ * HTML5 Parser By Sam Blowes
+ *
+ * Designed for HTML5 documents
+ *
+ * Original code by John Resig (ejohn.org)
+ * http://ejohn.org/blog/pure-javascript-html-parser/
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ *
+ * ----------------------------------------------------------------------------
+ * License
+ * ----------------------------------------------------------------------------
+ *
+ * This code is triple licensed using Apache Software License 2.0,
+ * Mozilla Public License or GNU Public License
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is Simple HTML Parser.
+ *
+ * The Initial Developer of the Original Code is Erik Arvidsson.
+ * Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
+ * Reserved.
+ *
+ * ////////////////////////////////////////////////////////////////////////////
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * ----------------------------------------------------------------------------
+ * Usage
+ * ----------------------------------------------------------------------------
+ *
+ * // Use like so:
+ * HTMLParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ * // or to get an XML string:
+ * HTMLtoXML(htmlString);
+ *
+ * // or to get an XML DOM Document
+ * HTMLtoDOM(htmlString);
+ *
+ * // or to inject into an existing document/DOM node
+ * HTMLtoDOM(htmlString, document);
+ * HTMLtoDOM(htmlString, document.body);
+ *
+ */
+// Regular Expressions for parsing tags and attributes
+var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
+var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
+
+var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
+// fixed by xxx 将 ins 标签从块级名单中移除
+
+var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
+
+var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
+// (and which close themselves)
+
+var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
+
+var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
+
+var special = makeMap('script,style');
+function HTMLParser(html, handler) {
+  var index;
+  var chars;
+  var match;
+  var stack = [];
+  var last = html;
+
+  stack.last = function () {
+    return this[this.length - 1];
+  };
+
+  while (html) {
+    chars = true; // Make sure we're not in a script or style element
+
+    if (!stack.last() || !special[stack.last()]) {
+      // Comment
+      if (html.indexOf('<!--') == 0) {
+        index = html.indexOf('-->');
+
+        if (index >= 0) {
+          if (handler.comment) {
+            handler.comment(html.substring(4, index));
+          }
+
+          html = html.substring(index + 3);
+          chars = false;
+        } // end tag
+
+      } else if (html.indexOf('</') == 0) {
+        match = html.match(endTag);
+
+        if (match) {
+          html = html.substring(match[0].length);
+          match[0].replace(endTag, parseEndTag);
+          chars = false;
+        } // start tag
+
+      } else if (html.indexOf('<') == 0) {
+        match = html.match(startTag);
+
+        if (match) {
+          html = html.substring(match[0].length);
+          match[0].replace(startTag, parseStartTag);
+          chars = false;
+        }
+      }
+
+      if (chars) {
+        index = html.indexOf('<');
+        var text = index < 0 ? html : html.substring(0, index);
+        html = index < 0 ? '' : html.substring(index);
+
+        if (handler.chars) {
+          handler.chars(text);
+        }
+      }
+    } else {
+      html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
+        text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
+
+        if (handler.chars) {
+          handler.chars(text);
+        }
+
+        return '';
+      });
+      parseEndTag('', stack.last());
+    }
+
+    if (html == last) {
+      throw 'Parse Error: ' + html;
+    }
+
+    last = html;
+  } // Clean up any remaining tags
+
+
+  parseEndTag();
+
+  function parseStartTag(tag, tagName, rest, unary) {
+    tagName = tagName.toLowerCase();
+
+    if (block[tagName]) {
+      while (stack.last() && inline[stack.last()]) {
+        parseEndTag('', stack.last());
+      }
+    }
+
+    if (closeSelf[tagName] && stack.last() == tagName) {
+      parseEndTag('', tagName);
+    }
+
+    unary = empty[tagName] || !!unary;
+
+    if (!unary) {
+      stack.push(tagName);
+    }
+
+    if (handler.start) {
+      var attrs = [];
+      rest.replace(attr, function (match, name) {
+        var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
+        attrs.push({
+          name: name,
+          value: value,
+          escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
+
+        });
+      });
+
+      if (handler.start) {
+        handler.start(tagName, attrs, unary);
+      }
+    }
+  }
+
+  function parseEndTag(tag, tagName) {
+    // If no tag name is provided, clean shop
+    if (!tagName) {
+      var pos = 0;
+    } // Find the closest opened tag of the same type
+    else {
+        for (var pos = stack.length - 1; pos >= 0; pos--) {
+          if (stack[pos] == tagName) {
+            break;
+          }
+        }
+      }
+
+    if (pos >= 0) {
+      // Close all the open elements, up the stack
+      for (var i = stack.length - 1; i >= pos; i--) {
+        if (handler.end) {
+          handler.end(stack[i]);
+        }
+      } // Remove the open elements from the stack
+
+
+      stack.length = pos;
+    }
+  }
+}
+
+function makeMap(str) {
+  var obj = {};
+  var items = str.split(',');
+
+  for (var i = 0; i < items.length; i++) {
+    obj[items[i]] = true;
+  }
+
+  return obj;
+}
+
+function removeDOCTYPE(html) {
+  return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
+}
+
+function parseAttrs(attrs) {
+  return attrs.reduce(function (pre, attr) {
+    var value = attr.value;
+    var name = attr.name;
+
+    if (pre[name]) {
+			pre[name] = pre[name] + " " + value;
+    } else {
+			pre[name] = value;
+    }
+
+    return pre;
+  }, {});
+}
+
+function parseHtml(html) {
+  html = removeDOCTYPE(html);
+  var stacks = [];
+  var results = {
+    node: 'root',
+    children: []
+  };
+  HTMLParser(html, {
+    start: function start(tag, attrs, unary) {
+      var node = {
+        name: tag
+      };
+
+      if (attrs.length !== 0) {
+        node.attrs = parseAttrs(attrs);
+      }
+
+      if (unary) {
+        var parent = stacks[0] || results;
+
+        if (!parent.children) {
+          parent.children = [];
+        }
+
+        parent.children.push(node);
+      } else {
+        stacks.unshift(node);
+      }
+    },
+    end: function end(tag) {
+      var node = stacks.shift();
+      if (node.name !== tag) console.error('invalid state: mismatch end tag');
+
+      if (stacks.length === 0) {
+        results.children.push(node);
+      } else {
+        var parent = stacks[0];
+
+        if (!parent.children) {
+          parent.children = [];
+        }
+
+        parent.children.push(node);
+      }
+    },
+    chars: function chars(text) {
+      var node = {
+        type: 'text',
+        text: text
+      };
+
+      if (stacks.length === 0) {
+        results.children.push(node);
+      } else {
+        var parent = stacks[0];
+
+        if (!parent.children) {
+          parent.children = [];
+        }
+
+        parent.children.push(node);
+      }
+    },
+    comment: function comment(text) {
+      var node = {
+        node: 'comment',
+        text: text
+      };
+      var parent = stacks[0];
+
+      if (!parent.children) {
+        parent.children = [];
+      }
+
+      parent.children.push(node);
+    }
+  });
+  return results.children;
+}
+
+export default parseHtml;

+ 157 - 0
common/iconfont.css

@@ -0,0 +1,157 @@
+@font-face {
+  font-family: "iconfont"; /* Project id  */
+  src: url('@/static/iconfont.ttf') format('truetype');
+}
+
+@font-face {
+  font-family: "iconfont"; /* Project id  */
+  src: url('@/static/iconfont2.ttf') format('truetype');
+}
+
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+.icon-shipinjiankong:before {
+  content: "\e60e";
+}
+
+.icon-shipinbofang:before {
+  content: "\e602";
+}
+
+.icon-shexiangtou:before {
+  content: "\e657";
+}
+
+.icon-shipinjiankong1:before {
+  content: "\e859";
+}
+
+.icon-shipinjiankong2:before {
+  content: "\e61b";
+}
+.icon-shijian:before {
+  content: "\e62a";
+}
+.icon-didian01:before {
+  content: "\e61f";
+}
+.icon-haoyou:before {
+  content: "\e600";
+}
+
+.icon-baoming:before {
+  content: "\e624";
+}
+
+.icon-kehufuwukefu:before {
+  content: "\e698";
+}
+
+.icon-baomingshuju:before {
+  content: "\e6a1";
+}
+
+.icon-PK:before {
+  content: "\e661";
+}
+
+.icon-daohang:before {
+  content: "\eaf2";
+}
+
+.icon-Basket-Ball:before {
+  content: "\eb6f";
+}
+
+.icon-renlian:before {
+  content: "\e690";
+}
+
+.icon-Rrl_s_141:before {
+  content: "\e614";
+}
+
+.icon-running:before {
+  content: "\e60c";
+}
+
+.icon-changguanyuyue:before {
+  content: "\e601";
+}
+
+.icon-xiangfatianjia:before {
+  content: "\e639";
+}
+
+.icon-shouye:before {
+  content: "\e60d";
+}
+
+.icon-shouye1:before {
+  content: "\e74b";
+}
+
+.icon-jianshenjiaolian:before {
+  content: "\e615";
+}
+
+.icon-jianshen3:before {
+  content: "\e669";
+}
+
+.icon-ic_mianxing_jiaxiaobaoming_1:before {
+  content: "\e613";
+}
+
+.icon-icon_xinyong_xianxing_jijin-161:before {
+  content: "\e64d";
+}
+
+.icon-zuduiqingqiu:before {
+  content: "\e619";
+}
+
+.icon-baoming1:before {
+  content: "\e642";
+}
+
+.icon-tuandui:before {
+  content: "\e682";
+}
+
+.icon-tuandui_xianxing:before {
+  content: "\e69c";
+}
+
+.icon-womentuandui:before {
+  content: "\e617";
+}
+
+.icon-zcpt-peixunbaomingguanli:before {
+  content: "\e916";
+}
+
+.icon-zuixing-55:before {
+  content: "\e63c";
+}
+
+.icon-tuandui1:before {
+  content: "\f4fe";
+}
+
+.icon-zudui:before {
+  content: "\f50f";
+}
+.icon-menjindukaqi:before {
+  content: "\e671";
+}
+
+.icon-person:before {
+  content: "\e61a";
+}

+ 72 - 0
common/share.js

@@ -0,0 +1,72 @@
+export default {
+	data() {
+		return {
+			//设置默认的分享参数
+			//如果页面不设置share,就触发这个默认的分享
+			share: {
+				title: '闽南魂',
+				path: '',
+				imageUrl: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/ccbg.png',
+				desc: '',
+				content: ''
+			}
+		}
+	},
+	onShareAppMessage(res) {
+		console.log(this.share.path);
+		if (this.share.path == '') {
+			var pages = getCurrentPages() // 获取栈实例
+			let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由			
+			let currentPage = pages[pages.length - 1]['$page']['fullPath'] //当前页面路径(带参数)
+			this.share.path = currentPage;
+		}
+		let user = this.$common.userInfo();
+		if (user) {
+			if (this.share.path.indexOf('from_userid') < 0) {
+				if (this.share.path.indexOf('?') > 0) {
+					this.share.path = this.share.path + '&from_userid=' + user.id
+				} else {
+					this.share.path = this.share.path + '?from_userid=' + user.id
+				}
+
+			}
+		}
+
+		return {
+			title: this.share.title,
+			path: this.share.path,
+			imageUrl: this.share.imageUrl,
+			desc: this.share.desc,
+			content: this.share.content,
+			success(res) {
+				uni.showToast({
+					title: '分享成功'
+				})
+			},
+			fail(res) {
+				uni.showToast({
+					title: '分享失败',
+					icon: 'none'
+				})
+			}
+		}
+	},
+	onShareTimeline(res) {
+		return {
+			title: this.share.title,
+			path: this.share.path,
+			imageUrl: this.share.imageUrl,
+			success(res) {
+				uni.showToast({
+					title: '分享成功'
+				})
+			},
+			fail(res) {
+				uni.showToast({
+					title: '分享失败',
+					icon: 'none'
+				})
+			}
+		}
+	}
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1448 - 0
common/uni.css


+ 466 - 0
common/util.js

@@ -0,0 +1,466 @@
+const extend = function extend(target) {
+	var sources = Array.prototype.slice.call(arguments, 1)
+
+	for (var i = 0; i < sources.length; i += 1) {
+		var source = sources[i]
+		for (var key in source) {
+			if (source.hasOwnProperty(key)) {
+				target[key] = source[key]
+			}
+		}
+	}
+
+	return target
+}
+
+/**
+ * 获取当前时间戳
+ */
+const getTimestamp = (date) => {
+	date = date || new Date()
+	return Math.round(date / 1000)
+}
+
+/**
+ * 保留指定小数位
+ */
+const toDecimal = (float, num) => {
+	if (typeof float !== 'number') float = parseFloat(float)
+	return parseFloat(float.toFixed(num))
+}
+
+/**
+ * 时间戳转 yyyy-MM-dd hh:mm
+ */
+export function formatDate(timestamp, format) {
+	const date = timestamp ? new Date(timestamp * 1000) : new Date();
+	const data = {
+		'M+': date.getMonth() + 1,
+		'd+': date.getDate(),
+		'h+': date.getHours(),
+		'm+': date.getMinutes(),
+		's+': date.getSeconds(),
+		'q+': Math.floor((date.getMonth() + 3) / 3),
+		'S+': date.getMilliseconds()
+	}
+	if (/(y+)/i.test(format)) {
+		format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+	}
+	for (var key in data) {
+		if (new RegExp('(' + key + ')').test(format)) {
+			format = format.replace(RegExp.$1, RegExp.$1.length == 1 ?
+				data[key] : ('00' + data[key]).substr(('' + data[key]).length))
+		}
+	}
+
+	return format
+}
+
+/**
+ * 分钟、小时、天前的处理
+ */
+const timeAgo = function(timestamp, format) {
+	const minute = 1000 * 60 // 把分,时,天,周,半个月,一个月用毫秒表示
+	const hour = minute * 60
+	const day = hour * 24
+	const now = new Date().getTime() // 获取当前时间毫秒
+	const spreadTime = now - timestamp * 1000 // 时间差
+	if (spreadTime < 0) {
+		return
+	}
+
+
+	const minC = spreadTime / minute
+	const hourC = spreadTime / hour
+	const dayC = spreadTime / day
+	let result
+
+	if (spreadTime >= 0 && spreadTime <= minute) {
+		result = '刚刚'
+	} else if (minC >= 1 && minC <= 59) {
+		result = parseInt(minC) + '分钟前'
+	} else if (hourC >= 1 && hourC <= 23) {
+		result = parseInt(hourC) + '小时前'
+	} else if (dayC >= 1 && dayC < 3) {
+		result = parseInt(dayC) + '天前'
+	} else if (dayC >= 3 && dayC <= 7) {
+		result = '3天前'
+	} else {
+		result = formatDate(timestamp, format)
+	}
+
+	return result
+}
+
+/**
+ * param 将要转为URL参数字符串的对象
+ * key URL参数字符串的前缀
+ * encode true/false 是否进行URL编码,默认为true
+ *
+ * return URL参数字符串
+ */
+const urlEncode = (param, key, encode) => {
+	if (param == null) return ''
+	const t = typeof(param)
+	let paramStr = ''
+	if (t === 'string' || t === 'number' || t === 'boolean') {
+		paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param)
+	} else {
+		for (let i in param) {
+			let k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '[' + i + ']')
+			paramStr += urlEncode(param[i], k, encode)
+		}
+	}
+
+	return paramStr
+}
+
+/**
+ * return
+ */
+const urlDecode = (query) => {
+	if (!query) return null
+	let hash, object = {}
+	const hashes = query.slice(query.indexOf('?') + 1).split('&')
+	for (let i = 0; i < hashes.length; i++) {
+		hash = hashes[i].split('=')
+		object[hash[0]] = hash[1]
+	}
+
+	return object;
+}
+
+/**
+ * 对象合并
+ */
+const deepAssign = (origin, source) => {
+	for (let key in source) {
+		if (source.hasOwnProperty(key)) {
+			if (source[key] instanceof Object) {
+				deepAssign(origin[key], source[key])
+			} else {
+				origin[key] = source[key]
+			}
+		}
+	}
+}
+
+/**
+ * 状态数据
+ */
+const display = {
+	toast: false, // 无用
+	modal: false,
+	loading: false,
+}
+
+// 显示消息提示
+const showToast = function(text, icon) {
+	wx.showToast({
+		title: text || '加载中',
+		icon: icon || 'none',
+		mask: true,
+		duration: 2000
+	})
+}
+
+// 隐藏消息提示
+const hideToast = function() {
+	wx.hideToast()
+}
+
+// 显示 loading
+const showLoading = function(text) {
+	if (!display.loading) {
+		display.loading = true
+		wx.showLoading({
+			title: text || '加载中',
+			mask: true
+		})
+	}
+}
+
+// 隐藏 loading
+const hideLoading = function() {
+	if (display.loading) {
+		display.loading = false
+		wx.hideLoading()
+	}
+}
+
+// 显示失败提示
+const showModal = (title, content) => {
+	if (display.toast) hideToast()
+	if (display.loading) hideLoading()
+
+	if (!display.modal) {
+		title = title || '信息提示'
+		content = content || '未知错误' // content 为 null 时会报错
+		display.modal = true
+		wx.showModal({
+			title,
+			content: typeof content === 'object' ? JSON.stringify(content) : content,
+			showCancel: false,
+			confirmColor: '#3B99FC',
+			complete: function(e) {
+				display.modal = false
+			}
+		})
+	}
+}
+
+export function buildPageUrl(page, options) {
+	let pageUrl = page;
+	if (options) {
+		let params = urlEncode(options)
+		pageUrl += '?' + params.substring(1, params.length);
+	}
+
+	return pageUrl;
+}
+
+export function encodeRedirectUrl(page, options) {
+	return encodeURIComponent(buildPageUrl(page, options));
+}
+
+export function decodeRedirectUrl(url) {
+	return decodeURIComponent(url);
+}
+
+/**
+ * 处理富文本里的图片宽度自适应
+ * 1.去掉img标签里的style、width、height属性
+ * 2.img标签添加style属性:max-width:100%;height:auto
+ * 3.修改所有style里的width属性为max-width:100%
+ * 4.去掉<br/>标签
+ * 
+ * @param html
+ * @returns {void|string|*}
+ */
+export function formatRichText(html) {
+	let newContent = html.replace(/<img[^>]*>/gi, function(match, capture) {
+		match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
+		match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
+		match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
+		return match;
+	});
+	newContent = newContent.replace(/style="[^"]+"/gi, function(match, capture) {
+		match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
+		return match;
+	});
+	newContent = newContent.replace(/<br[^>]*\/>/gi, '');
+	newContent = newContent.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:block;margin:10px 0;"');
+	return newContent;
+}
+
+function strlen(value) {
+	//中文、中文标点、全角字符按1长度,英文、英文符号、数字按0.5长度计算
+	let cnReg = /([\u4e00-\u9fa5]|[\u3000-\u303F]|[\uFF00-\uFF60])/g;
+	let mat = value.match(cnReg);
+	let length = 0;
+	if (mat) {
+		return (length = mat.length + (value.length - mat.length) * 0.5);
+	} else {
+		return (length = value.length * 0.5);
+	}
+}
+
+/**
+ *
+ *  判断是否在微信浏览器 true是
+ */
+function isWeiXinBrowser() {
+	// #ifdef H5
+	let ua = window.navigator.userAgent.toLowerCase()
+	if (ua.match(/MicroMessenger/i) == 'micromessenger') {
+		return true
+	} else {
+		return false
+	}
+	// #endif
+	return false
+}
+
+
+/**
+ * 获取url参数
+ * @param {*} name
+ * @param {*}
+ * @returns
+ */
+function getQueryString(name, url) {
+	var url = url || window.location.href
+	var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
+	var r = url.substr(1).match(reg)
+	if (r != null) {
+		return r[2]
+	}
+	return null
+}
+
+//路径转化
+function getPath(path) {
+	return path ? path.split('?').shift() : path;
+}
+
+//复制内容
+function uniCopy({
+	content,
+	success,
+	error
+}) {
+
+	content = typeof content === 'string' ? content : content.toString() // 复制内容,必须字符串,数字需要转换为字符串
+
+	/**
+	 * 小程序端 和 app端的复制逻辑
+	 */
+	//#ifndef H5
+	uni.setClipboardData({
+		data: content,
+		success: function() {
+			success("复制成功~")
+		},
+		fail: function() {
+			error("复制失败~")
+		}
+	});
+	//#endif
+
+	/**
+	 * H5端的复制逻辑
+	 */
+	// #ifdef H5
+	if (!document.queryCommandSupported('copy')) { //为了兼容有些浏览器 queryCommandSupported 的判断
+		// 不支持
+		error('浏览器不支持')
+	}
+	let textarea = document.createElement("textarea")
+	textarea.value = content
+	textarea.readOnly = "readOnly"
+	document.body.appendChild(textarea)
+	textarea.select() // 选择对象
+	textarea.setSelectionRange(0, content.length) //核心
+	let result = document.execCommand("copy") // 执行浏览器复制命令
+	if (result) {
+		success("复制成功~")
+	} else {
+		error("复制失败,请检查h5中调用该方法的方式,是不是用户点击的方式调用的,如果不是请改为用户点击的方式触发该方法,因为h5中安全性,不能js直接调用!")
+	}
+	textarea.remove()
+	// #endif
+}
+
+
+//设置缓存
+function setDb(name, value, db_time = 7200) {
+	let time = (new Date()).getTime();
+	let data = {
+		value: value,
+		time: time,
+		db_time: db_time
+	}
+	uni.setStorageSync(name, data);
+}
+//获取缓存
+function getDb(name) {
+	try {
+		let res = uni.getStorageSync(name);
+		if (!res) {
+			return '';
+		}
+		let time = (new Date()).getTime();
+		if ((time - res.time) / 1000 >= res.db_time) {
+			uni.removeStorageSync(name);
+			return '';
+		}
+		return res.value;
+	} catch (e) {
+		//TODO handle the exception
+		return '';
+	}
+}
+
+/**
+ * 下载图片
+ */
+function getCachedImage(image_url) {
+	return new Promise((resolve, reject) => {
+		let arr = image_url.split('/');
+		let image_name = arr[arr.length - 1];
+		var u = getDb('cms' + image_name);
+		if (u) {
+			resolve(u);
+		} else {
+			// 本地没有缓存 需要下载
+			uni.downloadFile({
+				url: image_url,
+				success: res => {
+					if (res.statusCode === 200) {
+						uni.saveFile({
+							tempFilePath: res.tempFilePath,
+							success: function(res) {
+								setDb('cms' + image_name, res.savedFilePath)
+								resolve(res.savedFilePath);
+							}
+						});
+					} else {
+						reject('下载失败');
+					}
+				},
+				fail: function() {
+					reject('下载失败');
+				}
+			});
+		}
+	});
+}
+/**
+ * 重设tabbar
+ * @param {Object} tablist
+ */
+function setTabbar(tablist) {
+	tablist.list.forEach((item, index) => {
+		uni.setTabBarItem({
+			index: index,
+			text: item.text,
+			iconPath: item.image,
+			selectedIconPath: item.selectedImage,
+			pagePath: item.path
+		})
+	})
+	uni.setTabBarStyle({
+		color: tablist.color,
+		selectedColor: tablist.selectColor,
+		backgroundColor: tablist.bgColor,
+		borderStyle: 'black'
+	})
+}
+
+
+export default {
+	extend,
+	toDecimal,
+	getTimestamp,
+	formatDate,
+	timeAgo,
+	urlEncode,
+	urlDecode,
+	deepAssign,
+	showToast,
+	hideToast,
+	showLoading,
+	hideLoading,
+	showModal,
+	formatRichText,
+	strlen,
+	isWeiXinBrowser,
+	getQueryString,
+	getPath,
+	uniCopy,
+	setDb,
+	getDb,
+	getCachedImage,
+	setTabbar,
+	encodeRedirectUrl
+}

+ 202 - 0
components/course-item/course-item.vue

@@ -0,0 +1,202 @@
+<template>
+	<view class="course-item" @click="onJumpDetail">
+		<view class="b-cover">
+			<image style="width: 100%; height: 100%" :src="item.cover_url" mode="aspectFill"></image>
+		</view>
+		<view class="b-main">
+			<text class="text_23">{{ item.name }}</text>
+			<view class="b-price">
+				<view class="aa" style="display: flex; margin-top: 70rpx; width: 150rpx">
+					<view lines="1" class="text_25">会员价</view>
+					<view lines="1" class="text_26">¥{{ item.price }}</view>
+				</view>
+
+				<!-- <view class="s-vip-price" v-if="item.card_price > 0 && !iphonePlatform">会员价 ¥{{ item.card_price }}</view> -->
+				<button bindtap="onClick" class="button_6">
+					<text lines="1" class="text_27">立即报名</text>
+				</button>
+			</view>
+			<!-- <view class="b-info">
+				<view class="s-category">{{ item.category_name }}</view>
+				<view class="b-counter">
+					<view class="s-learn">{{ item.count_user }}人学习</view>
+				</view>
+			</view> -->
+		</view>
+	</view>
+</template>
+
+<script>
+import mixinsGoods from '@/mixins/goods.js';
+export default {
+	name: 'course-item',
+	mixins: [mixinsGoods],
+	props: {
+		item: {
+			type: Object,
+			default: null
+		}
+	},
+	data() {
+		return {};
+	},
+	methods: {
+		onJumpDetail() {
+			console.log(11);
+			uni.navigateTo({
+				url: '/pages/course/detail?cid=' + this.item.id
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.button_6 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	height: 44rpx;
+	display: flex;
+	flex-direction: column;
+	width: 129rpx;
+	margin: 70rpx 18rpx 0 82rpx;
+}
+.text_23 {
+	width: 110rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-left: 1rpx;
+}
+.text_25 {
+	width: 60rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 20rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 2rpx;
+}
+.text_26 {
+	width: 56rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text_27 {
+	color: rgba(248, 226, 175, 1);
+	font-size: 24rpx;
+	white-space: nowrap;
+	line-height: 45rpx;
+	margin-left: -10rpx;
+}
+.course-item {
+	padding: 30upx;
+	background: #fff;
+	display: flex;
+	align-items: center;
+}
+
+.course-item:last-child {
+	margin-bottom: 0;
+}
+
+.course-item .b-cover {
+	width: 307rpx;
+	height: 171rpx;
+}
+
+.course-item .b-cover image {
+	width: 100%;
+	height: 100%;
+}
+
+.course-item .b-main {
+	flex: 1;
+	height: 170rpx;
+	margin-left: 20upx;
+}
+
+.course-item .b-main .b-title {
+	font-size: 30upx;
+	color: #333;
+	max-width: 530upx;
+	display: inline-block;
+}
+
+.course-item .b-main .b-price {
+	margin-top: 16upx;
+	display: flex;
+	align-items: center;
+}
+
+.course-item .b-main .b-price .s-payment {
+	margin-right: 20upx;
+	font-size: 36upx;
+	font-weight: bold;
+	color: #dd524d;
+}
+
+.course-item .b-main .b-price .s-payment.f-small {
+	font-size: 28upx;
+}
+
+.course-item .b-main .b-price .s-vip-price {
+	margin-right: 20upx;
+	font-size: 26upx;
+	color: #f0ad4e;
+}
+
+.course-item .b-main .b-price .s-vip-free {
+	margin-right: 20upx;
+	padding: 6upx 10upx;
+	font-size: 24upx;
+	color: #555;
+	background: #f0ad4e;
+	border-radius: 5upx;
+}
+
+.course-item .b-main .b-info {
+	margin-top: 16upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.course-item .b-main .b-info .s-category {
+	font-size: 26upx;
+	color: #666;
+}
+
+.course-item .b-main .b-info .b-counter {
+	display: flex;
+	align-items: center;
+}
+
+.course-item .b-main .b-info .b-counter .s-like {
+	font-size: 24upx;
+	color: #999;
+}
+
+.course-item .b-main .b-info .b-counter .s-learn {
+	margin-left: 30upx;
+	font-size: 24upx;
+	color: #999;
+}
+</style>

+ 73 - 0
components/mn_yindaoye.vue

@@ -0,0 +1,73 @@
+<template>
+	<view class="box" :style="{ height: screenHeight + 'px' }">
+		<view class="tiaoguo" @click="skipGuide">
+			<view>{{ countdown }}跳过</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			screenHeight: 0,
+			interval: null, // 用于存储倒计时的定时器ID
+			countdown: 3 // 倒计时初始值
+		};
+	},
+	onLoad() {
+		// 获取窗口高度
+		const systemInfo = uni.getSystemInfoSync();
+		this.screenHeight = systemInfo.screenHeight;
+	},
+	mounted() {
+		this.startCountdown();
+	},
+	methods: {
+		// 开始倒计时
+		startCountdown() {
+			this.interval = setInterval(() => {
+				if (this.countdown > 0) {
+					this.countdown--;
+				} else {
+					clearInterval(this.interval);
+					this.closeGuide();
+				}
+			}, 1000); // 每秒减少1
+		},
+		// 跳过引导
+		skipGuide() {
+			// 清除延时器不然会跳 两次
+			clearInterval(this.interval);
+			this.closeGuide();
+		},
+		closeGuide() {
+			uni.switchTab({
+				url: '/pages/index/index'
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.box {
+	width: 100%;
+	height: 100%;
+	background-image: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_yindaoye.jpg');
+	background-size: cover;
+}
+.img {
+	width: 100%;
+	height: 100%;
+}
+.tiaoguo {
+	width: 100rpx;
+	border-radius: 20rpx;
+	position: absolute;
+	top: 160rpx;
+	right: 38rpx;
+	text-align: center;
+	background-color: rgba(0, 0, 0, 0.3);
+}
+</style>

+ 78 - 0
components/mntabBar/mntabBar.vue

@@ -0,0 +1,78 @@
+<template>
+	<view>
+		<view style="height: 75px"></view>
+		<view class="cu-bar tabbar bg-gray shadow foot">
+			<view class="action" :class="footerTab == '0' ? 'text-red' : 'text-black'" @tap="clickTabPath('/pages/index/index')">
+				<!-- <u-icon name="https://huli-app.wenlvti.net/app_static/minnanhun/image/home_a.png" color="#a49086" size="20" labelPos="bottom"></u-icon> -->
+				<image style="width: 56rpx; height: 40rpx" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/home_a.png" mode=""></image>
+				<view class="">首页</view>
+			</view>
+
+			<view class="action" :class="footerTab == '1' ? 'text-red' : 'text-black'" @tap="clickTabPath('/pages/jiyi/jiyi')">
+				<!-- <u-icon name="https://huli-app.wenlvti.net/app_static/minnanhun/image/commossion_a.png" color="#a49086" size="20" labelPos="bottom"></u-icon> -->
+
+				<image style="width: 56rpx; height: 40rpx" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/commossion_a.png" mode=""></image>
+				<view class="">记忆</view>
+			</view>
+
+			<view class="action add-action" :class="footerTab == '2' ? 'text-red' : 'text-black'" @tap="clickTabPath('/pages/chuanCheng/chuanCheng')">
+				<view class="cuIcon-">
+					<u-icon
+						size="35"
+						labelSize="22rpx"
+						space="10rpx"
+						:labelColor="footerTab == '2' ? '#CA5642' : '#666666'"
+						name="https://huli-app.wenlvti.net/app_static/minnanhun/image/wajue.png"
+						label="传承"
+						labelPos="bottom"
+					></u-icon>
+				</view>
+			</view>
+
+			<view class="action" :class="footerTab == '3' ? 'text-red' : 'text-black'" @tap="clickTabPath('/pages/xueYuan/xueYuan')">
+				<!-- <u-icon name="https://huli-app.wenlvti.net/app_static/minnanhun/image/invite_a.png" color="#a49086" size="20" labelPos="bottom"></u-icon> -->
+				<image style="width: 56rpx; height: 40rpx" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/invite_a.png" mode=""></image>
+				<view class="">学院</view>
+			</view>
+
+			<view class="action" :class="footerTab == '4' ? 'text-red' : 'text-black'" @tap="clickTabPath('/pages/user/index')">
+				<!-- <u-icon name="https://huli-app.wenlvti.net/app_static/minnanhun/image/mine_a.png" color="#a49086" size="20" labelPos="bottom"></u-icon> -->
+				<image style="width: 56rpx; height: 40rpx" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/mine_a.png" mode=""></image>
+				<view class="">我的</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'colorBar',
+	props: {
+		footerTab: {
+			type: String,
+			default: 0
+		},
+		messageCount: {
+			type: Number,
+			default: 0
+		}
+	},
+	data() {
+		return {};
+	},
+	methods: {
+		clickTabPath(url) {
+			console.log(url);
+			uni.switchTab({
+				url: url
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.action {
+	line-height: 25rpx !important;
+}
+</style>

+ 153 - 0
components/quick-cart/quick-cart.vue

@@ -0,0 +1,153 @@
+<template>
+	<view class="component" v-if="show">
+		<view class="sub-block">
+			<view class="b-main" @click="onClose()">
+				<view class="b-info">
+					<view class="b-count" @click.stop="onJumpCart()">
+						<view class="iconfont icon-user-cart"></view>
+						<view class="s-num">{{ cartCount }}</view>
+					</view>
+					<view class="b-price">¥{{ totalPrice }}</view>
+				</view>
+				<view class="b-action" @click.stop="onPreview()">
+					<view class="s-submit">去结算</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'quick-cart',
+	props: {
+		show: {
+			type: Boolean,
+			default: false
+		}
+	},
+	data() {
+		return {};
+	},
+	computed: {
+		cartCount() {
+			return this.$store.getters.cartCount;
+		},
+		totalPrice() {
+			const cartList = this.$store.getters.cartList;
+			let totalPrice = 0;
+			for (var i = 0; i < cartList.length; i++) {
+				totalPrice += parseFloat(cartList[i].goods_price);
+			}
+			return totalPrice;
+		}
+	},
+	methods: {
+		onJumpCart(e) {
+			console.log('onJumpCart');
+			uni.navigateTo({
+				url: '/pages/order/cart'
+			});
+		},
+		onClose(e) {
+			console.log('onClose');
+			this.$emit('close');
+		},
+		onPreview() {
+			console.log('onPreview');
+			const cartList = this.$store.getters.cartList;
+			let goodsData = [];
+			for (var i = 0; i < cartList.length; i++) {
+				let cartItem = cartList[i];
+				goodsData.push({
+					cart_id: cartItem.id,
+					goods_type: cartItem.goods_type,
+					goods_id: cartItem.goods_id
+				});
+			}
+			uni.navigateTo({
+				url: '/pages/order/preview?goods_data=' + JSON.stringify(goodsData)
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.sub-block {
+	position: fixed;
+	left: 30upx;
+	bottom: 150upx;
+	z-index: 100;
+	width: 690upx;
+}
+
+.sub-block image {
+	width: 100%;
+}
+
+.b-main {
+	width: 690upx;
+	height: 100upx;
+	background: #fff;
+	border: 2upx solid #eee;
+	border-radius: 50upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.b-info {
+	padding: 0 20upx;
+	display: flex;
+	align-items: center;
+}
+
+.b-info .b-count {
+	position: relative;
+}
+
+.b-info .b-count .iconfont {
+	font-size: 50upx;
+	width: 60upx;
+	height: 60upx;
+	color: #666;
+}
+
+.b-info .b-count .s-num {
+	position: absolute;
+	right: -10upx;
+	top: -30upx;
+	font-size: 24upx;
+	background: #da5650;
+	color: #fff;
+	width: 40upx;
+	height: 40upx;
+	line-height: 40upx;
+	text-align: center;
+	border-radius: 20upx;
+}
+
+.b-info .b-price {
+	margin-left: 20upx;
+	font-size: 28upx;
+	font-weight: bold;
+	color: #da5650;
+}
+
+.b-action {
+	padding: 0 20upx;
+	display: flex;
+	align-items: center;
+}
+
+.b-action .s-submit {
+	padding: 0 50upx;
+	height: 70upx;
+	line-height: 70upx;
+	font-size: 26upx;
+	color: #fff;
+	background: #da5650;
+	border-radius: 35upx;
+}
+</style>

+ 209 - 0
components/schedule-item/schedule-item.vue

@@ -0,0 +1,209 @@
+<template>
+	<view class="schedule-item" :class="{ 'f-index': scene === 'index' }" @click="onJumpDetail">
+		<view class="b-cover">
+			<image style="width: 100%; height: 100%" :src="item.cover_url" mode="aspectFill"></image>
+		</view>
+		<view class="b-main">
+			<text class="text_23">{{ item.name }}</text>
+			<view class="b-price">
+				<!-- <view class="s-payment" :class="{ 'f-small': textCost }">{{ goodsPrice(item.price) }}</view> -->
+				<view class="aa" style="display: flex; margin-top: 70rpx; width: 150rpx">
+					<view lines="1" class="text_25">会员价</view>
+					<view lines="1" class="text_26">¥{{ item.price }}</view>
+				</view>
+				<!-- <view class="s-vip-price" v-if="item.card_price > 0 && !iphonePlatform">会员价 ¥{{ item.card_price }}</view> -->
+				<button bindtap="onClick" class="button_6">
+					<text lines="1" class="text_27">立即报名</text>
+				</button>
+			</view>
+			<!-- 分类 -->
+			<!-- 		<view class="b-info">
+				<view class="s-category">{{ item.category_name }}</view>
+				<view class="b-counter">
+					<view class="s-learn">{{ item.count_user }}人参加</view>
+				</view>
+			</view> -->
+		</view>
+	</view>
+</template>
+
+<script>
+import mixinsGoods from '@/mixins/goods.js';
+export default {
+	name: 'schedule-item',
+	mixins: [mixinsGoods],
+	props: {
+		item: {
+			type: Object,
+			default: null
+		},
+		scene: {
+			type: String,
+			default: null
+		}
+	},
+	data() {
+		return {};
+	},
+	methods: {
+		onJumpDetail() {
+			uni.navigateTo({
+				url: '/pages/schedule/detail?sid=' + this.item.id
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.button_6 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	height: 44rpx;
+	display: flex;
+	flex-direction: column;
+	width: 129rpx;
+	margin: 70rpx 18rpx 0 50rpx;
+}
+.text_27 {
+	color: rgba(248, 226, 175, 1);
+	font-size: 24rpx;
+	white-space: nowrap;
+	line-height: 45rpx;
+	margin-left: -10rpx;
+}
+.text_23 {
+	width: 110rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-left: 1rpx;
+}
+.text_25 {
+	width: 60rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 20rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 2rpx;
+}
+.text_26 {
+	width: 56rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.schedule-item {
+	padding: 20rpx;
+	background: #fff;
+	display: flex;
+	align-items: center;
+}
+
+.schedule-item:last-child {
+	margin-bottom: 0;
+}
+
+.schedule-item.f-index .b-main .b-title {
+	max-width: 370upx;
+}
+
+.schedule-item .b-cover {
+	width: 220rpx;
+	height: 160rpx;
+}
+
+.schedule-item .b-cover image {
+	width: 100%;
+	height: 100%;
+}
+
+.schedule-item .b-main {
+	flex: 1;
+	margin-left: 20upx;
+}
+
+.schedule-item .b-main .b-title {
+	font-size: 30upx;
+	color: #333;
+	max-width: 530upx;
+	display: inline-block;
+}
+
+.schedule-item .b-main .b-price {
+	margin-top: 16upx;
+	display: flex;
+	align-items: center;
+}
+
+.schedule-item .b-main .b-price .s-payment {
+	margin-right: 20upx;
+	font-size: 36upx;
+	font-weight: bold;
+	color: #dd524d;
+}
+
+.schedule-item .b-main .b-price .s-payment.f-small {
+	font-size: 28upx;
+}
+
+.schedule-item .b-main .b-price .s-vip-price {
+	margin-right: 20upx;
+	font-size: 26upx;
+	color: #f0ad4e;
+}
+
+.schedule-item .b-main .b-price .s-vip-free {
+	margin-right: 20upx;
+	padding: 6upx 10upx;
+	font-size: 24upx;
+	color: #555;
+	background: #f0ad4e;
+	border-radius: 5upx;
+}
+
+.schedule-item .b-main .b-info {
+	margin-top: 16upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.schedule-item .b-main .b-info .s-category {
+	font-size: 26upx;
+	color: #666;
+}
+
+.schedule-item .b-main .b-info .b-counter {
+	display: flex;
+	align-items: center;
+}
+
+.schedule-item .b-main .b-info .b-counter .s-like {
+	font-size: 24upx;
+	color: #999;
+}
+
+.schedule-item .b-main .b-info .b-counter .s-learn {
+	margin-left: 20upx;
+	font-size: 24upx;
+	color: #999;
+}
+</style>

+ 385 - 0
config/api.js

@@ -0,0 +1,385 @@
+import {
+	baseUrl,
+	baseApiUrl
+} from './config.js';
+import * as common from './common.js' //引入common
+import * as db from './db.js' //引入common
+// 需要登陆的,都写到这里,否则就是不需要登陆的接口
+let methodsToken = ['profile', 'refreshUser', 'wxLogin', 'changeMobile', 'getWuyuanUser', 'getContentDetail',
+	'addCart', 'previewOrder',
+];
+const post = (method, data, callback, type, orgurl) => {
+	let userToken = '';
+	let auth = '';
+	// 判断token是否存在
+	// console.log("method: ", method);
+	if (methodsToken.indexOf(method) >= 0) {
+		// 获取用户token
+		let auth = db.get("auth");
+		// console.log(auth);
+		let nowdate = (new Date()) / 1000; //当前时间戳
+		//新增用户判断是否登录逻辑begin
+		common.isLogin();
+		//新增用户判断是否登录逻辑end
+		if (!auth || auth.createtime + auth.expires_in < nowdate) {
+			common.toLogin();
+			return false;
+		} else {
+			userToken = auth.token;
+		}
+	}
+
+	if (type) {
+		method = type + '/' + method
+	} else {
+		method = '/' + method
+	}
+
+	let realurl = baseApiUrl + method;
+
+	if (orgurl) {
+		realurl = baseUrl + orgurl;
+	}
+
+
+	uni.showLoading({
+		title: '',
+		icon: 'loading'
+	});
+	uni.request({
+		url: realurl,
+		data: data,
+		header: {
+			'Accept': 'application/json',
+			'Content-Type': 'application/x-www-form-urlencoded',
+			'token': userToken,
+			'__token__': userToken
+
+		},
+		method: 'POST',
+		success: (response) => {
+			uni.hideLoading();
+			const result = response.data
+			if (result.msg == 'Please login' || result.msg == '请登陆') {
+				db.del("user");
+				db.del("auth");
+				console.log('未登陆')
+				uni.showToast({
+					title: result.msg,
+					icon: 'none',
+					duration: 2000,
+					complete: function() {
+						uni.reLaunch({
+							url: '/pages/index/index',
+						})
+					}
+				});
+			}
+			callback(result);
+		},
+		fail: (error) => {
+			uni.hideLoading();
+			if (error && error.response) {
+				showError(error.response);
+			}
+		},
+	});
+}
+
+// 上传图片
+export const uploadImage = (method, data = {}, callback, num = 9, type) => {
+	if (type) {
+		method = type + '/' + method
+	} else {
+		method = method
+	}
+	let userToken = '';
+	let auth = db.get("auth");
+	userToken = auth.token;
+	uni.chooseImage({
+		count: num,
+		success: (res) => {
+			uni.showLoading({
+				title: '上传中...'
+			});
+			let tempFilePaths = res.tempFilePaths
+			for (var i = 0; i < tempFilePaths.length; i++) {
+				data.file = tempFilePaths[i]
+				uni.uploadFile({
+					url: baseApiUrl + method,
+					filePath: tempFilePaths[i],
+					fileType: 'image',
+					name: 'file',
+					headers: {
+						'Accept': 'application/json',
+						'Content-Type': 'multipart/form-data',
+						'token': userToken
+					},
+					formData: data,
+					success: (uploadFileRes) => {
+						callback(JSON.parse(uploadFileRes.data))
+					},
+					fail: (error) => {
+						if (error && error.response) {
+							common.showError(error.response);
+						}
+					},
+					complete: () => {
+						setTimeout(function() {
+							uni.hideLoading();
+						}, 250);
+					},
+				});
+			}
+		}
+	});
+}
+
+const get = (url, callback) => {
+	uni.showLoading({
+		title: '加载中'
+	});
+	let realurl = baseUrl + url;
+
+	if (url.indexOf('http:') >= 0 || url.indexOf('https:') >= 0) {
+		let realurl = url;
+	}
+	uni.request({
+		url: realurl,
+		header: {
+			'Accept': 'application/json',
+			'Content-Type': 'application/x-www-form-urlencoded', //自定义请求头信息
+		},
+		method: 'GET',
+		success: (response) => {
+			callback(response.data);
+		},
+		fail: (error) => {
+			if (error && error.response) {
+				showError(error.response);
+			}
+		},
+		complete: () => {
+			setTimeout(function() {
+				uni.hideLoading();
+			}, 250);
+		}
+	});
+}
+
+const showError = error => {
+	let errorMsg = ''
+	switch (error.status) {
+		case 400:
+			errorMsg = '请求参数错误'
+			break
+		case 401:
+			errorMsg = '未授权,请登录'
+			break
+		case 403:
+			errorMsg = '跨域拒绝访问'
+			break
+		case 404:
+			errorMsg = `请求地址出错: ${error.config.url}`
+			break
+		case 408:
+			errorMsg = '请求超时'
+			break
+		case 500:
+			errorMsg = '服务器内部错误'
+			break
+		case 501:
+			errorMsg = '服务未实现'
+			break
+		case 502:
+			errorMsg = '网关错误'
+			break
+		case 503:
+			errorMsg = '服务不可用'
+			break
+		case 504:
+			errorMsg = '网关超时'
+			break
+		case 505:
+			errorMsg = 'HTTP版本不受支持'
+			break
+		default:
+			errorMsg = error.msg
+			break
+	}
+	uni.showToast({
+		title: errorMsg,
+		icon: 'none',
+		duration: 2000
+	});
+}
+
+
+
+const syncget = (url, data) => {
+	return new Promise(function(resolve, reject) {
+		get(url + queryParams(data, true), (result) => {
+			try {
+				resolve(result);
+			} catch (e) {
+				reject(e);
+			}
+		})
+	})
+
+}
+
+const syncpost = (f, m, d) => {
+	return new Promise(function(resolve, reject) {
+		post(f, d, (result) => {
+			try {
+				resolve(result);
+			} catch (e) {
+				reject(e);
+			}
+		}, m, m);
+	})
+
+}
+// 登录
+export const third = (data, callback) => post('third', data, callback, 'discover/user/third');
+// 用户绑定手机
+export const bindphone = (data, callback) => post('bind', data, callback, 'discover/User');
+// 修改用户信息
+export const profile = (data, callback) => post('profile', data, callback, 'discover/User');
+// 发送验证码
+export const sendSmsVerify = (data, callback) => post('sendSmsVerify', data, callback, 'discover/User');
+// 刷新用户
+export const refreshUser = (data, callback) => post('refreshUser', data, callback, 'discover/User');
+
+// 注册
+export const register = (data, callback) => post('register', data, callback, 'discover/User');
+// 登录
+export const login = (data, callback) => post('login', data, callback, 'discover/User');
+// 退出登录
+export const logout = (data, callback) => post('logout', data, callback, 'discover/User');
+// 上传头像
+export const upload = (data, callback) => post('upload', data, callback, 'discover/Ajax');
+
+// 绑定手机
+export const changeMobile = (data, callback) => post('changeMobile', data, callback, 'discover/User');
+
+//获取手机号前先登录
+export const wxLogin = (data, callback) => post('wxLogin', data, callback, 'user');
+//获取手机号
+export const getMobile = (data, callback) => post('getPhoneNumber', data, callback, 'user');
+//取CMS配置
+// export const getConfig = async (params = {}) => await syncget('addons/cms/api.common/init', params);
+
+
+function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
+	let prefix = isPrefix ? '?' : ''
+	let _result = []
+	if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets';
+	for (let key in data) {
+		let value = data[key]
+		// 去掉为空的参数
+		if (['', undefined, null].indexOf(value) >= 0) {
+			continue;
+		}
+		if (value.length > 0) {
+			value = value.replace(/%/g, "%25");
+			value = value.replace(/\&/g, "%26");
+			value = value.replace(/\+/g, "%2B");
+		}
+
+		// 如果值为数组,另行处理
+		if (value.constructor === Array) {
+			// e.g. {ids: [1, 2, 3]}
+			switch (arrayFormat) {
+				case 'indices':
+					// 结果: ids[0]=1&ids[1]=2&ids[2]=3
+					for (let i = 0; i < value.length; i++) {
+						_result.push(key + '[' + i + ']=' + value[i])
+					}
+					break;
+				case 'brackets':
+					// 结果: ids[]=1&ids[]=2&ids[]=3
+					value.forEach(_value => {
+						_result.push(key + '[]=' + _value)
+					})
+					break;
+				case 'repeat':
+					// 结果: ids=1&ids=2&ids=3
+					value.forEach(_value => {
+						_result.push(key + '=' + _value)
+					})
+					break;
+				case 'comma':
+					// 结果: ids=1,2,3
+					let commaStr = "";
+					value.forEach(_value => {
+						commaStr += (commaStr ? "," : "") + _value;
+					})
+					_result.push(key + '=' + commaStr)
+					break;
+				default:
+					value.forEach(_value => {
+						_result.push(key + '[]=' + _value)
+					})
+			}
+		} else {
+			_result.push(key + '=' + value)
+		}
+	}
+	return _result.length ? prefix + _result.join('&') : ''
+}
+
+//取轮播图
+export const getBannerList = (data, callback) => get('/api/wuyuan/swiper_icon/lists' + queryParams(data, true),
+	callback);
+export const getWuyuanUser = (data, callback) => post('getWuyuanUser', data, callback, 'wuyuan/user');
+// 学院底部课程
+export const getHomeData = (data, callback) => post('getHomeData', data, callback, '',
+	'addons/yuneducation/page/getHomeData');
+// 课程界面数据
+export const getCourseList = (data, callback) => post('getCourseList', data, callback, '',
+	'addons/yuneducation/course/getCourseList');
+// 课程详情
+export const getCourseDetail = (data, callback) => post('getCourseDetail', data, callback, '',
+	'addons/yuneducation/course/getCourseDetail');
+// 获取课程考核
+export const getCourseExamine = (data, callback) => post('getCourseExamine', data, callback, '',
+	'addons/yuneducation/course/getCourseExamine');
+// 课程开始学习
+export const startLearn = (data, callback) => post('startLearn', data, callback, '',
+	'addons/yuneducation/course/startLearn');
+// 试播
+export const getContentDetail = (data, callback) => post('getContentDetail', data, callback, '',
+	'addons/yuneducation/course/getContentDetail');
+// 加入购物车
+export const addCart = (data, callback) => post('addCart', data, callback, '',
+	'addons/yuneducation/order/addCart');
+// 预览订单
+export const previewOrder = (data, callback) => post('previewOrder', data, callback, '',
+	'addons/yuneducation/order/previewOrder');
+// 提交订单
+export const submitOrder = (data, callback) => post('submitOrder', data, callback, '',
+	'addons/yuneducation/order/submitOrder');
+// 移除购物车
+export const removeCart = (data, callback) => post('removeCart', data, callback, '',
+	'addons/yuneducation/order/removeCart');
+// 讲师详情
+export const getTeacherDetail = (data, callback) => post('getTeacherDetail', data, callback, '',
+	'addons/yuneducation/teacher/getTeacherDetail');
+// 培训分类列表
+export const getCategoryList = (data, callback) => post('getCategoryList', data, callback, '',
+	'addons/yuneducation/course/getCategoryList');
+// 获取培训列表
+export const getScheduleList = (data, callback) => post('getScheduleList', data, callback, '',
+	'addons/yuneducation/schedule/getScheduleList');
+// 获取培训详情
+
+export const getScheduleDetail = (data, callback) => post('getScheduleDetail', data, callback, '',
+	'addons/yuneducation/schedule/getScheduleDetail');
+// 培训开始学习
+export const scheduleStartLearn = (data, callback) => post('startLearn', data, callback, '',
+	'addons/yuneducation/schedule/startLearn');
+// 获取我的课程列表
+export const getMineCourseList = (data, callback) => post('getMineCourseList', data, callback, '',
+	'addons/yuneducation/course/getMineCourseList');

+ 647 - 0
config/common.js

@@ -0,0 +1,647 @@
+import * as db from './db.js' //引入common
+import * as api from './api.js'
+import {
+	baseUrl,
+	cndUrl,
+	bgClass,
+	title,
+	baseLogo,
+} from './config.js'
+import htmlParser from '@/common/html-parser' //引入htmlParser
+
+
+/**
+ * 跳转登陆页面
+ */
+function toLogin() {
+
+	uni.showToast({
+		title: '请登录...',
+		icon: 'loading',
+		duration: 2000,
+		success: function(res) {
+			var pages = getCurrentPages() // 获取栈实例
+			let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
+			//console.log("路由当前页面路径"+currentRoute)
+			let currentPage = pages[pages.length - 1]['$page']['fullPath'] //当前页面路径(带参数)
+			// console.log(currentPage)
+
+			// #ifdef H5 || APP-PLUS
+			uni.navigateTo({
+				url: '/pages/user/login?redirect=' + escape(currentPage)
+			})
+			// #endif
+			// #ifdef MP-WEIXIN
+			uni.navigateTo({
+				url: '/pages/user/login?redirect=' + escape(currentPage),
+				animationType: 'pop-in',
+				animationDuration: 200
+			});
+			// #endif
+		}
+	})
+}
+
+/**
+ * 是否登陆,和绑定手机号,否则返回登录页
+ */
+function isLogin() {
+	let user = db.get('user');
+	//用户存在,不跳转,不存在直接跳转
+	if (user) {
+		if (user.id) {
+			// if(user.mobile==''){
+			// 	uni.navigateTo({
+			// 		url: '/pages/user/bind'
+			// 	})
+			// }	
+
+		} else {
+			console.log("user: ", user);
+			db.del('user');
+			db.del('auth');
+			toLogin()
+		}
+	}
+}
+/**
+ * 无图标提示
+ * @param {String} msg 提示消息
+ * @param {Function} callback 回调函数
+ */
+
+function normalToShow(msg = '保存成功', callback = function() {}) {
+	uni.showToast({
+		title: msg,
+		icon: 'none',
+		duration: 2000,
+	});
+	setTimeout(function() {
+		callback();
+	}, 1000);
+}
+/**
+ * 成功提示
+ * @param {String} msg 提示消息
+ * @param {Function} callback 回调函数
+ */
+
+function successToShow(msg = '保存成功', callback = function() {}) {
+	uni.showToast({
+		title: msg,
+		icon: 'success',
+		duration: 2000,
+	});
+	setTimeout(function() {
+		callback();
+	}, 1500);
+}
+
+/**
+ * 失败提示
+ * @param {String} msg 提示消息
+ * @param {Function} callback 回调函数
+ */
+
+function errorToShow(msg = '操作失败', callback = function() {}) {
+	uni.showToast({
+		title: msg,
+		icon: 'none',
+		duration: 2000,
+	});
+	setTimeout(function() {
+		callback();
+	}, 2000);
+}
+
+/**
+ * 加载显示
+ * @param {String} msg 提示消息
+ */
+function loadToShow(msg = '加载中', icon = 'loading') {
+	uni.showToast({
+		title: msg,
+		icon: icon,
+	});
+}
+
+/**
+ * 加载隐藏
+ */
+
+function loadToHide() {
+	uni.hideToast();
+}
+
+/**
+ * 提示框
+ * @param {String} title 提示标题
+ * @param {String} content 提示内容
+ * @param {Function} callback 回调函数
+ * @param {Boolean} showCancel = [true|false] 显示关闭按钮
+ * @param {String} cancelText 关闭按钮文字 
+ * @param {String} confirmText 确定按钮文字 
+ * @example
+ * modelShow('提示','确认执行此操作吗?',()=>{},()=>{},true,'取消','确定')
+ */
+function modelShow(title = '提示', content = '确认执行此操作吗?', callback = () => {}, callback2 = () => {}, showCancel = true,
+	cancelText = '拒绝',
+	confirmText = '通过') {
+	uni.showModal({
+		title: title,
+		content: content,
+		showCancel: showCancel,
+		cancelText: cancelText,
+		confirmText: confirmText,
+		success: function(res) {
+			if (res.confirm) {
+				// 用户点击确定操作
+				setTimeout(() => {
+					callback()
+				}, 500)
+			} else if (res.cancel) {
+				// 用户取消操作
+				setTimeout(() => {
+					callback2()
+				}, 500)
+			}
+		}
+	});
+}
+
+
+
+/**
+ * 判断数组
+ * @param {Object} arr 数组
+ */
+function isArray(object) {
+	return object && typeof object === 'object'
+}
+
+/**
+ * 统一跳转
+ * @param {String} url 跳转链接
+ */
+function navigateTo(url) {
+	if (url == '')
+		return;
+	if (url.indexOf("/pages/index/index") >= 0 || url.indexOf("answer_pages/home/dashboard") >= 0 || url.indexOf(
+			"/pages/shouhu/shouhu") >= 0 || url.indexOf("/pages/feiyi/feiyi") >= 0 || url.indexOf(
+			"/pages/user/index") >= 0) {
+		uni.switchTab({
+			url: url,
+			animationType: 'pop-in',
+			animationDuration: 300
+		});
+	} else {
+		uni.navigateTo({
+			url: url,
+			animationType: 'pop-in',
+			animationDuration: 300
+		});
+	}
+
+}
+
+/**
+ * 关闭当前页面并跳转
+ * @param {String} url 跳转链接
+ */
+function redirectTo(url) {
+	uni.redirectTo({
+		url: url,
+		animationType: 'pop-in',
+		animationDuration: 300
+	})
+}
+/**
+ * 返回上一层的逻辑判断
+ * @param {num} delta 跳转上一层,或者几层
+ */
+function navigateBack(delta = 1) {
+	let pages = getCurrentPages(); //当前页
+	//console.log(pages);
+	//当有前一页的时候。
+	if (pages.length > 1) {
+		let page = pages[pages.length - 2]; //上个页面
+		// console.log(page.route);
+		if (page.route == "pages/index/index" || page.route == 'pages/index/homepage' || page.route ==
+			'pages/user/index' || page.route == 'pages/consult/index') {
+			uni.switchTab({
+				url: '/' + page.route
+			})
+		} else if (page.route == "pages/user/login") {
+			uni.switchTab({
+				url: '/pages/user/index'
+			})
+		} else if (page.route == "pages/user/register") {
+			uni.switchTab({
+				url: '/pages/user/user'
+			})
+		} else {
+			uni.navigateBack({
+				delta: delta
+			})
+		}
+	} else {
+		uni.switchTab({
+			url: '/pages/index/index'
+		})
+	}
+
+}
+
+/**
+ *  判断是否在微信浏览器
+ */
+function isWeiXinBrowser() {
+	// #ifdef H5
+	// window.navigator.userAgent属性包含了浏览器类型、版本、操作系统类型、浏览器引擎类型等信息,这个属性可以用来判断浏览器类型
+	let ua = window.navigator.userAgent.toLowerCase()
+	// 通过正则表达式匹配ua中是否含有MicroMessenger字符串
+	if (ua.match(/MicroMessenger/i) == 'micromessenger') {
+		return true
+	} else {
+		return false
+	}
+	// #endif
+
+	// #ifdef MP
+	return false;
+	// #endif
+}
+
+
+/**
+ * 加载cms列表
+ * @param {Array} data
+ * 
+ */
+
+function cmsGetList(data, callback = function() {}) {
+	api.cmsGetList(data, res => {
+		if (res.code) {
+			res.data.list.forEach(function(ele, index) {
+				ele.ctime = timeToDate(ele.createtime);
+				if (ele.image.substring(0, 9) == '/uploads/') {
+					ele.image = cndUrl + ele.image
+				}
+			});
+			callback(res.data)
+		} else {
+			errorToShow(res.msg)
+		}
+	})
+}
+
+
+/**
+ * 加载cms详情
+ * @param {Array} data
+ * 
+ */
+
+function cmsGetDetails(data, callback = function() {}) {
+	api.cmsGetDetails(data, res => {
+		//console.log(data)
+		if (res.code) {
+			res.data.content = htmlParser(res.data.content); //	设置资源cdn;
+			res.data.ctime = timeToDate(res.data.createtime);
+			if (res.data.image) {
+				if (res.data.image.substring(0, 9) == '/uploads/') {
+					res.data.image = cndUrl + res.data.image
+				}
+			}
+			callback(res.data)
+		} else {
+			modelShow(
+				'错误提示',
+				res.msg,
+				() => {
+					uni.navigateBack({})
+				},
+				false
+			);
+		}
+	})
+}
+/**
+ * 初始化页面
+ * @param {Function} callback 回调函数
+ * @param {String} route	页面路径/默认当前路径
+ */
+function initPages(callback = function() {}, route) {
+
+	if (!route) {
+		let pages = getCurrentPages();
+		let page = pages[pages.length - 1];
+		route = page.route
+	}
+	let init_data = db.get('init_' + route)
+
+	setTimeout(() => {
+		api.getInit({
+			route: route
+		}, res => {
+			// console.log(res);
+			if (res.code) {
+
+				res.data.slide.forEach(function(ele, index) {
+					if (ele.image.substring(0, 9) == '/uploads/') {
+						ele.image = cndUrl + ele.image
+					}
+				});
+				res.data.content.forEach(function(ele, index) {
+					ele.content = ele.content.replace(new RegExp(`style="width: 100%;`, 'g'),
+						'style="width: 100%;margin-top: -3px;') //	无缝连接图片;
+					ele.content = ele.content.replace(new RegExp(`src="/uploads`, 'g'),
+						'src="' + cndUrl + '/uploads')
+					ele.content = htmlParser(ele.content); //	设置资源cdn;
+				});
+				db.set('init_' + route, res.data)
+				callback(res.data)
+			}
+		});
+	}, 1000);
+	if (init_data) {
+		callback(init_data)
+	} else {
+		// loadToShow('初始化页面...');
+	}
+}
+
+/**
+ * 跳转链接
+ * @param {String} url 跳转链接
+ */
+function toUrl(url) {
+	if (url) {
+
+		var objExp = new RegExp(/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/);
+		if (objExp.test(url) != true) {
+			// #ifdef APP-PLUS
+			url = baseUrl + url
+			// #endif
+			// #ifdef H5
+			url = baseUrl + url
+			// #endif
+		}
+		//console.log(url)
+		//return false
+		// #ifdef MP
+		uni.navigateTo({
+			url: url
+		})
+		// #endif
+
+		// #ifdef APP-PLUS
+		plus.runtime.openURL(url);
+		// #endif
+
+		// #ifdef H5
+		window.open(url);
+		// #endif
+
+	}
+}
+
+
+/**
+ * 保存登陆状态
+ * @param {Array} data 用户数据
+ */
+function saveLogin(data) {
+	db.set('auth', data.auth)
+
+	if (data.user.avatar.substring(0, 9) == '/uploads/') {
+		data.user.avatar = cndUrl + data.user.avatar
+	}
+	db.set('user', data.user)
+}
+
+
+/**
+ * 刷新用户
+ * @param {Function} callback 回调函数(用户数据)
+ * @example 
+ * refreshUser((user)=>{_this.user = user})
+ */
+function refreshUser(callback = function() {}) {
+	let user = db.get('user');
+	if (user.id) {
+		api.refreshUser({}, res => {
+			if (res.code == 1) {
+				saveLogin(res.data)
+				callback(res.data)
+			} else {
+				db.del('user');
+				toLogin()
+			}
+		})
+	} else {
+		db.del('user');
+		db.del('auth');
+		toLogin()
+	}
+}
+
+
+
+/**
+ * 清理用户
+ * @param {String} page 清理后跳转页面
+ */
+function cleanUser(page) {
+	db.del('user')
+	db.del('auth')
+	if (page) {
+		redirectTo(page)
+	}
+}
+
+
+
+
+/**
+ * 字符串校验
+ * @param {String} str 字符串
+ * @param {String} model = [number|mobile|name|idcard|] 模式
+ * @example 
+ * testString('17080057443','mobile')
+ * testString('17080057443','mobile')
+ */
+
+function testString(str, model = null) {
+	if (typeof(model) == 'number') {
+		if (str.length >= model) {
+			return true
+		}
+	} else {
+		switch (model) {
+			case null:
+				return false
+				break
+			case 'idcard':
+				return RegExp(/^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/)
+					.test(str)
+				break
+			case 'mobile':
+				return RegExp(/^1[0-9]{10}$/).test(str)
+				break
+			case 'name':
+				return RegExp(/^[\u4E00-\u9FA5\uf900-\ufa2d·s]{2,20}$/).test(str)
+				break
+			default:
+				return false
+				break
+		}
+	}
+	return false
+}
+
+
+
+
+/**
+ * 时间戳转时差
+ * @param {String} date 时间戳
+ */
+
+function timeToDate(time) {
+	time = time * 1000
+	var interval = new Date().getTime() - time;
+	//计算出相差天数
+	var returnTime = "";
+	var days = Math.floor(interval / (24 * 3600 * 1000))
+	if (days == 0) {
+		//计算出小时数
+		var leaveTime = interval % (24 * 3600 * 1000) //计算天数后剩余的毫秒数
+		var hours = Math.floor(leaveTime / (3600 * 1000))
+		if (hours == 0) {
+			//计算相差分钟数
+			leaveTime = leaveTime % (3600 * 1000) //计算小时数后剩余的毫秒数
+			var minutes = Math.floor(leaveTime / (60 * 1000))
+			if (minutes == 0) {
+				//计算相差秒数
+				leaveTime = leaveTime % (60 * 1000) //计算分钟数后剩余的毫秒数
+				var seconds = Math.round(leaveTime / 1000)
+				return seconds + "秒前";
+			}
+			return minutes + "分钟前";
+		}
+		return hours + "小时前";
+	}
+	return days + "天前";
+}
+
+
+
+/**
+ * 基本信息
+ */
+function baseInfo() {
+	return {
+		bgClass: bgClass,
+		title: title,
+		baseLogo: baseLogo,
+	}
+}
+//校验邮箱格式
+function checkEmail(email) {
+	return RegExp(/^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/).test(
+		email);
+}
+//校验手机格式
+function checkMobile(mobile) {
+	return RegExp(/^1[0-9]{10}$/).test(mobile);
+}
+/**
+ * 用户信息
+ */
+function userInfo() {
+	let user = db.get('user')
+	if (user) {
+		return user
+	} else {
+		return false;
+	}
+
+	// return {
+	// 	bgClass: bgClass,
+	// 	title: title,
+	// 	baseLogo: baseLogo,
+	// }
+}
+
+
+/**
+ * 上传图片
+ * @param {Array} data 附带数据
+ * @param {Function} callback 回调函数
+ * @param {int} num 限制数量
+ * @param {String} type 类型
+ * @return {String} url 
+ */
+function uploadImage(data = {}, callback = function() {}, num = 1, type) {
+	api.uploadImage(
+		'common/upload', data, (res) => {
+			if (res.code) {
+				if (res.data.url.substring(0, 9) == '/uploads/') {
+					res.data.url = cndUrl + res.data.url
+				}
+				callback(res.data.url)
+			} else {
+				errorToShow(res.msg)
+			}
+		}, type)
+
+}
+
+function formatRichText(html) {
+	let newContent = html.replace(/<img[^>]*>/gi, function(match, capture) {
+		match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
+		match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
+		match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
+		return match;
+	});
+	newContent = newContent.replace(/style="[^"]+"/gi, function(match, capture) {
+		match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
+		return match;
+	});
+	newContent = newContent.replace(/<br[^>]*\/>/gi, '');
+	newContent = newContent.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:block;margin:10px 0;"');
+	return newContent;
+}
+
+
+export {
+	toLogin,
+	isLogin,
+	normalToShow,
+	successToShow,
+	errorToShow,
+	isArray,
+	loadToShow,
+	loadToHide,
+	navigateTo,
+	navigateBack,
+	redirectTo,
+	modelShow,
+	isWeiXinBrowser,
+	initPages,
+	toUrl,
+	saveLogin,
+	refreshUser,
+	cleanUser,
+	testString,
+	timeToDate,
+	cmsGetList,
+	cmsGetDetails,
+	baseInfo,
+	userInfo,
+	uploadImage,
+	checkEmail,
+	checkMobile,
+	formatRichText
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 19 - 0
config/config.js


+ 83 - 0
config/db.js

@@ -0,0 +1,83 @@
+import * as common from './common.js' //引入common
+
+//取值
+function get(key,sync = true) {
+    try {
+		if(sync){
+			return uni.getStorageSync(key);
+		}else{
+			let data = '';
+			uni.getStorage({
+				key:key,
+				success: function (res) {
+					data = res.data;
+				}
+			});
+			return data;
+		}
+    } catch (e) {
+        return false;
+    }
+}
+
+//赋值
+function set(key, value, sync = true) {
+    try {
+        if (sync) {
+            return uni.setStorageSync(key, value);
+        } else {
+            uni.setStorage({
+                key: key,
+                data: value
+            });
+        }
+    } catch (e) {
+
+    }
+}
+
+//移除
+function del(key, sync = true){
+    try {
+        if (sync) {
+            return uni.removeStorageSync(key);
+        } else {
+            uni.removeStorage({
+                key: key
+            });
+        }
+    } catch (e) {
+        return false;
+    }
+}
+
+//清空
+function clear(sync = true){
+    try {
+        if (sync) {
+            return uni.clearStorageSync();
+        } else {
+            uni.clearStorage();
+        }
+    } catch (e) {
+        return false;
+    }
+}
+
+//获取用户token,如果缓存有,直接返回,如果没有,就先微信登陆,然后服务器登陆,最后返回token
+function userToken(callback) {
+    var token = get('userToken');
+    if (token){
+        callback(token);
+    }else{
+        //如果没有登陆,就去登陆
+        common.toLogin();
+    }
+}
+export {
+    get,
+    set,
+    del,
+    clear,
+    userToken
+}

+ 129 - 0
index_fenbao/cs_liebiao/cs_liebiao.vue

@@ -0,0 +1,129 @@
+<template>
+	<view class="body">
+		<u-navbar :autoBack="true" title="村史馆" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="fy_nav_bj">
+			<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/cs_lb.png"></image>
+		</view>
+		<view class="banxin">
+			<u-picker :show="show" @close="show = false" :closeOnClickOverlay="true" :columns="columns" @cancel="show = false" @confirm="yf_isok"></u-picker>
+			<view class="" style="margin-top: 40rpx">
+				<!-- 选择城市 -->
+				<view class="" style="display: flex">
+					<view @click="show = true" class="fy_cs">
+						<uni-icons type="location" size="20"></uni-icons>
+						<text style="margin: 0 10rpx 0 10rpx">{{ columnsItem }}</text>
+						<uni-icons type="bottom" size="20"></uni-icons>
+					</view>
+
+					<!-- 选择城市end -->
+
+					<view class="">
+						<u-tabs
+							:list="tabList"
+							:lineWidth="0"
+							:activeStyle="{
+								border: '1px solid #dac1a1',
+								color: '#dac1a1'
+							}"
+						></u-tabs>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- 村史馆列表 -->
+		<view class="banxin lb_box" style="">
+			<view class="a1" v-for="item in 10" :key="item">
+				<view class="a2">
+					<image src="https://huli-app.wenlvti.net/app_static/minnanhun/image/cs_item_lb.png" class="a3"></image>
+				</view>
+
+				<view class="a4">湖里社区</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			show: false,
+			columns: [['厦门', '泉州', '福州']],
+			columnsItem: '厦门' /* 选中的城市 */,
+			tabList: [
+				{
+					name: '湖里街道',
+					id: 0
+				},
+				{
+					name: '江头街道',
+					id: 1
+				},
+				{
+					name: '殿前街道',
+					id: 2
+				},
+
+				{
+					name: '江头街道',
+					id: 3
+				}
+			]
+		};
+	},
+	methods: {
+		// 选择城市
+		yf_isok(e) {
+			console.log(e);
+			this.columnsItem = e.value;
+			this.show = false;
+		}
+	}
+};
+</script>
+
+<style>
+.lb_box {
+	display: flex;
+	flex-flow: wrap;
+	justify-content: space-between;
+	margin-top: 20rpx;
+}
+.a1 {
+	margin-bottom: 20rpx;
+}
+.a2 {
+	background-image: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/cs_bjx.png');
+	background-size: 100% 100%;
+	width: 200rpx; /* 六边形容器的宽度 */
+	height: 210rpx; /* 六边形容器的高度 */
+	position: relative;
+	clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
+	border: 3px solid #f6cf91;
+}
+.a3 {
+	width: 100%; /* 图片宽度设置为容器宽度 */
+	height: 100%; /* 图片高度设置为容器高度 */
+	object-fit: cover;
+}
+.a4 {
+	text-align: center;
+	margin-top: 10rpx;
+}
+.banxin {
+	margin: 0 32rpx 0 32rpx;
+}
+.fy_nav_bj {
+	width: 100%;
+	height: 220rpx;
+	color: #ffffff;
+	margin-bottom: 25rpx;
+}
+.fy_cs {
+	display: flex;
+	align-items: center;
+	width: 255rpx;
+	height: 50rpx;
+	margin-top: 20rpx;
+}
+</style>

+ 215 - 0
index_fenbao/feiyi/feiyi.vue

@@ -0,0 +1,215 @@
+<template>
+	<view class="body2">
+		<u-navbar :autoBack="true" title="闽南非遗" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="fy_nav_bj">
+			<view class="" style="padding: 80rpx 0rpx 0 50rpx">
+				<view style="font-size: 36rpx; margin-bottom: 20rpx">闽南非遗</view>
+				<view style="font-size: 24rpx">推进制度化建设,打造非遗活态传承新机制</view>
+			</view>
+		</view>
+		<!-- 轮播图 -->
+		<view class="banxin">
+			<u-swiper
+				indicatorMode="dot"
+				indicatorStyle="bottom: 10rpx"
+				:list="list1"
+				height="180rpx"
+				:indicator="true"
+				:autoplay="true"
+				:circular="true"
+				keyName="image"
+			></u-swiper>
+		</view>
+		<u-picker :show="show" @close="show = false" :closeOnClickOverlay="true" :columns="columns" @cancel="show = false" @confirm="yf_isok"></u-picker>
+		<view class="banxin" style="margin-top: 40rpx">
+			<!-- 选择城市 -->
+			<view class="" style="display: flex">
+				<view @click="show = true" class="fy_cs">
+					<uni-icons type="location" size="20"></uni-icons>
+					<text style="margin: 0 10rpx 0 10rpx">{{ columnsItem }}</text>
+					<uni-icons type="bottom" size="20"></uni-icons>
+				</view>
+
+				<!-- 选择城市end -->
+
+				<view class="">
+					<u-tabs
+						:list="tabList"
+						:lineWidth="0"
+						:activeStyle="{
+							border: '1px solid #dac1a1',
+							color: '#dac1a1'
+						}"
+					></u-tabs>
+				</view>
+			</view>
+			<!-- 滑动模式 -->
+			<!-- <view class="" style="margin-left: 200rpx">
+				<scroll-view scroll-x style="display: flex; white-space: nowrap" class="">
+					<view @click="fyTab(item)" v-for="item in tabList" :key="item.id" class="fy_tab_item" :class="{ active: tabactive == item.id }">
+						{{ item.name }}
+					</view>
+				</scroll-view>
+			</view> -->
+		</view>
+		<!-- 内容 -->
+		<view class="sh_xs banxin">
+			<view class="sh_xs_item" v-for="item in twList" :key="item">
+				<view class="" style="width: 325rpx; height: 180rpx; border-radius: 10rpx">
+					<image style="width: 100%; height: 100%" :src="item.img"></image>
+				</view>
+				<view class="">{{ item.title }}</view>
+				<view class="ms_dianzan">
+					<view class="">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+
+					<view class="">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			show: false,
+			columns: [['厦门', '泉州', '福州']],
+			columnsItem: '厦门' /* 选中的城市 */,
+			tabactive: 0,
+			list1: [
+				{
+					image: 'https://feicheng.16fw.cn:1443/uploads/20230403/f394190a0e3fc5873644beadead1cc3f.jpg'
+				},
+				{
+					image: 'https://feicheng.16fw.cn:1443/uploads/20230403/00885f0245196beebe66ca79aebe5656.jpg'
+				},
+				{
+					image: 'https://feicheng.16fw.cn:1443/uploads/20230403/1cf5f3c9c6b28fcbd3a983068f06d257.jpg'
+				}
+			],
+			tabList: [
+				{
+					name: '民俗文学',
+					id: 0
+				},
+				{
+					name: '江头街道',
+					id: 1
+				},
+				{
+					name: '殿前街道',
+					id: 2
+				},
+				{
+					name: '民俗文学',
+					id: 3
+				},
+				{
+					name: '江头街道',
+					id: 4
+				}
+			],
+			twList: [
+				{
+					img: 'https://feicheng.16fw.cn:1443/uploads/20230403/133f120ee8e260640890dc2a7fe97c1f.png',
+					title: '闽南传统金银制作技艺'
+				},
+				{
+					img: 'https://feicheng.16fw.cn:1443/uploads/20230524/fe15cad25eaa4cf09236b70235fc1f14.png',
+					title: '开厦上柱国祠陈氏祭祖习俗'
+				},
+				{
+					img: 'https://feicheng.16fw.cn:1443/uploads/20230403/1cf5f3c9c6b28fcbd3a983068f06d257.jpg',
+					title: '沈氏漆线雕'
+				},
+
+				{
+					img: 'https://feicheng.16fw.cn:1443/uploads/20230524/6eefa546579b4bee7b1609cce87ba79f.png',
+					title: '闽台送王船习俗'
+				}
+			]
+		};
+	},
+	methods: {
+		fyTab(item) {
+			this.tabactive = item.id;
+			console.log(item);
+		},
+		// 选择城市
+		yf_isok(e) {
+			console.log(e);
+			this.columnsItem = e.value;
+			this.show = false;
+		}
+	}
+};
+</script>
+
+<style>
+.body2 {
+	background-size: 100% 100%;
+	background-attachment: fixed;
+	background-repeat: repeat-y;
+	background-color: #efefef;
+	padding-bottom: 50rpx;
+	background-color: #efefef;
+}
+.banxin {
+	margin: 0 32rpx 0 32rpx;
+}
+/deep/.u-swiper-indicator__wrapper__dot--active {
+	width: 5px !important;
+}
+.fy_nav_bj {
+	width: 100%;
+	height: 220rpx;
+	color: #ffffff;
+	margin-bottom: 25rpx;
+	background-image: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/fy_navbj.png');
+	background-size: 100% 100%;
+}
+.active {
+	border: 1px solid #dac1a1;
+}
+.fy_tab_item {
+	line-height: 45rpx;
+	text-align: center;
+	margin-right: 30rpx;
+	width: 170rpx;
+	height: 50rpx;
+	display: inline-block;
+	background-color: #fffcf3;
+}
+.sh_xs {
+	margin-top: 50rpx;
+	display: flex;
+	flex-flow: wrap;
+	justify-content: space-between;
+}
+.ms_dianzan {
+	width: 245rpx;
+	display: flex;
+	justify-content: space-between;
+	margin-top: 10rpx;
+}
+.sh_xs_item {
+	border-radius: 10rpx;
+	background: #ffffff;
+	margin-bottom: 35rpx;
+}
+.fy_cs {
+	display: flex;
+	align-items: center;
+	width: 255rpx;
+	height: 50rpx;
+	margin-top: 20rpx;
+	/* background-color: antiquewhite; */
+}
+</style>

+ 124 - 0
index_fenbao/jianzhu/jianzhu.vue

@@ -0,0 +1,124 @@
+<template>
+	<view class="body2">
+		<u-navbar :autoBack="true" title="建筑文化" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="jz_swiper">
+			<u-swiper
+				:list="list1"
+				height="335rpx"
+				:indicator="true"
+				:autoplay="true"
+				indicatorMode="dot"
+				indicatorActiveColor="#fff"
+				indicatorInactiveColor="rgba(255, 255, 255, 0.35)"
+				:circular="true"
+				indicatorStyle="bottom: 10px"
+			></u-swiper>
+		</view>
+		<view class="" style="margin: 30rpx 0 0 0">
+			<u-tabs
+				:duration="200"
+				:list="listTab"
+				:lineWidth="25"
+				:lineHeight="12"
+				lineColor="#4E7198"
+				:lineColor="`url(${tabImg}) 100% 100%`"
+				:activeStyle="{
+					color: '#4E7198',
+					fontSize: '34rpx'
+				}"
+			></u-tabs>
+		</view>
+		<view class="banxin">
+			<view style="margin-bottom: 30rpx" v-for="item in jianZhuList" :key="item">
+				<view class="jz_item">
+					<image style="width: 100%; height: 100%" :src="item.img"></image>
+				</view>
+				<view class="" style="display: flex; justify-content: space-between">
+					<text>{{ item.title }}</text>
+					<uni-icons style="margin-top: 5rpx" type="heart" size="20"></uni-icons>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			tabImg: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/tab.png',
+			list1: [
+				'https://img1.baidu.com/it/u=3551075903,1493549593&fm=253&fmt=auto&app=138&f=JPEG?w=667&h=500',
+				'https://img0.baidu.com/it/u=1667631211,245764236&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=357',
+				'https://img1.baidu.com/it/u=2554021422,1871009309&fm=253&fmt=auto&app=138&f=JPEG?w=700&h=500'
+			],
+			listTab: [
+				{
+					name: '全部',
+					tabid: 1
+				},
+				{
+					name: '民居大厝',
+					tabid: 2
+				},
+				{
+					name: '宫殿建筑',
+					tabid: 3
+				},
+				{
+					name: '礼制性祭祀建筑',
+					tabid: 4
+				},
+				{
+					name: '百家争鸣',
+					tabid: 5
+				}
+			],
+			jianZhuList: [
+				{
+					img: 'https://img2.baidu.com/it/u=1282947730,847518852&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=390',
+
+					title: '中国传统建筑文化——闽南地区的屋顶文化古建中国'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=3045646735,3994404954&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=304',
+					title: '雕梁画栋的闽南建筑,一砖一瓦都体现着古人对美的追求'
+				}
+			]
+		};
+	},
+	methods: {}
+};
+</script>
+
+<style>
+.body2 {
+	background-size: 100% 100%;
+	background-attachment: fixed;
+	background-repeat: repeat-y;
+	background-color: #efefef;
+	padding-bottom: 50rpx;
+}
+/deep/.u-swiper-indicator__wrapper__dot--active {
+	width: 5px !important;
+}
+/deep/.u-tabs__wrapper__nav__item.data-v-48634e29 {
+	padding: 0 40rpx !important;
+}
+/deep/.u-tabs__wrapper__nav__line.data-v-48634e29 {
+	bottom: 16rpx !important;
+}
+/deep/.u-tabs__wrapper__nav__item.data-v-48634e29 {
+	align-items: end !important;
+}
+.banxin {
+	margin: 0 32rpx 0 32rpx;
+}
+.jz_swiper {
+}
+.jz_item {
+	width: 686rpx;
+	height: 345rpx;
+	border-radius: 26rpx 26rpx 0rpx 0rpx;
+}
+</style>

+ 216 - 0
index_fenbao/minNanyu/minNanyu.vue

@@ -0,0 +1,216 @@
+<template>
+	<view class="body2">
+		<u-navbar :autoBack="true" title="闽南语" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="jz_swiper">
+			<u-swiper
+				:list="list1"
+				indicatorStyle="bottom: 10rpx"
+				indicatorMode="dot"
+				height="335rpx"
+				:indicator="true"
+				:autoplay="true"
+				:circular="true"
+				keyName="image"
+			></u-swiper>
+		</view>
+		<!--闽南语歌曲 -->
+		<view class="text-wrapper_7">
+			<text lines="1" class="text_4">闽南语歌曲</text>
+			<text lines="1" class="text_5" @click="yinPinLieBiao">查看更多》</text>
+		</view>
+		<view class="banxin">
+			<view class="content">
+				<!-- 下列代码未加规范,仅供参考,请勿模仿 -->
+				<scroll-view scroll-x style="display: flex; white-space: nowrap">
+					<view class="mn_container" v-for="item in mnGeQu" :key="item">
+						<view class="mn_box">
+							<image style="border-radius: 10rpx 10rpx 10rpx 0rpx; width: 100%; height: 100%" :src="item.img"></image>
+						</view>
+						<text class="mn_text">{{ item.titie }}</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
+		<!--闽南语歌曲end -->
+		<!-- 戏曲 -->
+		<view class="text-wrapper_7">
+			<text lines="1" class="text_4">戏曲</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<view class="banxin">
+			<view class="content">
+				<!-- 下列代码未加规范,仅供参考,请勿模仿 -->
+				<scroll-view scroll-x style="display: flex; white-space: nowrap">
+					<view class="mn_container" v-for="item in mnXiQu" :key="item">
+						<view class="mn_box">
+							<image :src="item.img" style="border-radius: 10rpx 10rpx 10rpx 0rpx; width: 100%; height: 100%"></image>
+						</view>
+						<text class="mn_text">{{ item.titie }}</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
+		<!-- 戏曲end -->
+		<!-- 俗语谚语歇后语 -->
+		<!-- <view class="text-wrapper_7">
+			<text lines="1" class="text_4">俗语谚语歇后语</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<view class="banxin">
+			<view class="content">
+			
+				<scroll-view scroll-x style="display: flex; white-space: nowrap">
+					<view class="mn_container" v-for="item in 6" :key="item">
+						<view class="mn_box">
+							<image src="/static/image/kctp.png" style="border-radius: 10rpx 10rpx 10rpx 0rpx; width: 100%; height: 100%"></image>
+						</view>
+						<text class="mn_text">浪子回头金不换</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view> -->
+		<!-- 俗语谚语歇后语end -->
+		<!--趣谈  -->
+		<!-- <view class="text-wrapper_7">
+			<text lines="1" class="text_4">趣谈</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<view class="banxin">
+			<view class="content">
+			
+				<scroll-view scroll-x style="display: flex; white-space: nowrap">
+					<view class="mn_container" v-for="item in 6">
+						<view class="mn_box">
+							<image src="/static/image/kctp.png" style="border-radius: 10rpx 10rpx 10rpx 0rpx; width: 100%; height: 100%"></image>
+						</view>
+						<text class="mn_text">浪子回头金不换</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view> -->
+		<!-- 趣谈 -->
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			list1: [
+				{
+					image: 'https://speech.xmu.edu.cn/_upload/article/images/c0/fa/3ff524314ed9992200a0db99bb7b/824d7b82-5e07-4857-9c35-5d1219bc710f.jpg',
+					title: '昨夜星辰昨夜风,画楼西畔桂堂东'
+				},
+				{
+					image: 'https://img0.baidu.com/it/u=1455151824,1249683265&fm=253&fmt=auto&app=138&f=JPEG?w=667&h=500',
+					title: '身无彩凤双飞翼,心有灵犀一点通'
+				},
+				{
+					image: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fci.xiaohongshu.com%2F20292d28-c439-2758-a2a7-c954170fde70%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fci.xiaohongshu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1697881437&t=db418f32a3826bfaf554feb7ae6f4ba8',
+					title: '谁念西风独自凉,萧萧黄叶闭疏窗,沉思往事立残阳'
+				}
+			],
+			// 闽南歌曲
+			mnGeQu: [
+				{
+					img: 'http://t14.baidu.com/it/u=2294107695,3570586599&fm=224&app=112&f=JPEG?w=500&h=500',
+					titie: '闽南经典歌曲'
+				},
+				{
+					img: 'http://t14.baidu.com/it/u=561204940,3527801245&fm=224&app=112&f=JPEG?w=500&h=500',
+					titie: '闽南30年经典老歌'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=1473724061,3866170653&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
+					titie: '闽南情'
+				}
+			],
+			mnXiQu: [
+				{
+					img: 'https://img.pconline.com.cn/images/upload/upc/tx/photoblog/1411/12/c1/40851785_40851785_1415781337347.jpg',
+					titie: '闽剧王莲莲拜香'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=1657718455,2908945415&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500',
+					titie: '赏闽剧《北进图'
+				},
+				{
+					img: 'https://img.pconline.com.cn/images/upload/upc/tx/photoblog/1301/11/c2/17299755_17299755_1357871971161.jpg',
+					titie: '高甲戏(闽南传统民间戏剧)'
+				}
+			]
+		};
+	},
+	methods: {
+		yinPinLieBiao() {
+			uni.navigateTo({
+				url: '/index_fenbao/minNanyu/yinPinLieBiao'
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.body2 {
+	background-size: 100% 100%;
+	background-attachment: fixed;
+	background-repeat: repeat-y;
+	background-color: #efefef;
+	padding-bottom: 60rpx;
+}
+/deep/.u-swiper-indicator__wrapper__dot--active {
+	width: 5px !important;
+}
+/* 去除轮播图标题遮罩背景色 */
+.u-swiper__wrapper__item__wrapper__title {
+	background-color: transparent !important;
+}
+.banxin {
+	margin: 0 32rpx 0 32rpx;
+}
+.text-wrapper_7 {
+	width: 651rpx;
+	height: 45rpx;
+	flex-direction: row;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	margin: 33rpx 0 25rpx 48rpx;
+}
+.text_4 {
+	width: 112rpx;
+	height: 27rpx;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text_5 {
+	width: 89rpx;
+	height: 20rpx;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 3rpx;
+}
+.mn_container {
+	display: inline-block;
+	margin-right: 20rpx;
+	text-align: center;
+}
+
+.mn_box {
+	width: 261rpx;
+	height: 349rpx;
+	background: #ca5642;
+	border-radius: 10rpx 10rpx 10rpx 0rpx;
+}
+
+.mn_text {
+	font-size: 28rpx;
+	color: #333;
+}
+</style>

+ 197 - 0
index_fenbao/minNanyu/yinPinLieBiao.vue

@@ -0,0 +1,197 @@
+<template>
+	<view class="box">
+		<u-navbar :autoBack="true" title="音频列表" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="box_search">
+			<u-search v-model="val" bgColor="#ffffff" :showAction="false"></u-search>
+		</view>
+		<view class="box_tab">
+			<u-tabs
+				:duration="200"
+				:list="listTab"
+				:lineWidth="25"
+				:lineHeight="12"
+				lineColor="#4E7198"
+				:lineColor="`url(${tabImg}) 100% 100%`"
+				:activeStyle="{
+					color: '#4E7198',
+					fontSize: '34rpx'
+				}"
+			></u-tabs>
+		</view>
+		<!-- 音乐 -->
+		<view class="list-items_1-0" v-for="item in 3">
+			<view class="group_2-0">
+				<view class="image-wrapper_1-0">
+					<image src="/static/image/sz.png"></image>
+					<view class="box_str">
+						<image style="width: 100%; height: 100%" src="/static/image/star.png"></image>
+					</view>
+				</view>
+			</view>
+			<view class="box_4-0">
+				<view class="text_1-0">南音-御前清音</view>
+				<view class="group_12-0">
+					<view class="image-text_14-0">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+					<view class="image-text_15-0">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			val: '',
+			tabImg: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/tab.png',
+			listTab: [
+				{
+					name: '经典歌曲',
+					tabid: 1
+				},
+				{
+					name: '热门歌曲',
+					tabid: 2
+				},
+				{
+					name: '流行歌曲',
+					tabid: 3
+				},
+				{
+					name: '80后音乐',
+					tabid: 4
+				}
+			]
+		};
+	},
+	methods: {}
+};
+</script>
+
+<style>
+.box {
+	height: auto;
+	width: 100%;
+	background-color: #f8f8f8;
+	background-attachment: fixed;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+/deep/.u-tabs__wrapper__nav__item.data-v-48634e29 {
+	padding: 0 40rpx !important;
+}
+/deep/.u-tabs__wrapper__nav__line.data-v-48634e29 {
+	bottom: 16rpx !important;
+}
+/deep/.u-tabs__wrapper__nav__item.data-v-48634e29 {
+	align-items: end !important;
+}
+/deep/.column-value.data-v-ddfcbb1c {
+	border-radius: 25rpx 60rpx 0rpx 30rpx !important;
+}
+.box_search {
+	z-index: 1;
+	margin: 20rpx 32rpx 0 32rpx;
+}
+.box_tab {
+	margin: 45rpx 32rpx 0 32rpx;
+}
+.list-items_1-0 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 686rpx;
+	height: 174rpx;
+	margin: 20rpx 32rpx 10rpx 32rpx;
+	padding: 0 20rpx;
+	flex-direction: row;
+	display: flex;
+}
+.image-wrapper_1-0 {
+	position: relative;
+	background-color: rgba(0, 0, 0, 0.15);
+	border-radius: NaNrpx;
+	height: 174rpx;
+	display: flex;
+	flex-direction: column;
+	width: 131rpx;
+}
+
+.box_4-0 {
+	width: 210rpx;
+	height: 100rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 34rpx 0 0 27rpx;
+}
+.text_1-0 {
+	height: 26rpx;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	line-height: 28rpx;
+}
+.group_12-0 {
+	width: 210rpx;
+	height: 32rpx;
+	margin-top: 42rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+}
+.image-text_14-0 {
+	width: 90rpx;
+	height: 32rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+}
+
+.text-group_2-0 {
+	width: 50rpx;
+	height: 19rpx;
+	color: rgba(49, 37, 32, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 6rpx;
+}
+.image-text_15-0 {
+	width: 90rpx;
+	height: 32rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+}
+
+.text-group_3-0 {
+	width: 50rpx;
+	height: 19rpx;
+	color: rgba(49, 37, 32, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 6rpx;
+}
+.text_2-0 {
+	width: 44rpx;
+	height: 18rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin: 38rpx 21rpx 0 253rpx;
+}
+.box_str {
+	position: absolute;
+	top: 40rpx;
+	left: 25rpx;
+	width: 80rpx;
+	height: 80rpx;
+}
+</style>

+ 213 - 0
index_fenbao/minsu/minsu.vue

@@ -0,0 +1,213 @@
+<template>
+	<view class="body" style="background-color: #efefef">
+		<u-navbar :autoBack="true" title="民俗宗教" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view>
+			<u-swiper :list="list1" height="335rpx" :indicator="true" :autoplay="true" :circular="true" keyName="image" showTitle></u-swiper>
+		</view>
+		<view class="text-wrapper_7">
+			<text lines="1" class="text_4">生活习俗</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<!-- 生活习俗 -->
+		<view class="sh_xs banxin">
+			<view class="sh_xs_item" v-for="item in shXiShuList" :key="item">
+				<view @click="detailsBtn" class="" style="width: 325rpx; height: 180rpx; border-radius: 10rpx">
+					<image style="width: 100%; height: 100%" :src="item.img"></image>
+				</view>
+				<view class="">{{ item.title }}</view>
+				<view class="ms_dianzan">
+					<view class="">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+
+					<view class="">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- 生活习俗end -->
+		<!-- 行业习俗 -->
+		<!-- 		<view class="text-wrapper_7">
+			<text lines="1" class="text_4">行业习俗</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<view class="sh_xs banxin">
+			<view class="sh_xs_item" v-for="item in 4" :key="item">
+				<view class="" style="width: 325rpx; height: 180rpx; border-radius: 10rpx">
+					<image style="width: 100%; height: 100%" src="https://img0.baidu.com/it/u=2448527499,3053317408&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=394"></image>
+				</view>
+				<view class="">閩南自古有廟就有</view>
+				<view class="ms_dianzan">
+					<view class="">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+
+					<view class="">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+				</view>
+			</view>
+		</view> -->
+		<!-- 行业习俗end -->
+		<!-- 岁时习俗 -->
+		<!-- 	<view class="text-wrapper_7">
+			<text lines="1" class="text_4">岁时习俗</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<view class="sh_xs banxin">
+			<view class="sh_xs_item" v-for="item in 4" :key="item">
+				<view class="" style="width: 325rpx; height: 180rpx; border-radius: 10rpx">
+					<image style="width: 100%; height: 100%" src="https://img1.baidu.com/it/u=2977394516,3415116795&fm=253&fmt=auto&app=138&f=JPEG?w=641&h=361"></image>
+				</view>
+				<view class="">閩南自古有廟就有</view>
+				<view class="ms_dianzan">
+					<view class="">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+
+					<view class="">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+				</view>
+			</view>
+		</view> -->
+		<!-- 岁时习俗end -->
+		<!-- 礼仪习俗 -->
+		<!-- <view class="text-wrapper_7">
+			<text lines="1" class="text_4">礼仪习俗</text>
+			<text lines="1" class="text_5">查看更多》</text>
+		</view>
+		<view class="sh_xs banxin">
+			<view class="sh_xs_item" v-for="item in 4" :key="item">
+				<view class="" style="width: 325rpx; height: 180rpx; border-radius: 10rpx">
+					<image style="width: 100%; height: 100%" src="https://img0.baidu.com/it/u=2448527499,3053317408&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=394"></image>
+				</view>
+				<view class="">閩南自古有廟就有</view>
+				<view class="ms_dianzan">
+					<view class="">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+
+					<view class="">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+				</view>
+			</view>
+		</view> -->
+		<!-- 礼仪习俗end -->
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			list1: [
+				{
+					image: 'https://img0.baidu.com/it/u=1541281845,960690765&fm=253&fmt=auto&app=138&f=JPEG?w=758&h=500',
+					title: '山里乡民祭妈祖'
+				},
+				{
+					image: 'https://img1.baidu.com/it/u=4153166350,2319982730&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=424',
+					title: '初九拜天公'
+				},
+				{
+					image: 'https://img1.baidu.com/it/u=3003350307,572069045&fm=253&fmt=auto&app=138&f=JPEG?w=751&h=500',
+					title: '福建茶乡古礼祭茶神'
+				}
+			],
+			// 生活习俗
+			shXiShuList: [
+				{
+					img: 'https://www.chinanews.com/tp/hd2011/2013/03-11/U508P4T426D182733F16470DT20130311112416.jpg',
+					title: '闽南民俗浔浦天香日'
+				},
+				{
+					img: 'https://inews.gtimg.com/newsapp_bt/0/11032609926/1000',
+					title: '闽南冬至丸'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=1711973128,1321603179&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=333',
+					title: '闽南习俗拜天公'
+				},
+				{
+					img: 'https://i2.hdslb.com/bfs/archive/24ab948019ae5cc13055113cfcd5321f7c16dc41.jpg',
+					title: '抬神'
+				}
+			]
+		};
+	},
+	methods: {
+		detailsBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/minsu/ms_wenZhang'
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.banxin {
+	margin: 0 32rpx 0 32rpx;
+}
+/deep/.u-swiper-indicator__wrapper__dot--active {
+	width: 5px !important;
+}
+/* 去除轮播图标题遮罩背景色 */
+/* .u-swiper__wrapper__item__wrapper__title {
+	background-color: transparent !important;
+} */
+.sh_xs {
+	display: flex;
+	flex-flow: wrap;
+	justify-content: space-between;
+}
+.ms_dianzan {
+	width: 245rpx;
+	display: flex;
+	justify-content: space-between;
+	margin-top: 10rpx;
+}
+.sh_xs_item {
+	border-radius: 10rpx;
+	background: #ffffff;
+	margin-bottom: 35rpx;
+}
+.text-wrapper_7 {
+	width: 651rpx;
+	height: 45rpx;
+	flex-direction: row;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	margin: 33rpx 0 25rpx 48rpx;
+}
+.text_4 {
+	width: 112rpx;
+	height: 27rpx;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text_5 {
+	width: 89rpx;
+	height: 20rpx;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 3rpx;
+}
+</style>

+ 264 - 0
index_fenbao/minsu/ms_wenZhang.vue

@@ -0,0 +1,264 @@
+<template>
+	<view>
+		<u-navbar :autoBack="true" title="民俗宗教" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="text-group_17">
+			<text lines="1" class="text_2">闽南人,拜拜成风,佛教、道教自然不缺,民间信仰才是主流。</text>
+			<text lines="1" decode="true" class="text_13">2023.09.01&nbsp;12:00:10</text>
+		</view>
+		<view class="block_3">
+			<view class="text_3">
+				<text class="text_10">
+					说到民间信仰,闽南可谓丰富多彩,以种类和数量论,闽南都可以称得上是全国各民系中的佼佼者,闽南人常将信仰活动称为“拜拜”,也就是祭拜、祭祀之意,而其拜拜的对象来源广泛,从中国历史上的真实人物、传说神灵到地方名士、乡野术士和生灵,无所不包。
+				</text>
+			</view>
+			<view class="box_3">
+				<image style="width: 100%; height: 100%" src="https://img0.baidu.com/it/u=1541281845,960690765&fm=253&fmt=auto&app=138&f=JPEG?w=758&h=500"></image>
+			</view>
+			<view class="text-wrapper_1">
+				<text class="paragraph_1">一、水神、海神</text>
+
+				<p class="paragraph_2">闽南近海,大多以海为田,以海为生,在与海交往的几千年里,闽南人最乐于将海神作为自己营生的保护神。</p>
+
+				<p class="paragraph_6">
+					闽南的水神、海神大概有四种:一为全国各地普遍存在的海龙王;二为闽南土生土长的海神妈祖;三为主管水的玄天上帝;四为较罕见的水仙尊王。水仙尊王并非独一角色。
+					有不同,常见者如西楚霸王项羽(乌江自刎)、屈原(汨罗江投江)、伍子胥(沉尸河底)、李白(醉酒溺亡)、王勃(渡江溺亡)、大禹(治水)等。
+				</p>
+			</view>
+
+			<view class="box_35">
+				<view class="ms_dianzan">
+					<view class="box_r">
+						<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+
+					<view class="box_r">
+						<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+						<text>1.5w</text>
+					</view>
+					<view class="box_r">
+						<uni-icons type="redo" size="20"></uni-icons>
+
+						<text lines="1" class="text-group_1">分享</text>
+					</view>
+				</view>
+			</view>
+			<text lines="1" class="text_5">相关推荐</text>
+			<view class="sh_xs">
+				<view class="sh_xs_item" v-for="item in shXiShuList" :key="item">
+					<view @click="detailsBtn" class="" style="width: 325rpx; height: 180rpx; border-radius: 10rpx">
+						<image style="width: 100%; height: 100%" :src="item.img"></image>
+					</view>
+					<view class="">{{ item.title }}</view>
+					<view class="ms_dianzan">
+						<view class="">
+							<uni-icons type="star-filled" color="#4e7198" size="20"></uni-icons>
+							<text>1.5w</text>
+						</view>
+
+						<view class="">
+							<uni-icons type="heart-filled" color="#ca5642" size="20"></uni-icons>
+							<text>1.5w</text>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			shXiShuList: [
+				{
+					img: 'https://www.chinanews.com/tp/hd2011/2013/03-11/U508P4T426D182733F16470DT20130311112416.jpg',
+					title: '闽南民俗浔浦天香日'
+				},
+				{
+					img: 'https://inews.gtimg.com/newsapp_bt/0/11032609926/1000',
+					title: '闽南冬至丸'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=1711973128,1321603179&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=333',
+					title: '闽南习俗拜天公'
+				},
+				{
+					img: 'https://i2.hdslb.com/bfs/archive/24ab948019ae5cc13055113cfcd5321f7c16dc41.jpg',
+					title: '抬神'
+				}
+			]
+		};
+	},
+	methods: {}
+};
+</script>
+
+<style>
+.ms_dianzan {
+	display: flex;
+	justify-content: space-between;
+	margin-top: 10rpx;
+}
+.box_r {
+	margin-right: 15rpx;
+}
+.sh_xs {
+	margin: 32rpx;
+	display: flex;
+	flex-flow: wrap;
+	justify-content: space-between;
+}
+.sh_xs_item {
+	border-radius: 10rpx;
+	background: #ffffff;
+	margin-bottom: 35rpx;
+}
+.text-group_17 {
+	width: 668rpx;
+	height: 163rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 0 0 0 35rpx;
+}
+.text_2 {
+	width: 668rpx;
+	height: 121rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 48rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+
+	line-height: 72rpx;
+}
+.text_13 {
+	width: 214rpx;
+	height: 18rpx;
+	overflow-wrap: break-word;
+	color: rgba(153, 153, 153, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+
+	white-space: nowrap;
+	line-height: 72rpx;
+	margin-top: 80rpx;
+}
+.block_3 {
+	background-color: rgba(255, 255, 255, 1);
+	width: 749rpx;
+	margin-top: 100rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text_3 {
+	width: 685rpx;
+	height: 270rpx;
+	text-indent: 2rem;
+	font-size: 0rpx;
+	overflow: scroll;
+	line-height: 48rpx;
+	margin: 38rpx 0 0 42rpx;
+}
+.text_10 {
+	width: 685rpx;
+	height: 270rpx;
+	/* overflow-wrap: break-word; */
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	line-height: 48rpx;
+}
+
+.box_3 {
+	background-color: rgba(232, 242, 217, 1);
+	height: 422rpx;
+	margin-top: 46rpx;
+	display: flex;
+	flex-direction: column;
+	width: 750rpx;
+}
+.box_4 {
+	background-color: rgba(0, 0, 0, 0.15);
+	width: 750rpx;
+	height: 422rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text-wrapper_1 {
+	width: 684rpx;
+	height: 378rpx;
+	overflow-wrap: break-word;
+	font-size: 0rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: justifyLeft;
+	line-height: 48rpx;
+	margin: 42rpx 0 32rpx 42rpx;
+}
+.paragraph_1 {
+	width: 684rpx;
+
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	line-height: 48rpx;
+}
+.paragraph_2 {
+	width: 684rpx;
+	margin-bottom: 10rpx;
+	text-indent: 2rem;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+
+	line-height: 48rpx;
+}
+.paragraph_5 {
+	width: 684rpx;
+	height: 378rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+
+	line-height: 14rpx;
+}
+.paragraph_6 {
+	width: 684rpx;
+	text-indent: 2rem;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+
+	line-height: 48rpx;
+}
+.text_5 {
+	width: 111rpx;
+	height: 28rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	margin-bottom: 20rpx;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin: 50rpx 0 0 48rpx;
+}
+.box_35 {
+	height: 32rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 150rpx 0 32rpx 380rpx;
+}
+</style>

+ 86 - 0
index_fenbao/mn_jingshen/mn_jingshen.vue

@@ -0,0 +1,86 @@
+<template>
+	<view class="box">
+		<u-navbar :autoBack="true" title="闽南精神" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="header">
+			<image style="width: 100%; height: 100%" src="http://mms2.baidu.com/it/u=4012979722,1550976495&fm=253&app=120&f=JPEG?w=1080&h=324"></image>
+		</view>
+		<view class="banner" v-for="item in list" :key="item.name">
+			<view class="box_img">
+				<image style="width: 100%; height: 100%; border-radius: 50%" :src="item.img" mode=""></image>
+			</view>
+			<view class="" style="line-height: 65rpx">
+				<view class="">{{ item.name }}</view>
+				<view class="" style="width: 450rpx">{{ item.title }}</view>
+			</view>
+			<view class="">
+				<uni-icons type="forward" size="24"></uni-icons>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			list: [
+				{
+					img: 'https://img2.baidu.com/it/u=2106717653,1595552958&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=337',
+					name: '郑成功',
+					title: '汉族,明末清初军事家,民族英雄'
+				},
+				{
+					img: 'https://img2.baidu.com/it/u=2734408568,2157410577&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=318',
+					name: '人文精神',
+					title: '追寻先人精神,品读闽南文化 '
+				},
+				{
+					img: 'https://img2.baidu.com/it/u=2106717653,1595552958&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=337',
+					name: '闽南华侨华人人文精神探析',
+					title: '拼搏进取,敢打敢拼的奋进精神'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=2520995424,4290269983&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1698858000&t=09b27eddc6fdec5ea15fb8c979a60ba6',
+					name: '李光地',
+					title: '名相故里安溪湖头'
+				}
+			]
+		};
+	},
+	methods: {}
+};
+</script>
+
+<style>
+.box {
+	height: auto;
+	width: 100%;
+	background-color: #f8f8f8;
+	background-attachment: fixed;
+	border-radius: 16px 16px 0 0;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+
+.header {
+	width: 100%;
+	height: 255rpx;
+}
+.banner {
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+	margin-left: 32rpx;
+	margin-bottom: 20rpx;
+	height: 198rpx;
+	background: #ffffff;
+	border-radius: 99rpx 0rpx 0rpx 99rpx;
+	padding-left: 10rpx;
+}
+.box_img {
+	width: 160rpx;
+	height: 160rpx;
+	border-radius: 50%;
+}
+</style>

+ 614 - 0
index_fenbao/mn_wenhua/mn_wenhua.vue

@@ -0,0 +1,614 @@
+<template>
+	<view class="body" style="background-color: #efefef">
+		<u-navbar :autoBack="true" title="文化" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="banxin">
+			<u-tabs
+				:list="listTab"
+				:lineWidth="30"
+				lineColor="#4E7198"
+				:activeStyle="{
+					color: '#4E7198',
+					fontSize: '34rpx'
+				}"
+			></u-tabs>
+		</view>
+
+		<view class="box_1">
+			<view class="box_28">
+				<view class="text-wrapper_46">
+					<text lines="1" class="text_8">课程录播</text>
+					<text lines="1" class="text_9">查看更多》</text>
+				</view>
+				<view class="group_3" v-for="item in 2" :key="item">
+					<view class="section_3">
+						<image src="../../../static/image/kctp.png"></image>
+					</view>
+					<view class="section_16">
+						<view class="text-group_36">
+							<text lines="1" class="text_10">课程标题</text>
+							<text lines="1" class="text_11">课程附标题</text>
+						</view>
+						<view class="text-wrapper_47">
+							<text lines="1" class="text_12">会员价</text>
+							<text lines="1" class="text_13">¥99</text>
+						</view>
+					</view>
+					<view class="text-wrapper_4">
+						<text lines="1" class="text_14">立即报名</text>
+					</view>
+				</view>
+
+				<view class="text-wrapper_50">
+					<text lines="1" class="text_25">文化集锦</text>
+					<text lines="1" class="text_9">查看更多》</text>
+				</view>
+				<view class="list_5">
+					<view class="image-text_2-0" v-for="item in 2" :key="item">
+						<view class="box_4-0">
+							<image src="../../../static/image/fx.png"></image>
+						</view>
+						<view class="box_30-0">
+							<view class="text-group_39-0">
+								<text lines="1" class="text_27-0">闽南的“博饼”文化</text>
+								<text lines="1" class="text_28-0">起源于清初,相传是郑成功屯兵鼓..</text>
+							</view>
+							<view class="box_31-0">
+								<view class="text-wrapper_10-0">
+									<text lines="1" class="text_31-0">#博饼</text>
+								</view>
+								<view class="text-wrapper_11-0">
+									<text lines="1" class="text_31-0">#博饼</text>
+								</view>
+								<view class="text-wrapper_25-0">
+									<text lines="1" decode="true" class="text_47-0">+&nbsp;收藏</text>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="text-wrapper_50">
+					<text lines="1" class="text_33">文章荟萃</text>
+					<text lines="1" class="text_9">查看更多》</text>
+				</view>
+				<view class="section_18">
+					<view class="box_7" v-for="item in 2" :key="item">
+						<view class="box_8">
+							<image style="width: 100%; height: 100%" src="../../../static/image/mn.png"></image>
+							<view class="block_3">
+								<view class="image-text_16">
+									<uni-icons color="#ffffff" type="locked" size="20"></uni-icons>
+
+									<text lines="1" class="text-group_8">待解锁</text>
+								</view>
+							</view>
+						</view>
+						<view class="group_25">
+							<view class="text-group_41">
+								<text lines="1" class="text_35">课程标题</text>
+								<text lines="1" class="text_36">课程附标题</text>
+							</view>
+							<view class="block_10">
+								<view class="text-wrapper_13">
+									<text lines="1" class="text_31-0">#标签</text>
+								</view>
+								<view class="text-wrapper_14">
+									<text lines="1" class="text_31-0">#标签</text>
+								</view>
+							</view>
+						</view>
+						<view class="text-wrapper_28">
+							<text lines="1" decode="true" class="text_49">+&nbsp;收藏</text>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			listTab: [
+				{
+					name: '历史',
+					tabid: 1
+				},
+				{
+					name: '宗教',
+					tabid: 2
+				},
+				{
+					name: '经典',
+					tabid: 3
+				},
+				{
+					name: '人物',
+					tabid: 4
+				},
+				{
+					name: '社会',
+					tabid: 5
+				}
+			]
+		};
+	},
+	methods: {}
+};
+</script>
+
+<style>
+.banxin {
+	margin: 0 32rpx 0 32rpx;
+}
+.box_1 {
+	width: 750rpx;
+	display: flex;
+	flex-direction: column;
+	background-color: #efefef;
+}
+
+.box_28 {
+	width: 750rpx;
+
+	display: flex;
+	flex-direction: column;
+}
+.text-wrapper_46 {
+	width: 684rpx;
+	height: 27rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 42rpx 0 0 34rpx;
+}
+.text_8 {
+	width: 111rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text_9 {
+	width: 89rpx;
+	height: 20rpx;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 4rpx;
+}
+.group_3 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 686rpx;
+	height: 170rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 30rpx 0 0 31rpx;
+}
+.section_3 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	width: 307rpx;
+	height: 170rpx;
+	display: flex;
+	flex-direction: column;
+}
+.section_16 {
+	width: 130rpx;
+	height: 122rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 29rpx 0 0 20rpx;
+}
+.text-group_36 {
+	width: 111rpx;
+	height: 61rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+.text_10 {
+	width: 110rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-left: 1rpx;
+}
+.text_11 {
+	width: 107rpx;
+	height: 21rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 22rpx;
+	margin-top: 14rpx;
+}
+.text-wrapper_47 {
+	width: 125rpx;
+	height: 22rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 39rpx 0 0 5rpx;
+}
+.text_12 {
+	width: 60rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 20rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 2rpx;
+}
+.text_13 {
+	width: 56rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text-wrapper_4 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	height: 44rpx;
+	display: flex;
+	flex-direction: column;
+	width: 129rpx;
+	margin: 115rpx 18rpx 0 82rpx;
+}
+.text_14 {
+	width: 92rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(248, 226, 175, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 10rpx 0 0 18rpx;
+}
+
+.text-wrapper_50 {
+	width: 670rpx;
+	height: 27rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 32rpx 0 0 32rpx;
+}
+.text_25 {
+	width: 111rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+
+.list_5 {
+	width: 686rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 30rpx 0 0 31rpx;
+}
+.image-text_2-0 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 686rpx;
+	height: 170rpx;
+	margin-bottom: 31rpx;
+	flex-direction: row;
+	display: flex;
+}
+.box_4-0 {
+	border-radius: 10rpx;
+	height: 170rpx;
+	display: flex;
+	flex-direction: column;
+	width: 307rpx;
+	background: rgba(202, 86, 66, 1);
+}
+.box_30-0 {
+	position: relative;
+	width: 343rpx;
+	height: 125rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 29rpx 0 0 19rpx;
+}
+.text-group_39-0 {
+	position: absolute;
+	left: 1rpx;
+	top: 0rpx;
+	width: 337rpx;
+	height: 62rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+.text_27-0 {
+	width: 249rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-left: 2rpx;
+}
+.text_28-0 {
+	width: 337rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 36rpx;
+	margin-top: 14rpx;
+}
+.box_31-0 {
+	width: 343rpx;
+	height: 44rpx;
+	margin-top: 81rpx;
+	flex-direction: row;
+	display: flex;
+}
+.text-wrapper_10-0 {
+	background-color: rgba(202, 86, 66, 0.09);
+	border-radius: 18rpx;
+	height: 36rpx;
+	border: 1px solid rgba(202, 87, 66, 1);
+	margin-top: 7rpx;
+	display: flex;
+	flex-direction: column;
+	width: 84rpx;
+}
+.text_31-0 {
+	width: 50rpx;
+	height: 19rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 20rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 46rpx;
+	margin: -6rpx 0 0 12rpx;
+}
+.text-wrapper_11-0 {
+	background-color: rgba(255, 135, 2, 0.09);
+	border-radius: 18rpx;
+	height: 36rpx;
+	border: 1px solid rgba(255, 135, 2, 1);
+	display: flex;
+	flex-direction: column;
+	width: 84rpx;
+	margin: 7rpx 0 0 11rpx;
+}
+
+.text-wrapper_25-0 {
+	background-color: rgba(78, 113, 152, 1);
+	border-radius: 10rpx;
+	height: 44rpx;
+	margin-left: 60rpx;
+	display: flex;
+	flex-direction: column;
+	width: 104rpx;
+}
+.text_47-0 {
+	width: 65rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 10rpx 0 0 18rpx;
+}
+
+.text_33 {
+	width: 111rpx;
+	height: 28rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+
+.section_18 {
+	width: 686rpx;
+	height: 371rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 29rpx 0 32rpx 31rpx;
+}
+.box_7 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 686rpx;
+	height: 170rpx;
+	flex-direction: row;
+	display: flex;
+}
+.box_8 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	height: 170rpx;
+	display: flex;
+	flex-direction: column;
+	width: 307rpx;
+}
+.block_3 {
+	position: absolute;
+	background-color: rgba(0, 0, 0, 0.3);
+	border-radius: 10rpx;
+	width: 307rpx;
+	height: 170rpx;
+	display: flex;
+	flex-direction: row;
+}
+.image-text_16 {
+	width: 97rpx;
+	height: 27rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 71rpx 0 0 105rpx;
+	line-height: 25rpx;
+}
+
+.text-group_8 {
+	width: 71rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-top: 3rpx;
+}
+.group_25 {
+	width: 179rpx;
+	height: 122rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 29rpx 0 0 19rpx;
+}
+.text-group_41 {
+	width: 111rpx;
+	height: 61rpx;
+	margin-left: 1rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+.text_35 {
+	width: 110rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-left: 1rpx;
+}
+.text_36 {
+	width: 107rpx;
+	height: 21rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 22rpx;
+	margin-top: 14rpx;
+}
+.block_10 {
+	width: 179rpx;
+	height: 36rpx;
+	margin-top: 25rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+}
+.text-wrapper_13 {
+	background-color: rgba(202, 86, 66, 0.09);
+	border-radius: 18rpx;
+	height: 36rpx;
+	border: 1px solid rgba(202, 87, 66, 1);
+	display: flex;
+	flex-direction: column;
+	width: 84rpx;
+}
+
+.text-wrapper_14 {
+	background-color: rgba(255, 135, 2, 0.09);
+	border-radius: 18rpx;
+	height: 36rpx;
+	border: 1px solid rgba(255, 135, 2, 1);
+	display: flex;
+	flex-direction: column;
+	width: 84rpx;
+}
+.text-wrapper_28 {
+	background-color: rgba(78, 113, 152, 1);
+	border-radius: 10rpx;
+	height: 44rpx;
+	display: flex;
+	flex-direction: column;
+	width: 104rpx;
+	margin: 106rpx 17rpx 0 60rpx;
+}
+.text_49 {
+	width: 65rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 10rpx 0 0 18rpx;
+}
+</style>

+ 20 - 0
jiyi_fenbao/aaa.vue

@@ -0,0 +1,20 @@
+<template>
+	<view>
+		<u-navbar :autoBack="true" title="分包" leftText="返回" :placeholder="true" bgColor="rgba(255,255,255,0.3)" titleStyle="font-weight:bold;color:#7a5831"></u-navbar>
+		<h1>分包</h1>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {};
+	},
+	onLoad(options) {
+		console.log(options);
+	},
+	methods: {}
+};
+</script>
+
+<style></style>

+ 22 - 0
jiyi_fenbao/bb/bb.vue

@@ -0,0 +1,22 @@
+<template>
+	<view>
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 147 - 0
main.js

@@ -0,0 +1,147 @@
+import Vue from 'vue'
+import App from './App'
+import * as Api from './config/api.js'
+import * as Common from './config/common.js'
+import * as Db from './config/db.js'
+import * as Config from './config/config.js'
+import share from "@/common/share.js"
+import store from './store';
+import util from "@/common/util.js"
+
+
+
+const logic = {
+	systemInfo: null,
+	/**
+	 * 显示消息提示
+	 * 
+	 * @param {Object} text
+	 * @param {Object} icon
+	 */
+	showToast(text, icon) {
+		return uni.showToast({
+			title: text || '加载中',
+			icon: icon || 'none',
+			mask: true,
+			duration: 2000
+		});
+	},
+	/**
+	 * 全局方法 - px2rpx 
+	 *
+	 * @param {Object} px
+	 */
+	px2rpx(px) {
+		if (this.systemInfo === null) {
+			this.systemInfo = uni.getSystemInfoSync()
+		}
+
+		//  官方规定屏幕宽为750rpx
+		return px / this.systemInfo.windowWidth * 750;
+	},
+
+	/**
+	 * 全局方法 - rpx2px
+	 * 
+	 * @param {Object} rpx
+	 */
+	rpx2px(rpx) {
+		if (this.systemInfo === null) {
+			this.systemInfo = uni.getSystemInfoSync()
+		}
+
+		//  官方规定屏幕宽为750rpx
+		return rpx / 750 * this.systemInfo.windowWidth;
+	},
+}
+
+// import {
+// 	createSSRApp
+// } from 'vue'
+// export function createApp() {
+// 	const app = createSSRApp(App)
+// 	app.use(store)
+// 	app.config.globalProperties.$logic = logic
+// 	return {
+// 		app
+// 	}
+// }
+
+function isPromise(obj) {
+	return (!!obj &&
+		(typeof obj === "object" || typeof obj === "function") &&
+		typeof obj.then === "function"
+	);
+}
+
+// uni方法转then数组
+uni.addInterceptor({
+	returnValue(res) {
+		if (!isPromise(res)) {
+			return res;
+		}
+		const returnValue = [undefined, undefined];
+		return res
+			.then((res) => {
+				returnValue[1] = res;
+			})
+			.catch((err) => {
+				returnValue[0] = err;
+			})
+			.then(() => returnValue);
+	},
+});
+
+import {
+	tools
+} from '@/common/fa.mixin.js'
+Vue.mixin(tools)
+//皮肤色处理
+let styleMixin = require('@/common/fa.style.mixin.js')
+Vue.mixin(styleMixin)
+import uView from '@/uni_modules/uview-ui'
+Vue.use(uView)
+
+Vue.prototype.$api = Api;
+Vue.prototype.$common = Common;
+Vue.prototype.$db = Db;
+Vue.prototype.$config = Config;
+Vue.prototype.$logic = logic;
+Vue.prototype.$util = util;
+Vue.prototype.vuex_token = '';
+Vue.prototype.user = {};
+Vue.prototype.vuex_theme = {
+	value: {
+		color: "#fff",
+		bgColor: "#c7a772"
+	}
+}
+Vue.prototype.vuex_parse_style = {
+	h1: 'padding:20rpx 0;',
+	h2: 'padding:10rpx 0;',
+	h3: 'padding:10rpx 0;',
+	h4: 'padding:10rpx 0;',
+	h5: 'padding:5rpx 0;',
+	h6: 'padding:5rpx 0;',
+	ul: 'margin-bottom:20rpx;padding-left:30rpx;',
+	ol: 'margin-bottom:20rpx;padding-left:30rpx;',
+	code: 'background-color: #f6f6f6;margin: 0 5rpx;padding: 6rpx 8rpx;border-radius: 6rpx;text-align:center;',
+	pre: 'white-space: pre;overflow: auto;background: #f6f6f6;border-radius: 8rpx;border: none;color: #1a1a1a;margin-bottom: 20rpx;padding:20rpx;',
+	'pre code': 'margin:0;padding:0;',
+	blockquote: 'padding: 15rpx;margin:0 0 20rpx 0;border-radius: 6rpx;',
+	p: 'margin-bottom:20rpx',
+	table: 'width:100%;margin-bottom:20rpx;border-collapse: collapse;',
+	th: 'background-color: whitesmoke;border: 1px solid #e6e6e6;padding:10rpx;',
+	td: 'border: 1px solid #e6e6e6;padding:10rpx;'
+}
+Vue.prototype.vuex_config = {}
+Vue.config.productionTip = false
+
+Vue.mixin(share)
+App.mpType = 'app'
+
+const app = new Vue({
+	...App,
+	store
+})
+app.$mount()

+ 170 - 0
manifest.json

@@ -0,0 +1,170 @@
+{
+    "name" : "闽南魂",
+    "appid" : "__UNI__5CDBB2E",
+    "description" : "闽南魂",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "Share" : {}
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "idfa" : false
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "maps" : {
+                    "qqmap" : {
+                        // 腾讯地图秘钥 https://lbs.qq.com/dev/console/key/manage
+                        "key" : "FHEBZ-HYVNS-KGHOD-65O3N-O32P3-5FBI6"
+                    },
+                    "amap" : {
+                        "appkey_ios" : "",
+                        "appkey_android" : ""
+                    }
+                },
+                "ad" : {},
+                "share" : {
+                    "weixin" : {
+                        "appid" : "wx9a27d13d29890754",
+                        "UniversalLinks" : ""
+                    }
+                }
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "androidStyle" : "common"
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wx9a27d13d29890754",
+        "setting" : {
+            "urlCheck" : false,
+            "es6" : true,
+            "minified" : true
+        },
+        "usingComponents" : true,
+        "permission" : {
+            "scope.userLocation" : {
+                "desc" : "你的位置信息将用于小程序位置接口的效果展示"
+            }
+        },
+        "requiredPrivateInfos" : [ "getLocation" ]
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "h5" : {
+        "devServer" : {
+            "https" : false
+        },
+        "router" : {
+            "base" : "",
+            "mode" : "hash"
+        },
+        "title" : "闽南魂",
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        },
+        "domain" : "http://demo.usiyi.com/discover_h5/",
+        "sdkConfigs" : {
+            "maps" : {
+                "qqmap" : {
+                    "key" : "FHEBZ-HYVNS-KGHOD-65O3N-O32P3-5FBI6"
+                }
+            }
+        }
+    },
+    "vueVersion" : "2"
+}

+ 14 - 0
mixins/auth.js

@@ -0,0 +1,14 @@
+import {
+	silentReload
+} from '@/service/request/main.js'
+
+export default {
+	onLoad(options) {
+		console.log('onload mixin auth')
+		if (!this.$store.getters.accessToken) {
+			console.info('needLogin onload')
+			console.info('needLogin onload', 'silentReload')
+			silentReload()
+		}
+	}
+}

+ 102 - 0
mixins/common.js

@@ -0,0 +1,102 @@
+import {
+	buildPageUrl,
+	formatDate,
+	encodeRedirectUrl
+} from '../common/util.js'
+import {
+
+	getRedirectUrl
+} from '@/service/request/main.js'
+
+export default {
+	data() {
+		const pages = getCurrentPages()
+		console.log(pages);
+		const PageTitle = '闽南魂';
+		if (pages.length > 0) {
+			const currentPage = pages[pages.length - 1]
+			const currentPageUrl = buildPageUrl(currentPage.route, currentPage.options)
+			return {
+				PageTitle,
+				currentPage,
+				currentPageUrl
+			}
+		} else {
+			return {
+				PageTitle
+			}
+		}
+
+	},
+	onLoad(options) {
+		console.log('page onLoad', this.currentPageUrl);
+	},
+	methods: {
+		onCopy(text) {
+			uni.setClipboardData({
+				data: text + ''
+			}).then(([err, res]) => {
+				console.log('uni.setClipboardData', err, res);
+				if (!err) {
+					uni.showToast({
+						title: '复制成功',
+						icon: 'none',
+					});
+				}
+			});
+		},
+		checkLogin() {
+			if (!this.isLogin) {
+				uni.navigateTo({
+					url: '/pages/user/login?from=' + encodeRedirectUrl(getRedirectUrl())
+				})
+				return false
+			}
+
+			return true
+		},
+	},
+	computed: {
+		costTime() {
+			return (seconds, type) => {
+				let second = parseInt(seconds)
+				if (second <= 0) {
+					if (type === 'countdown') {
+						return '已结束'
+					}
+					return '0秒'
+				}
+				let minute = 0 // 初始化分
+				let hour = 0 // 初始化小时
+				if (second >= 60) { // 如果秒数大于等于60,将秒数转换成分钟
+					minute = parseInt(second / 60) // 获取分钟
+					second = parseInt(second % 60) // 获取秒数
+					if (minute >= 60) { // 如果分钟大于等于60,将分钟转换成小时
+						hour = parseInt(minute / 60) // 获取小时
+						minute = parseInt(minute % 60) // 获取小时后取余的分
+					}
+				}
+				if (type === 'countdown') {
+					return `${hour.toString().padStart(2,'0')}:${minute.toString().padStart(2,'0')}:${second.toString().padStart(2,'0')}`
+				}
+				let desc = ''
+				if (hour > 0) {
+					desc = hour + '小时'
+				}
+				if (minute > 0 || hour > 0) {
+					desc += minute + '分'
+				}
+				desc += second + '秒'
+				return desc
+			}
+		},
+		timeFormat() {
+			return (timestamp) => {
+				if (!timestamp) {
+					return ''
+				}
+				return formatDate(timestamp, 'yyyy-MM-dd hh:mm:ss')
+			}
+		},
+	},
+}

+ 31 - 0
mixins/goods.js

@@ -0,0 +1,31 @@
+export default {
+	data() {
+		return {
+			textCost: false
+		}
+	},
+	computed: {
+		iphonePlatform() {
+			const systemInfo = this.$store.getters.systemInfo
+			if (systemInfo && Object.keys(systemInfo).length > 0) {
+				return systemInfo.model.indexOf('iPhone') !== -1
+			}
+
+			return false
+		},
+		goodsPrice() {
+			return (price) => {
+				if (price > 0) {
+					if (this.iphonePlatform) {
+						this.textCost = true
+						return '需要申请'
+					}
+					return '¥' + price
+				}
+				this.textCost = true
+
+				return '免费'
+			}
+		}
+	}
+}

+ 30 - 0
node_modules/jweixin-module/README.md

@@ -0,0 +1,30 @@
+# jweixin-module
+
+微信JS-SDK
+
+## 安装
+
+### NPM
+
+```shell
+npm install jweixin-module --save
+```
+
+### UMD
+
+```http
+https://unpkg.com/jweixin-module/out/index.js
+```
+
+## 使用
+
+```js
+var jweixin = require('jweixin-module')
+jweixin.ready(function(){
+    // TODO
+});
+```
+
+## 完整API
+
+>[微信JS-SDK说明文档](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 0
node_modules/jweixin-module/lib/index.js


+ 26 - 0
node_modules/jweixin-module/package.json

@@ -0,0 +1,26 @@
+{
+  "name": "jweixin-module",
+  "version": "1.6.0",
+  "description": "微信JS-SDK",
+  "main": "lib/index.js",
+  "scripts": {},
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/zhetengbiji/jweixin-module.git"
+  },
+  "keywords": [
+    "wxjssdk",
+    "weixin",
+    "jweixin",
+    "wechat",
+    "jssdk",
+    "wx"
+  ],
+  "author": "Shengqiang Guo",
+  "license": "ISC",
+  "bugs": {
+    "url": "https://github.com/zhetengbiji/jweixin-module/issues"
+  },
+  "homepage": "https://github.com/zhetengbiji/jweixin-module#readme",
+  "devDependencies": {}
+}

+ 418 - 0
pages.json

@@ -0,0 +1,418 @@
+{
+	// "easycom": {
+	// 	"custom": {
+	// 		"autoscan": true,
+	// 		"gui-(.*)": "@/GraceUI5/components/gui-$1.vue",
+	// 		"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
+	// 	}
+	// },
+
+	"pages": [{
+			"path": "components/mn_yindaoye",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+
+		},
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/jiyi/jiyi",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		},
+
+		{
+			"path": "pages/chuanCheng/chuanCheng",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/user/index",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		},
+
+		{
+			"path": "pages/xueYuan/xueYuan",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		},
+		{
+			"path": "pages/user/login",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}
+
+
+		, {
+			"path": "pages/course/index",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/course/detail",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/schedule/detail",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}
+
+		, {
+			"path": "pages/schedule/index",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/user/learn",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/order/preview",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/teacher/detail",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+
+		}
+
+
+	],
+
+	// 分包
+	"subPackages": [{
+			"root": "index_fenbao/cs_liebiao",
+			"pages": [{
+				"path": "cs_liebiao",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		},
+		{
+			"root": "index_fenbao/feiyi",
+			"pages": [{
+				"path": "feiyi",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		},
+		{
+			"root": "index_fenbao/jianzhu",
+			"pages": [{
+				"path": "jianzhu",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		},
+		{
+			"root": "index_fenbao/minNanyu",
+			"pages": [{
+				"path": "minNanyu",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}, {
+				"path": "yinPinLieBiao",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+			}]
+		},
+		{
+			"root": "index_fenbao/minsu",
+			"pages": [{
+				"path": "minsu",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}, {
+				"path": "ms_wenZhang",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+			}]
+		},
+		{
+			"root": "index_fenbao/mn_jingshen",
+			"pages": [{
+				"path": "mn_jingshen",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		},
+		{
+			"root": "index_fenbao/mn_wenhua",
+			"pages": [
+
+
+				{
+					"path": "mn_wenhua",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				}
+			]
+		},
+
+
+		{
+			"root": "jiyi_fenbao",
+			"pages": [{
+				"path": "aaa",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}, {
+				"path": "bb/bb",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		},
+
+		// llllllllllll
+		{
+			"root": "xueyuan_fenbao/zhuangJia",
+			"pages": [{
+					"path": "zhuangJia",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				},
+				{
+					"path": "huodongXq",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				}
+			]
+		},
+
+
+		{
+			"root": "xueyuan_fenbao/kcXiangQing",
+			"pages": [{
+					"path": "kcXiangQing",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				},
+				{
+					"path": "huoDong",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				}, {
+					"path": "baoMing",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				}, {
+					"path": "zhengCe",
+					"style": {
+						"navigationBarTitleText": "",
+						"enablePullDownRefresh": false
+					}
+
+				}
+			]
+		},
+		{
+			"root": "xueyuan_fenbao/jiGou",
+			"pages": [{
+				"path": "jiGou",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		},
+
+		// 2222222
+		{
+			"root": "chuanCheng_fenbao/search",
+			"pages": [{
+				"path": "search",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		}, {
+			"root": "user_fenbao",
+			"pages": [{
+				"path": "myLike",
+				"style": {
+					"navigationBarTitleText": "",
+					"enablePullDownRefresh": false
+				}
+
+			}]
+		}
+
+	],
+
+	//分包预加载
+	"preloadRule": {
+		"pages/index/index": {
+			"network": "all",
+			"packages": ["index_fenbao/cs_liebiao",
+				"index_fenbao/feiyi",
+				"index_fenbao/jianzhu",
+				"index_fenbao/minNanyu",
+				"index_fenbao/minsu",
+				"index_fenbao/mn_jingshen",
+				"index_fenbao/mn_wenhua"
+			]
+		},
+
+		"pages/jiyi/jiyi": {
+			"network": "all",
+			"packages": ["jiyi_fenbao"]
+		},
+		"pages/xueYuan/xueYuan": {
+			"network": "all",
+			"packages": [
+				"xueyuan_fenbao/jiGou",
+				"xueyuan_fenbao/zhuangJia",
+				"xueyuan_fenbao/kcXiangQing"
+			]
+		}
+
+	},
+	"tabBar": {
+		"color": "#282828",
+		"selectedColor": "#a9360d",
+		"borderStyle": "white",
+		"backgroundColor": "#ffffff",
+		"custom": true, //开启自定义tarBar
+		"list": [{
+				"pagePath": "pages/index/index"
+
+			},
+			{
+				"pagePath": "pages/jiyi/jiyi"
+
+
+			},
+
+			{
+				"pagePath": "pages/chuanCheng/chuanCheng"
+
+
+			},
+			{
+				"pagePath": "pages/xueYuan/xueYuan"
+
+
+			},
+			{
+				"pagePath": "pages/user/index"
+
+
+			}
+
+		]
+	},
+
+	"globalStyle": {
+
+		"mp-alipay": {
+			/* 支付宝小程序特有相关 */
+			"transparentTitle": "always",
+			"allowsBounceVertical": "NO"
+		},
+		"navigationBarBackgroundColor": "#AACCEE32",
+		"navigationBarTitleText": "",
+		"navigationStyle": "custom",
+		"navigationBarTextStyle": "black"
+	},
+	"usingComponts": true,
+	"condition": { //模式配置,仅开发期间生效
+		"current": 0, //当前激活的模式(list 的索引项)
+		"list": []
+	},
+	"sitemapLocation": "sitemap.json"
+
+}

+ 199 - 0
pages/chuanCheng/chuanCheng.vue

@@ -0,0 +1,199 @@
+<template>
+	<view class="">
+		<view class="box">
+			<view class="box_top">
+				<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/ccbg.png"></image>
+			</view>
+			<view class="box_search" @click="searchBtn">
+				<view class="">
+					<uni-icons type="search" size="20"></uni-icons>
+				</view>
+				<view class="">请输入搜索内容</view>
+			</view>
+			<view class="box_tab">
+				<u-tabs
+					:duration="200"
+					:list="listTab"
+					:lineWidth="25"
+					:lineHeight="12"
+					lineColor="#4E7198"
+					:lineColor="`url(${tabImg}) 100% 100%`"
+					:activeStyle="{
+						color: '#4E7198',
+						fontSize: '34rpx'
+					}"
+				></u-tabs>
+			</view>
+			<!-- 瀑布流 -->
+
+			<custom-waterfalls-flow :value="list" style="width: 90%; margin: auto">
+				<view class="item" style="position: relative" v-for="(item, index) in list" :key="index" slot="slot{{index}}">
+					<view class="title_pubu">
+						{{ item.title }}
+					</view>
+					<!-- <view class="desc">{{ item.desc }}</view> -->
+				</view>
+			</custom-waterfalls-flow>
+		</view>
+		<mntabBar footerTab="2" :messageCount="0"></mntabBar>
+	</view>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+let that;
+
+export default {
+	components: {},
+	data() {
+		return {
+			tabImg: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/tab.png',
+			list: [
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy1.png',
+					title: '传统捏泥人',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy2.png',
+					title: '青龙宫',
+					desc: '描述描述描述描述描述描述描述描述1'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy3.png',
+					title: '火把节',
+					desc: '11'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy9.png',
+					title: '老物件',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy4.png',
+					title: '林后青龙宫',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy10.png',
+					title: '书籍',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy7.png',
+					title: '建筑',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy8.png',
+					title: '老钟表',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy14.png',
+					title: '老物件',
+					desc: '描述描述描述描述描述描述描述描述2'
+				}
+			],
+			listTab: [
+				{
+					name: '书法',
+					tabid: 1
+				},
+				{
+					name: '戏曲',
+					tabid: 2
+				},
+				{
+					name: '非遗',
+					tabid: 3
+				},
+				{
+					name: '文化',
+					tabid: 4
+				},
+				{
+					name: '创作',
+					tabid: 5
+				}
+			]
+		};
+	},
+	onLoad(option) {
+		that = this;
+	},
+	computed: {},
+	methods: {
+		searchBtn() {
+			uni.navigateTo({
+				url: '/chuanCheng_fenbao/search/search'
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.body {
+	/* background-image: url('https://huli-app.wenlvti.net/uploads/20230512/88f8347924d08296bbde9d55afd74c15.jpg');
+	background-size: 100% 100%; */
+	background-attachment: fixed;
+}
+/deep/.u-tabs__wrapper__nav__item.data-v-48634e29 {
+	padding: 0 40rpx !important;
+}
+/deep/.u-tabs__wrapper__nav__line.data-v-48634e29 {
+	bottom: 16rpx !important;
+}
+/deep/.u-tabs__wrapper__nav__item.data-v-48634e29 {
+	align-items: end !important;
+}
+/deep/.column-value.data-v-ddfcbb1c {
+	border-radius: 25rpx 60rpx 0rpx 30rpx !important;
+}
+.box {
+	height: auto;
+	width: 100%;
+	background-color: #eff6ff;
+	background-attachment: fixed;
+	border-radius: 16px 16px 0 0;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+.box_top {
+	width: 100%;
+	height: 410rpx;
+}
+.box_search {
+	display: flex;
+	align-items: center;
+	padding-left: 20rpx;
+	box-sizing: border-box;
+	width: 685rpx;
+	height: 80rpx;
+	color: #999999;
+	font-size: 28rpx;
+	background-color: #ffffff;
+	z-index: 2;
+	border-radius: 40rpx;
+	margin: -90rpx 32rpx 0 34rpx;
+}
+.box_tab {
+	margin: 45rpx 32rpx 0 32rpx;
+}
+.title_pubu {
+	width: 100%;
+	height: 65rpx;
+	line-height: 65rpx;
+	background-color: #ca5642;
+	font-size: 30rpx;
+	color: #ffffff;
+	text-align: center;
+	position: absolute;
+	bottom: 0;
+	left: 0;
+}
+</style>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1094 - 0
pages/course/detail.vue


+ 373 - 0
pages/course/index.vue

@@ -0,0 +1,373 @@
+<template>
+	<view class="wrap">
+		<u-navbar :autoBack="true" title="课程" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="search">
+			<view class="b-input">
+				<input class="s-input" :value="keyword" @input="onInput" @confirm="onSearch" placeholder="搜索课程" />
+				<view class="s-submit iconfont icon-search" @click="onSearch"></view>
+			</view>
+		</view>
+		<view class="category-list">
+			<view class="b-row">
+				<view class="b-all" @click="onCategorySelect('first', -1)" :class="{ 'f-active': -1 === firstCategoryIndex }">不限</view>
+				<view class="b-items">
+					<view
+						class="s-item"
+						v-for="(item, index) in categoryList"
+						:key="index"
+						@click="onCategorySelect('first', index)"
+						:class="{ 'f-active': index === firstCategoryIndex }"
+					>
+						{{ item.name }}
+					</view>
+				</view>
+			</view>
+			<view class="b-row" v-if="secondCategoryList.length > 0">
+				<view class="b-all" @click="onCategorySelect('second', -1)" :class="{ 'f-active': -1 === secondCategoryIndex }">不限</view>
+				<view class="b-items">
+					<view
+						class="s-item"
+						v-for="(item, index) in secondCategoryList"
+						:key="index"
+						@click="onCategorySelect('second', index)"
+						:class="{ 'f-active': index === secondCategoryIndex }"
+					>
+						{{ item.name }}
+					</view>
+				</view>
+			</view>
+			<view class="b-row" v-if="thirdCategoryList.length > 0">
+				<view class="b-all" @click="onCategorySelect('third', -1)" :class="{ 'f-active': -1 === thirdCategoryIndex }">不限</view>
+				<view class="b-items">
+					<view
+						class="s-item"
+						v-for="(item, index) in thirdCategoryList"
+						:key="index"
+						@click="onCategorySelect('third', index)"
+						:class="{ 'f-active': index === thirdCategoryIndex }"
+					>
+						{{ item.name }}
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="filter-box">
+			<view class="b-item" v-for="(item, index) in groupList" :key="index" :class="{ 'f-active': index == groupIndex }" @click="onGroupSelect(index)">
+				<view class="s-tit">{{ item.name }}</view>
+				<view class="iconfont" v-if="item.sort && index == groupIndex" :class="{ 'icon-unfold': item.sort == 'asc', 'icon-fold': item.sort == 'desc' }"></view>
+			</view>
+		</view>
+		<view class="course-list">
+			<view class="b-items">
+				<course-item v-for="item in courseList" :item="item" :key="item.id"></course-item>
+			</view>
+			<!-- 加载中 -->
+			<load-more :loadingType="loadingType" :loadingText="loadingText"></load-more>
+		</view>
+	</view>
+</template>
+
+<script>
+// import { getCategoryList, getCourseList } from '@/service/api/course.js';
+// import mixinsCommon from '@/mixins/common.js';
+let that;
+export default {
+	// mixins: [mixinsCommon],
+	data() {
+		return {
+			groupIndex: 0,
+			groupList: [
+				{
+					name: '全部',
+					value: 'all',
+					sort: ''
+				},
+				{
+					name: '免费',
+					value: 'free',
+					sort: ''
+				},
+				{
+					name: 'VIP',
+					value: 'vip',
+					sort: ''
+				},
+				{
+					name: '热门',
+					value: 'hot',
+					sort: ''
+				},
+				{
+					name: '价格',
+					value: 'price',
+					sort: 'asc'
+				}
+			],
+			categoryList: [],
+			categoryValue: 0,
+			firstCategoryIndex: -1,
+			secondCategoryIndex: -1,
+			thirdCategoryIndex: -1,
+			courseList: [],
+			keyword: '',
+			loadingType: 1,
+			loadingText: ''
+		};
+	},
+	computed: {
+		secondCategoryList() {
+			if (this.firstCategoryIndex === -1) {
+				return [];
+			}
+			return this.categoryList[this.firstCategoryIndex].children;
+		},
+		thirdCategoryList() {
+			if (this.secondCategoryIndex === -1) {
+				return [];
+			}
+			return this.categoryList[this.firstCategoryIndex].children[this.secondCategoryIndex].children;
+		}
+	},
+	onLoad(options) {
+		that = this;
+		this.$api.getCategoryList({}, function (res) {
+			console.log(res.data, 9999);
+			that.categoryList = res.data;
+		});
+		// getCategoryList().then(([err, res]) => {
+		// 	console.log('getCourseList', err, res);
+		// 	if (!err) {
+		// 		this.categoryList = res;
+		// 		console.log(this.categoryList, 'this.categoryList');
+		// 	}
+		// });
+		this.loadList(true);
+	},
+	onReachBottom() {
+		if (this.loadingType !== 1 && this.loadingType !== 2) {
+			this.loadList();
+		}
+	},
+	methods: {
+		loadList(refresh) {
+			console.log('loadList', refresh);
+			if (refresh) {
+				this.page = 1;
+				this.courseList = [];
+			} else {
+				this.page++;
+			}
+
+			this.loadingType = 1;
+			this.loadingText = '';
+			this.$api.getCourseList(
+				{
+					category_id: this.categoryValue,
+					group: this.groupList[this.groupIndex].value,
+					keyword: this.keyword,
+					page: this.page,
+					page_size: 10,
+					sort: this.groupList[this.groupIndex].sort
+				},
+				function (res) {
+					that.loadingType = -1;
+					console.log('啦啦啦', res);
+					that.loadingType = -1;
+					if (res.code == 1) {
+						if (res.data.items.length > 0) {
+							that.courseList = [...that.courseList, ...res.data.items];
+						} else {
+							that.loadingType = 2;
+							if (that.page == 1) {
+								that.loadingText = '暂无课程数据';
+							}
+							that.page--; // 重置分页
+						}
+					} else {
+						that.loadingType = 3;
+					}
+				}
+			);
+			// getCourseList(this.categoryValue, this.groupList[this.groupIndex].value, this.groupList[this.groupIndex].sort, this.keyword, this.page, 10).then(([err, res]) => {
+			// 	console.log('getCourseList', err, res);
+			// 	this.loadingType = -1;
+			// 	if (!err) {
+			// 		if (res.items.length > 0) {
+			// 			this.courseList = [...this.courseList, ...res.items];
+			// 		} else {
+			// 			this.loadingType = 2;
+			// 			if (this.page == 1) {
+			// 				this.loadingText = '暂无课程数据';
+			// 			}
+			// 			this.page--; // 重置分页
+			// 		}
+			// 	} else {
+			// 		this.loadingType = 3;
+			// 	}
+
+			// });
+		},
+		onInput(e) {
+			this.keyword = e.detail.value;
+		},
+		onSearch() {
+			if (this.keyword) {
+				this.onCategorySelect('first', -1);
+			}
+		},
+		onCategorySelect(level, index) {
+			if (this.keyword && !(level === 'first' && index === -1)) {
+				this.keyword = '';
+			}
+			if (level === 'first') {
+				this.firstCategoryIndex = index;
+				if (index === -1) {
+					this.categoryValue = 0;
+				} else {
+					this.categoryValue = this.categoryList[index].id;
+				}
+			} else if (level === 'second') {
+				this.secondCategoryIndex = index;
+				if (index === -1) {
+					this.categoryValue = this.categoryList[this.firstCategoryIndex].id;
+				} else {
+					this.categoryValue = this.categoryList[this.firstCategoryIndex].children[index].id;
+				}
+			} else if (level === 'third') {
+				this.thirdCategoryIndex = index;
+				if (index === -1) {
+					this.categoryValue = this.categoryList[this.firstCategoryIndex].children[this.secondCategoryIndex].id;
+				} else {
+					this.categoryValue = this.categoryList[this.firstCategoryIndex].children[this.secondCategoryIndex].children[index].id;
+				}
+			}
+			this.loadList(true);
+		},
+		// 分类点击事件
+		onGroupSelect(index) {
+			console.log(index);
+			if (index == this.groupIndex) {
+				const sort = this.groupList[this.groupIndex].sort;
+				if (sort) {
+					if (sort === 'asc') {
+						this.groupList[this.groupIndex].sort = 'desc';
+					} else {
+						this.groupList[this.groupIndex].sort = 'asc';
+					}
+				}
+			}
+			this.groupIndex = index;
+			this.loadList(true);
+		}
+	}
+};
+</script>
+
+<style>
+.search {
+	margin: auto;
+	padding: 0 30upx;
+	width: 690upx;
+	height: 90upx;
+	background: #da5650;
+	display: flex;
+	align-items: center;
+}
+
+.search .b-input {
+	padding: 0 20upx;
+	flex: 1;
+	height: 70upx;
+	background: #fff;
+	border-radius: 10upx;
+	display: flex;
+	align-items: center;
+}
+
+.search .b-input .s-input {
+	flex: 1;
+	color: #333;
+	font-size: 26upx;
+}
+
+.search .b-input .s-submit {
+	margin-left: 20upx;
+	color: #c3c3c3;
+	font-size: 40upx;
+}
+
+.category-list {
+	background: #fff;
+}
+
+.category-list .b-row {
+	padding: 0 30upx;
+	display: flex;
+	border-bottom: 2upx solid #eee;
+}
+
+.category-list .b-all {
+	padding: 20upx 0;
+	font-size: 28upx;
+}
+
+.category-list .b-all.f-active {
+	font-weight: bold;
+}
+
+.category-list .b-items {
+	margin-left: 20upx;
+	flex: 1;
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.category-list .b-items .s-item {
+	padding: 20upx 20upx;
+	font-size: 28upx;
+}
+
+.category-list .b-items .s-item.f-active {
+	font-weight: bold;
+}
+
+.filter-box {
+	background: #fff;
+	display: flex;
+	align-items: center;
+}
+
+.filter-box .b-item {
+	padding: 20upx 30upx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	font-size: 28upx;
+}
+
+.filter-box .b-item.f-active {
+	font-weight: bold;
+}
+
+.filter-box .b-item .s-tit {
+	color: #333;
+}
+
+.filter-box .b-item .iconfont {
+	color: #999;
+	font-size: 28upx;
+	margin-left: 10upx;
+}
+
+.course-list {
+	margin-top: 30upx;
+}
+
+.course-list .course-item {
+	border-bottom: 1upx solid #eee;
+}
+
+.course-list .course-item:last-child {
+	border-bottom: none;
+}
+</style>

+ 726 - 0
pages/index/index.vue

@@ -0,0 +1,726 @@
+<template>
+	<view class="">
+		<view class="box">
+			<view class="nabBar">
+				<u-navbar @leftClick="leftClick" title="首页" :placeholder="true" bgColor="rgba(255,255,255,0)" :leftIconSize="0" titleStyle="font-weight:bold;color:#7a5831">
+					<view class="u-nav-slot" slot="left">
+						<text>切换城市</text>
+						<uni-icons type="tune" size="20"></uni-icons>
+					</view>
+				</u-navbar>
+				<!-- <view class="" style="position: absolute; top: 55rpx; left: 40rpx">
+				<text>切换城市</text>
+				<uni-icons type="tune" size="20"></uni-icons>
+			</view> -->
+			</view>
+			<view class="group_1">
+				<view class="group_25 banxin2">
+					<u-swiper
+						:list="mn_swiperList"
+						imgMode="aspectFill"
+						:height="120"
+						:indicator="true"
+						:autoplay="true"
+						:circular="true"
+						indicatorStyle="bottom: 10px"
+						@click="bannerClick"
+						indicatorMode="dot"
+						indicatorActiveColor="#fff"
+						indicatorInactiveColor="rgba(255, 255, 255, 0.35)"
+					></u-swiper>
+				</view>
+			</view>
+			<template>
+				<view></view>
+			</template>
+
+			<view class="block_8">
+				<view @click="moreBtn" class="an" style="margin-top: 25rpx">
+					<u-notice-bar text="系统消息提示"></u-notice-bar>
+				</view>
+
+				<view class="text-wrapper_17">
+					<text lines="1" class="text_32">闽南文化推荐</text>
+					<!-- <text @click="moreBtn" lines="1" class="text_33">查看更多》</text> -->
+				</view>
+				<!-- 闽南精神 -->
+				<view class="group_js">
+					<view class="box_js" @click="jingshenBtn">
+						<image class="box_19_js" src="https://p9.itc.cn/q_70/images03/20210721/23bcf2d618cb4f8a941eccd923294e78.png"></image>
+						<view class="image-text_js">
+							<image src="https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_js.png" class="image_js"></image>
+							<text lines="1" class="text-group_js">闽南精神</text>
+						</view>
+					</view>
+				</view>
+				<view class="grid_2">
+					<view class="group_23" @click="jianzhuBtn">
+						<view class="box_19">
+							<image class="box_19_img" src="https://img1.baidu.com/it/u=2349874273,3785455421&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=400"></image>
+							<view class="image-text_13">
+								<image src="/static/image/2019-07-03000000000018.png" class="image_20"></image>
+								<text lines="1" class="text-group_10">建筑文化</text>
+							</view>
+						</view>
+					</view>
+					<view class="group_24" @click="minsuBtn">
+						<view class="box_19">
+							<image class="box_19_img" src="https://img1.baidu.com/it/u=2977394516,3415116795&fm=253&fmt=auto&app=138&f=JPEG?w=641&h=361"></image>
+							<view class="image-text_13">
+								<image src="/static/image/传统吉祥纹样17.png" class="image_20"></image>
+								<text lines="1" class="text-group_10">民俗宗教</text>
+							</view>
+						</view>
+					</view>
+					<view class="group_13" @click="feiyiBtn">
+						<view class="box_19">
+							<image class="box_19_img" src="https://img0.baidu.com/it/u=2448527499,3053317408&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=394"></image>
+							<view class="image-text_13">
+								<image src="/static/image/flower.png" class="image_20"></image>
+								<text lines="1" class="text-group_10">非遗传承</text>
+							</view>
+						</view>
+					</view>
+					<view class="group_14" @click="minyuBtn">
+						<view class="box_19">
+							<image class="box_19_img" src="https://img1.baidu.com/it/u=2717270821,618986584&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=327"></image>
+							<view class="image-text_13">
+								<image src="/static/image/BSV.png" class="image_20"></image>
+								<text lines="1" class="text-group_10">闽南语</text>
+							</view>
+						</view>
+					</view>
+
+					<view class="text-wrapper_18">
+						<text lines="1" class="text_23">精彩村史</text>
+						<text lines="1" class="text_24" @click="cs_listBtn">查看更多》</text>
+					</view>
+					<view class="cc banxin2" style="width: 100%; display: flex; justify-content: space-between">
+						<view class="" style="width: 320rpx">
+							<u-swiper height="150" :autoplay="true" circular :list="bannerlist1" previousMargin="30" nextMargin="30" radius="5" bgColor="#ffffff"></u-swiper>
+						</view>
+						<view class="" style="width: 320rpx">
+							<u-swiper
+								height="150"
+								:autoplay="true"
+								:circular="true"
+								:list="bannerlist2"
+								previousMargin="30"
+								nextMargin="30"
+								radius="5"
+								bgColor="#ffffff"
+							></u-swiper>
+						</view>
+					</view>
+					<view class="text-wrapper_18">
+						<text lines="1" class="text_23">精彩推荐</text>
+						<!-- <text lines="1" class="text_8">查看更多》</text> -->
+					</view>
+					<view class="ad" style="padding-bottom: 100rpx">
+						<view class="box_22" v-for="item in tj_List" :key="item">
+							<view class="block_5">
+								<image style="width: 100%; height: 100%; border-radius: 0 50rpx 0 20rpx" :src="item.img"></image>
+
+								<view class="tag_1">
+									<text lines="1" class="text_9">文物</text>
+								</view>
+
+								<view class="tag_2">
+									<text lines="1" class="text_10">文物精品展</text>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<mntabBar footerTab="0" :messageCount="0"></mntabBar>
+	</view>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+
+let that;
+export default {
+	components: {},
+	onLoad(option) {
+		that = this;
+		// this.getBannerList();
+	},
+	computed: {
+		...mapState(['ceShi'])
+	},
+	data() {
+		return {
+			value1: 0,
+			da: 1,
+			db: 2,
+			tj_List: [
+				{ img: 'https://t12.baidu.com/it/u=961699429,199854606&fm=30&app=106&f=JPEG?w=640&h=427&s=E2804EA45471118C54BC7E610300E070' },
+				{ img: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/shouyeTJ.png' }
+			],
+			mn_swiperList: [
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt2.png',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt1.png',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt3.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt4.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt5.png'
+			],
+
+			bannerlist1: [
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/gd.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/hk.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/hp.jpg'
+			],
+			bannerlist2: [
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sz.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/tp.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/zz.jpg'
+			]
+		};
+	},
+	/* 页面触底 */
+	onReachBottom() {
+		console.log('触底了');
+		// console.log(this.ceShi);
+	},
+	methods: {
+		// 闽南精神
+		jingshenBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/mn_jingshen/mn_jingshen'
+			});
+		},
+		leftClick() {
+			console.log('切换城市');
+		},
+		// 建筑
+		jianzhuBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/jianzhu/jianzhu'
+			});
+		},
+		// 民俗
+		minsuBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/minsu/minsu'
+			});
+		},
+		// 闽南语
+		minyuBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/minNanyu/minNanyu'
+			});
+		},
+		// 非遗
+		feiyiBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/feiyi/feiyi'
+			});
+		},
+		// 闽南文化推荐,
+		moreBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/mn_wenhua/mn_wenhua'
+			});
+		},
+
+		// 村史列表
+		cs_listBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/cs_liebiao/cs_liebiao'
+			});
+		},
+
+		getBannerList() {
+			this.$api.getBannerList({ block: 'home' }, function (res) {
+				// console.log(res);
+				if (res.code > 0) {
+					that.bannerlist = [];
+					for (var i = 0; i < res.data.length; i++) {
+						if (res.data[i].type == 'banner') {
+							that.bannerlist.push({
+								title: res.data[i].title,
+								url: that.$config.baseUrl + res.data[i].image,
+								page: res.data[i].url
+							});
+						}
+					}
+				}
+			});
+		},
+		bannerClick(index) {
+			console.log(index);
+			this.$common.navigateTo(this.bannerlist[index].page);
+		}
+	}
+};
+</script>
+
+<style>
+/deep/.u-swiper-indicator__wrapper__dot--active {
+	width: 5px !important;
+}
+.box {
+	height: auto;
+	width: 100%;
+	/* background-image: url('https://huli-app.wenlvti.net/app_static/wuyuan/static/shouhu/wyj-feiyi3-001.png'); */
+	/* background-size: 100% 100%; */
+	background-color: #f8f8f8;
+	background-attachment: fixed;
+	border-radius: 16px 16px 0 0;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+/deep/.u-icon__icon.data-v-2ee87dc9 {
+	top: 0 !important;
+	left: 5rpx !important;
+}
+
+.qh_icon {
+	position: absolute;
+	top: 0;
+	left: 0;
+}
+.banxin {
+	width: 100%;
+	height: 100rpx;
+	margin: auto;
+	/* background-color: yellowgreen; */
+}
+.banxin2 {
+	width: 90%;
+	margin: auto;
+}
+
+.u-nav-slot {
+	margin-left: 20rpx;
+}
+.nabBar {
+	/* height: 200rpx; */
+	background-image: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/shouyeBJ.png');
+	background-size: cover;
+}
+
+.group_1 {
+	width: 750rpx;
+	display: flex;
+	margin-top: 130rpx;
+	flex-direction: column;
+	justify-content: flex-end;
+}
+.group_25 {
+	margin-top: -120rpx;
+	display: flex;
+	flex-direction: column;
+}
+.image_3 {
+	width: 696rpx;
+	height: 28rpx;
+	margin: 13rpx 0 0 29rpx;
+}
+.nav-bar_4 {
+	width: 746rpx;
+	height: 81rpx;
+	margin-top: 10rpx;
+	flex-direction: row;
+	display: flex;
+}
+.group_33 {
+	height: 26rpx;
+	display: flex;
+	flex-direction: column;
+	width: 147rpx;
+	margin: 23rpx 0 0 32rpx;
+}
+.group_34 {
+	width: 147rpx;
+	height: 26rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+}
+.text_21 {
+	width: 110rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.label_5 {
+	width: 23rpx;
+	height: 23rpx;
+	margin-top: 1rpx;
+}
+.text_22 {
+	width: 68rpx;
+	height: 34rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 36rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 36rpx;
+	margin: 18rpx 0 0 143rpx;
+}
+.applet-top-bar_1 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 28rpx;
+	width: 155rpx;
+	height: 56rpx;
+	border: 1px solid rgba(241, 241, 241, 1);
+	flex-direction: row;
+	display: flex;
+	margin: 7rpx 25rpx 0 176rpx;
+}
+.image_4 {
+	width: 53rpx;
+	height: 31rpx;
+	margin: 13rpx 0 0 24rpx;
+}
+.label_1 {
+	width: 38rpx;
+	height: 38rpx;
+	margin: 9rpx 21rpx 0 19rpx;
+}
+
+.block_8 {
+	width: 750rpx;
+
+	display: flex;
+	flex-direction: column;
+}
+
+.text_1 {
+	width: 319rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(153, 153, 153, 1);
+	font-size: 24rpx;
+	font-family: PingFang-SC-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 21rpx 281rpx 0 23rpx;
+}
+.text-wrapper_17 {
+	width: 667rpx;
+	height: 34rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 35rpx 0 0 51rpx;
+}
+.text_32 {
+	width: 211rpx;
+	height: 34rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 36rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 36rpx;
+}
+.text_33 {
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 7rpx;
+}
+.grid_2 {
+	width: 687rpx;
+	height: 364rpx;
+	flex-wrap: wrap;
+	display: flex;
+	flex-direction: row;
+	margin: 27rpx 0 0 32rpx;
+}
+
+.group_js {
+	height: 166rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 20rpx 27rpx 0rpx 30rpx;
+}
+.box_js {
+	height: 166rpx;
+	position: relative;
+	display: flex;
+	flex-direction: row;
+}
+.box_19_js {
+	width: 100%;
+	height: 100%;
+	border-radius: 20rpx;
+}
+.box_19_js ::before {
+	content: '';
+	display: block;
+	position: absolute; /* 设置绝对定位 */
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	background-color: rgba(0, 0, 0, 0.2); /* 设置遮罩层颜色和透明度 */
+	z-index: 1;
+}
+.image-text_js {
+	width: 233rpx;
+	height: 102rpx;
+	position: absolute;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 35rpx 0 0 250rpx;
+	z-index: 2;
+}
+.image_js {
+	width: 75rpx;
+	height: 65rpx;
+	margin-left: 72rpx;
+}
+.text-group_js {
+	width: 233rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 228, 176, 1);
+	font-size: 28rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: center;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-top: 10rpx;
+}
+
+.group_23 {
+	height: 166rpx;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+	margin: 0 27rpx 32rpx 0;
+}
+.box_19 {
+	width: 330rpx;
+	height: 166rpx;
+	position: relative;
+	display: flex;
+	flex-direction: row;
+}
+.box_19_img {
+	width: 100%;
+	height: 100%;
+	border-radius: 20rpx;
+}
+.box_19_img ::before {
+	content: '';
+	display: block;
+	position: absolute; /* 设置绝对定位 */
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	background-color: rgba(0, 0, 0, 0.2); /* 设置遮罩层颜色和透明度 */
+	z-index: 1;
+}
+.image-text_13 {
+	width: 233rpx;
+	height: 102rpx;
+	position: absolute;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 35rpx 0 0 56rpx;
+	z-index: 2;
+}
+.image_20 {
+	width: 75rpx;
+	height: 65rpx;
+	margin-left: 72rpx;
+}
+.text-group_10 {
+	width: 233rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 228, 176, 1);
+	font-size: 28rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: center;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-top: 10rpx;
+}
+.group_24 {
+	border-radius: 20rpx;
+	height: 166rpx;
+	margin-bottom: 32rpx;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+}
+
+.text-group_11 {
+	width: 110rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 228, 176, 1);
+	font-size: 28rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: center;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-top: 10rpx;
+}
+.group_13 {
+	border-radius: 20rpx;
+	width: 330rpx;
+	height: 166rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 0 27rpx 32rpx 0;
+}
+
+.group_14 {
+	border-radius: 20rpx;
+	height: 166rpx;
+	margin-bottom: 32rpx;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+}
+
+.image-text_15 {
+	width: 193rpx;
+	height: 116rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 20rpx 0 0 68rpx;
+}
+.image_23 {
+	width: 93rpx;
+	height: 83rpx;
+	margin-left: 51rpx;
+}
+.text-group_6 {
+	width: 193rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 228, 176, 1);
+	font-size: 28rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: center;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-top: 6rpx;
+}
+.text-wrapper_18 {
+	width: 669rpx;
+	height: 34rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin-top: 45rpx;
+	margin-bottom: 40rpx;
+}
+.text_23 {
+	width: 142rpx;
+	height: 34rpx;
+	color: #312520;
+	font-size: 36rpx;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 36rpx;
+}
+.text_24 {
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 7rpx;
+}
+
+.text_8 {
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 7rpx;
+}
+.box_22 {
+	height: 345rpx;
+	display: flex;
+	flex-direction: column;
+	width: 686rpx;
+	margin-bottom: 50rpx;
+}
+.block_5 {
+	position: relative;
+	height: 345rpx;
+	width: 686rpx;
+	display: flex;
+	flex-direction: column;
+}
+
+.tag_1 {
+	position: absolute;
+	background-color: rgba(77, 113, 153, 1);
+	border-radius: 9rpx 9rpx 32rpx 0rpx;
+	height: 48rpx;
+	display: flex;
+	flex-direction: column;
+	width: 86rpx;
+}
+.tag_2 {
+	position: absolute;
+	bottom: 36rpx;
+	right: 20rpx;
+}
+.text_9 {
+	width: 47rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 12rpx 0 0 19rpx;
+}
+.text-wrapper_20 {
+	width: 147rpx;
+	height: 29rpx;
+	display: flex;
+	flex-direction: row;
+	margin: 232rpx 0 36rpx 518rpx;
+}
+.text_10 {
+	width: 147rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 30rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+}
+</style>

+ 362 - 0
pages/jiyi/jiyi.vue

@@ -0,0 +1,362 @@
+<template>
+	<view class="">
+		<view class="box">
+			<view class="nabBar" style="background-image: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/jiyi_zxc.png'); background-size: cover">
+				<u-navbar title="记忆" bgColor="rgba(255,255,255,0)" :placeholder="true" :leftIconSize="0" titleStyle="font-weight:bold;color:#7a5831"></u-navbar>
+			</view>
+
+			<view class="box_15">
+				<u-swiper previousMargin="40" nextMargin="40" :autoplay="true" showTitle :height="150" :list="bannerlist" :circular="true" radius="5" bgColor="#ffffff"></u-swiper>
+			</view>
+			<view class="box_1">
+				<view class="box_20">
+					<view class="block_9">
+						<button bindtap="onClick" class="button_1">
+							<text lines="1" class="text_1">城市记忆</text>
+						</button>
+						<button bindtap="onClick" class="button_2" @click="cunShiBtn">
+							<text lines="1" class="text_2">村史馆</text>
+						</button>
+					</view>
+					<view class="block_10">
+						<button bindtap="onClick" class="button_3">
+							<text lines="1" class="text_3">区史馆</text>
+						</button>
+						<button bindtap="onClick" class="button_5">
+							<text lines="1" class="text_4">校史馆</text>
+						</button>
+						<button bindtap="onClick" class="button_4">
+							<text lines="1" class="text_5">医史馆</text>
+						</button>
+					</view>
+
+					<view class="text-wrapper_4">
+						<text lines="1" class="text_6">经典推荐</text>
+
+						<!-- <text lines="1" class="text_7">查看更多》</text> -->
+					</view>
+					<!-- 瀑布流 -->
+
+					<custom-waterfalls-flow :value="list" style="width: 90%; margin: auto">
+						<view class="item" style="position: relative" v-for="(item, index) in list" :key="index" slot="slot{{index}}">
+							<view class="title_pubu">
+								{{ item.title }}
+							</view>
+							<!-- <view class="desc">{{ item.desc }}</view> -->
+						</view>
+					</custom-waterfalls-flow>
+				</view>
+			</view>
+		</view>
+
+		<mntabBar footerTab="1" :messageCount="0"></mntabBar>
+	</view>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+let that;
+export default {
+	data() {
+		return {
+			bannerlist: [
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt2.png',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt1.png',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt3.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt4.jpg',
+				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt5.png'
+			],
+			list: [
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy1.png',
+					title: '传统捏泥人',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy2.png',
+					title: '青龙宫',
+					desc: '描述描述描述描述描述描述描述描述1'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy3.png',
+					title: '火把节',
+					desc: '11'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy9.png',
+					title: '老物件',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy4.png',
+					title: '林后青龙宫',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy10.png',
+					title: '书籍',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy7.png',
+					title: '建筑',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy8.png',
+					title: '老钟表',
+					desc: '描述描述描述描述描述描述描述描述2'
+				},
+
+				{
+					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy14.png',
+					title: '老物件',
+					desc: '描述描述描述描述描述描述描述描述2'
+				}
+			]
+		};
+	},
+	onLoad(option) {
+		that = this;
+		// this.getBannerList();
+	},
+	computed: {
+		...mapState(['ceShi'])
+	},
+	methods: {
+		cunShiBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/cs_liebiao/cs_liebiao'
+			});
+		},
+		getBannerList() {
+			this.$api.getBannerList({ block: 'home' }, function (res) {
+				// console.log(res);
+				if (res.code > 0) {
+					that.bannerlist = [];
+					for (var i = 0; i < res.data.length; i++) {
+						if (res.data[i].type == 'banner') {
+							that.bannerlist.push({
+								title: res.data[i].title,
+								url: that.$config.baseUrl + res.data[i].image,
+								page: res.data[i].url
+							});
+						}
+					}
+				}
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.box {
+	height: auto;
+	width: 100%;
+	/* background-image: url('https://huli-app.wenlvti.net/app_static/wuyuan/static/shouhu/wyj-feiyi3-001.png'); */
+	/* background-size: 100% 100%; */
+	background-attachment: fixed;
+	border-radius: 16px 16px 0 0;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+.nabBar {
+	height: 340rpx;
+}
+.u-swiper.data-v-6b019429 {
+	background-color: rgba(0, 0, 0, 0) !important;
+}
+/deep/.column-value.data-v-ddfcbb1c {
+	border-radius: 25rpx 60rpx 0rpx 30rpx !important;
+}
+.box_1 {
+	position: relative;
+	width: 750rpx;
+	flex-direction: row;
+	display: flex;
+}
+.title_pubu {
+	width: 100%;
+	height: 65rpx;
+	line-height: 65rpx;
+	background-color: #ca5642;
+	font-size: 30rpx;
+	text-align: center;
+	color: #ffffff;
+	position: absolute;
+	bottom: 0;
+	left: 0;
+}
+.box_20 {
+	position: relative;
+	width: 750rpx;
+
+	display: flex;
+	flex-direction: column;
+}
+.block_9 {
+	width: 684rpx;
+	height: 67rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: auto;
+}
+.button_1 {
+	background-color: rgba(22, 69, 89, 1);
+	border-radius: 33rpx;
+	height: 67rpx;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+	position: relative;
+}
+.text_1 {
+	color: rgba(255, 255, 255, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	text-align: center;
+	line-height: 60rpx;
+}
+.image_1 {
+	position: absolute;
+	left: 0rpx;
+	top: 0rpx;
+	width: 330rpx;
+	height: 67rpx;
+}
+.button_2 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 33rpx;
+	height: 67rpx;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+	position: relative;
+}
+.text_2 {
+	color: rgba(255, 255, 255, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	text-align: center;
+	line-height: 60rpx;
+}
+
+.block_10 {
+	width: 691rpx;
+	height: 67rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 31rpx 0 0 32rpx;
+}
+.button_3 {
+	background: #c3a07b;
+	border-radius: 33rpx;
+	height: 67rpx;
+	display: flex;
+	flex-direction: column;
+	width: 212rpx;
+	position: relative;
+}
+.button_5 {
+	background: #5c987b;
+	border-radius: 33rpx;
+	height: 67rpx;
+	display: flex;
+	flex-direction: column;
+	width: 212rpx;
+	position: relative;
+}
+.text_3 {
+	color: rgba(255, 255, 255, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	text-align: center;
+	line-height: 60rpx;
+}
+
+.text-wrapper_1 {
+	background-color: rgba(197, 186, 165, 1);
+	border-radius: 33rpx;
+	height: 67rpx;
+	margin-left: 24rpx;
+	display: flex;
+	flex-direction: column;
+	width: 212rpx;
+}
+.text_4 {
+	color: rgba(255, 255, 255, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	text-align: center;
+	line-height: 60rpx;
+}
+.button_4 {
+	background-color: rgba(91, 84, 84, 1);
+	border-radius: 33rpx;
+	height: 67rpx;
+
+	display: flex;
+	flex-direction: column;
+	width: 212rpx;
+	position: relative;
+}
+.text_5 {
+	color: rgba(255, 255, 255, 1);
+	font-size: 28rpx;
+	font-weight: 700;
+	text-align: center;
+	line-height: 60rpx;
+}
+
+.text-wrapper_4 {
+	width: 668rpx;
+	height: 34rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 33rpx 0 25rpx 49rpx;
+}
+.text_6 {
+	width: 144rpx;
+	height: 34rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 36rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 36rpx;
+}
+.text_7 {
+	width: 107rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-top: 5rpx;
+}
+
+.box_15 {
+	margin-top: -160rpx;
+	margin-left: 32rpx;
+	margin-right: 32rpx;
+	border-radius: 20rpx;
+	padding: 20rpx;
+	height: 360rpx;
+	background-color: #ffe4b0;
+	display: flex;
+	margin-bottom: 35rpx;
+	box-sizing: border-box;
+	flex-direction: column;
+}
+</style>

+ 369 - 0
pages/order/preview.vue

@@ -0,0 +1,369 @@
+<template>
+	<view class="wrap">
+		<u-navbar :autoBack="true" title="购买课程" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="main" v-if="hasLoad">
+			<view class="gift-head">商品信息</view>
+			<view class="gift-list">
+				<view class="gift-item" v-for="(item, index) in orderData.goods_list" :key="index">
+					<view class="b-left">
+						<image :src="item.goods_cover" mode="aspectFill"></image>
+					</view>
+					<view class="b-main">
+						<view class="b-title">{{ item.goods_name }}</view>
+						<view class="b-spec">
+							<!-- <view class="s-tit">类型:</view> -->
+							<view class="s-value">{{ item.goods_type_text }}</view>
+						</view>
+						<view class="b-fund">
+							<view class="s-num">¥{{ item.payment }}</view>
+							<view class="s-worth">¥{{ item.goods_price }}</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="box">
+				<view class="b-row f-fund">
+					<view class="b-tit">商品总价:</view>
+					<view class="b-cont">
+						<view class="s-num">¥{{ orderData.total_price }}</view>
+					</view>
+				</view>
+				<view class="b-row f-fund">
+					<view class="b-tit">优惠金额:</view>
+					<view class="b-cont">
+						<view class="s-num">¥{{ orderData.total_discount }}</view>
+					</view>
+				</view>
+				<view class="b-row f-fund">
+					<view class="b-tit">应付金额:</view>
+					<view class="b-cont">
+						<view class="s-num">¥{{ orderData.total_payment }}</view>
+					</view>
+				</view>
+			</view>
+			<view class="box">
+				<radio-group @change="onRadioChange" v-for="(item, index) in payList" :key="index">
+					<view class="b-row f-pay">
+						<view class="b-tit">
+							<view class="iconfont" :class="'icon-' + item.icon"></view>
+							<view class="s-tit">{{ item.name }}</view>
+						</view>
+						<view class="b-cont">
+							<radio value="wechat" :checked="item.checked" color="#DA5650" />
+						</view>
+					</view>
+				</radio-group>
+			</view>
+			<view class="navbar">
+				<view class="b-amount">
+					<view class="s-tit">应付:</view>
+					<view class="s-num">¥{{ orderData.total_payment }}</view>
+				</view>
+				<view class="b-action">
+					<view class="s-exchange" @click="onSubmitOrder">确认下单</view>
+				</view>
+			</view>
+		</view>
+		<!-- 加载中 -->
+		<load-more :loadingType="loadingType" :loadingText="loadingText" :top="300"></load-more>
+		<!-- 首页 -->
+		<app-home></app-home>
+	</view>
+</template>
+
+<script>
+// import { removeCart, previewOrder, submitOrder, oncePay } from '@/service/api/order.js';
+// import { requestPayment } from '@/service/request/main.js';
+import mixinsCommon from '@/mixins/common.js';
+import mixinsAuth from '@/mixins/auth.js';
+let that;
+export default {
+	mixins: [mixinsCommon, mixinsAuth],
+	data() {
+		return {
+			disable: {
+				submit: false
+			},
+			orderData: {},
+			formData: {
+				goods_list: [],
+				total_price: 0,
+				total_payment: 0
+			},
+			payList: [
+				{
+					icon: 'pay-wechat',
+					alias: 'wechat',
+					name: '微信支付',
+					checked: true
+				}
+			],
+			payIndex: 0,
+			hasLoad: false,
+			loadingType: 1,
+			loadingText: ''
+		};
+	},
+	onLoad(options) {
+		that = this;
+		let goodsData = options.goods_data;
+		this.goodsData = JSON.parse(goodsData);
+		this.loadPreview();
+	},
+	methods: {
+		loadPreview() {
+			this.$api.previewOrder({ goods_list: this.goodsData }, function (res) {
+				console.log('加入购物车', res);
+				if (res.code == 1) {
+					that.hasLoad = true;
+					that.loadingType = -1;
+					that.orderData = res.data;
+					that.formData.goods_list = res.data.goods_list;
+					that.formData.total_price = res.data.total_price;
+					that.formData.total_payment = res.data.total_payment;
+				} else {
+					that.loadingType = 3;
+					that.loadingText = err.data.msg || '加载失败';
+				}
+			});
+
+			// previewOrder({
+			// 	goods_list: this.goodsData
+			// }).then(([err, res]) => {
+			// 	console.log('previewOrder', err, res);
+			// 	if (!err) {
+			// 		this.hasLoad = true;
+			// 		this.loadingType = -1;
+			// 		this.orderData = res;
+			// 		this.formData.goods_list = res.goods_list;
+			// 		this.formData.total_price = res.total_price;
+			// 		this.formData.total_payment = res.total_payment;
+			// 	} else {
+			// 		this.loadingType = 3;
+			// 		this.loadingText = err.data.msg || '加载失败';
+			// 	}
+			// });
+		},
+		onRadioChange(e) {
+			console.log('onRadioChange', e);
+		},
+		onSubmitOrder() {
+			if (this.disable.submit) {
+				return;
+			}
+			this.disable.submit = true;
+
+			this.$api.submitOrder({}, function () {
+				console.log('888', res);
+				that.disable.submit = false;
+				if (res.code == 1) {
+					for (let i = 0; i < this.goodsData.length; i++) {
+						let goodsData = this.goodsData[i];
+						if (goodsData.cart_id) {
+							this.$api.removeCart({}, function (res) {
+								console.log('999', res);
+								if (res.code == 1) {
+									this.$store.commit('delCartItem', goodsData.cart_id);
+								}
+							});
+
+							// removeCart(goodsData.cart_id).then(([err, res]) => {
+							// 	if (!err) {
+							// 		this.$store.commit('delCartItem', goodsData.cart_id);
+							// 	}
+							// });
+						}
+					}
+					requestPayment(res.order_no, this.payList[this.payIndex].alias, 'onceOrder');
+				}
+			});
+
+			// submitOrder(this.formData).then(([err, res]) => {
+			// 	console.log('submitOrder', err, res);
+			// 	this.disable.submit = false;
+			// 	if (!err) {
+			// 		for (let i = 0; i < this.goodsData.length; i++) {
+			// 			let goodsData = this.goodsData[i];
+			// 			if (goodsData.cart_id) {
+			// 				removeCart(goodsData.cart_id).then(([err, res]) => {
+			// 					if (!err) {
+			// 						this.$store.commit('delCartItem', goodsData.cart_id);
+			// 					}
+			// 				});
+			// 			}
+			// 		}
+			// 		requestPayment(res.order_no, this.payList[this.payIndex].alias, 'onceOrder');
+			// 	}
+			// });
+		}
+	}
+};
+</script>
+
+<style>
+.wrap {
+	padding-bottom: 150upx;
+}
+
+.gift-head {
+	padding: 20upx 30upx;
+	font-size: 28upx;
+	color: #333;
+}
+
+.gift-item {
+	padding: 30upx;
+	background: #fff;
+	border-bottom: 2upx solid #eee;
+	display: flex;
+	align-items: center;
+}
+
+.gift-item .b-left {
+	width: 160upx;
+	height: 160upx;
+}
+
+.gift-item .b-left image {
+	width: 160upx;
+	height: 160upx;
+}
+
+.gift-item .b-main {
+	margin-left: 30upx;
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+}
+
+.gift-item .b-main .b-title {
+	font-size: 28upx;
+	color: #333;
+}
+
+.gift-item .b-main .b-spec {
+	margin-top: 20upx;
+	display: flex;
+	align-items: center;
+}
+
+.gift-item .b-main .b-spec .s-tit {
+	margin-right: 10upx;
+	font-size: 24upx;
+	color: #999;
+}
+
+.gift-item .b-main .b-spec .s-value {
+	font-size: 24upx;
+	color: #666;
+}
+
+.gift-item .b-main .b-fund {
+	margin-top: 20upx;
+	display: flex;
+	align-items: baseline;
+}
+
+.gift-item .b-main .b-fund .s-num {
+	font-size: 32upx;
+	color: #da5650;
+}
+
+.gift-item .b-main .b-fund .s-worth {
+	margin-left: 20upx;
+	font-size: 26upx;
+	color: #999;
+	text-decoration: line-through;
+}
+
+.box {
+	margin-top: 30upx;
+	padding: 30upx;
+	background: #fff;
+}
+
+.box .b-row {
+	margin-bottom: 30upx;
+	display: flex;
+	justify-content: space-between;
+}
+
+.box .b-row:last-child {
+	margin-bottom: 0;
+}
+
+.box .b-row.f-fund .b-cont .s-num {
+	font-size: 32upx;
+	color: #da5650;
+}
+
+.box .b-row.f-pay .b-tit {
+	width: 320upx;
+	display: flex;
+	align-items: center;
+}
+
+.box .b-row.f-pay .b-tit .iconfont {
+	font-size: 50upx;
+	color: #6cb37a;
+}
+
+.box .b-row.f-pay .b-tit .s-tit {
+	margin-left: 10upx;
+	font-size: 28upx;
+}
+
+.box .b-row.f-pay .b-cont radio {
+	transform: scale(0.8);
+}
+
+.box .b-row .b-tit {
+	font-size: 28upx;
+	width: 160upx;
+}
+
+.box .b-row .b-cont {
+	display: flex;
+	align-items: center;
+}
+
+.navbar {
+	position: fixed;
+	left: 0;
+	bottom: 0;
+	width: 100%;
+	height: 100upx;
+	background: #fff;
+	border-top: 1upx solid #f6f6f6;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.navbar .b-amount {
+	margin-left: 30upx;
+	display: flex;
+	align-items: center;
+}
+
+.navbar .b-amount .s-tit {
+	font-size: 28upx;
+	color: #333;
+}
+
+.navbar .b-amount .s-num {
+	margin-left: 10upx;
+	font-size: 32upx;
+	color: #da5650;
+}
+
+.navbar .b-action .s-exchange {
+	background: #da5650;
+	height: 100upx;
+	padding: 0 60upx;
+	line-height: 100upx;
+	font-size: 30upx;
+	color: #fff;
+	letter-spacing: 4upx;
+}
+</style>

+ 698 - 0
pages/schedule/detail.vue

@@ -0,0 +1,698 @@
+<template>
+	<view class="wrap">
+		<u-navbar :autoBack="true" title="培训详情" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="main" v-if="hasLoad">
+			<view class="b-photos">
+				<swiper indicator-dots circular="true" duration="400">
+					<swiper-item class="swiper-item" v-for="(item, index) in state.photo_list" :key="index">
+						<view class="image-wrapper" @click="onPreviewPhoto(index)">
+							<image :src="item.url" mode="aspectFill"></image>
+						</view>
+					</swiper-item>
+				</swiper>
+			</view>
+			<view class="b-slide">
+				<view class="b-item" :class="{ 'f-active': showContent === 'detail' }" @click="onContentSwitch('detail')">介绍</view>
+				<view class="b-item" :class="{ 'f-active': showContent === 'course' }" @click="onContentSwitch('course')">课程</view>
+				<view class="b-item" :class="{ 'f-active': showContent === 'examine' }" @click="onContentSwitch('examine')" v-if="state.has_examine">考核</view>
+			</view>
+			<view class="content-list" v-show="showContent === 'course'">
+				<view class="course-item" v-for="(item, index) in state.course_list" :key="index" :class="{ 'f-active': courseIndex == index }">
+					<view class="b-main">
+						<view class="b-name too-long">第{{ index + 1 }}课 {{ item.name }}</view>
+						<view class="b-percent">
+							<view class="b-line" v-if="state.auth_state == 3">
+								<view class="s-num" :style="'width:' + item.learn_percent + '%'"></view>
+							</view>
+							<view class="b-info">
+								<view class="s-time">{{ item.need_length }}课时</view>
+								<view class="s-percent" v-if="state.auth_state == 3">已学{{ item.learn_percent }}%</view>
+							</view>
+						</view>
+					</view>
+					<view class="b-play" @click="onJumpCourse(item.id)">
+						<view class="iconfont icon-video"></view>
+						<view class="b-state" v-if="state.auth_state != 3">查看详情</view>
+						<view class="b-state" v-else>{{ item.learn_percent > 0 ? '继续学习' : '开始学习' }}</view>
+					</view>
+				</view>
+			</view>
+			<view class="course-detail" v-show="showContent === 'detail'">
+				<view class="info">
+					<view class="b-title">{{ state.name }}</view>
+					<view class="b-main">
+						<view class="b-price">
+							<view class="s-payment" :class="{ 'f-small': textCost }">{{ goodsPrice(state.price) }}</view>
+							<!-- <view class="s-vip-price" v-if="state.card_price > 0 && !iphonePlatform">会员价 ¥{{ state.card_price }}</view>
+							<view class="s-vip-free" v-if="state.vip_free">会员免费</view> -->
+						</view>
+						<view class="b-opt">
+							<view class="s-btn f-like" @click="onHandleLike()">
+								<view class="f-yes iconfont icon-like-yes" v-if="state.is_like"></view>
+								<view class="f-no iconfont icon-like-no" v-else></view>
+							</view>
+							<button class="s-btn f-shar open-data-btn" open-type="share">
+								<view class="iconfont icon-share"></view>
+							</button>
+							<!-- <view class="s-btn f-share">
+								<view class="iconfont icon-share"></view>
+							</view> -->
+						</view>
+					</view>
+					<view class="b-info">
+						<view class="s-worth">{{ state.category_name }}</view>
+						<view class="s-count">
+							<view class="s-left">{{ state.count_user }}人参加</view>
+							<view class="s-gain">{{ state.count_like }}人收藏</view>
+						</view>
+					</view>
+				</view>
+				<view class="content">
+					<view class="b-title">
+						<view class="xiant"></view>
+						<view class="s-tit">培训详情</view>
+						<view class="xiant"></view>
+					</view>
+					<view class="b-rich">
+						<rich-text :nodes="state.content"></rich-text>
+					</view>
+				</view>
+			</view>
+			<view class="course-examine" v-show="showContent === 'examine'">
+				<view class="examine-list" v-if="examineList.length > 0">
+					<examine-item v-for="(item, index) in examineList" :key="index" :item="item"></examine-item>
+				</view>
+			</view>
+			<view class="navbar" v-if="state.auth_state != 3">
+				<view class="b-main">
+					<view class="b-amount">
+						<!-- <view class="s-tit"></view> -->
+						<view class="s-num" :class="{ 'f-small': textCost }">{{ goodsPrice(state.price) }}</view>
+					</view>
+				</view>
+				<view class="b-action" v-if="state.auth_state == 0">
+					<view class="b-btn f-mute" v-if="iphonePlatform">根据相关规定,iOS不支持购买</view>
+					<template v-else>
+						<view class="b-btn f-cart" @click="onAddCart()">加入购物车</view>
+						<view class="b-btn f-order" @click="onPreviewOrder()">立即购买</view>
+					</template>
+				</view>
+				<view class="b-action" v-else-if="state.auth_state == 1">
+					<view class="b-btn f-learn" @click="onStartLearn()">开始学习</view>
+				</view>
+				<view class="b-action" v-else-if="state.auth_state == 2">
+					<view class="b-btn f-learn" @click="onStartLearn()">VIP免费</view>
+				</view>
+			</view>
+		</view>
+		<!-- 加载中 -->
+		<load-more :loadingType="loadingType" :loadingText="loadingText" :top="300"></load-more>
+		<!-- 快捷购物车 -->
+		<quick-cart :show="showCart" @close="onCloseCart()"></quick-cart>
+		<!-- 首页 -->
+		<app-home></app-home>
+	</view>
+</template>
+
+<script>
+// import { startLearn, handleLike, getScheduleDetail, getScheduleExamine } from '@/service/api/schedule.js';
+// import { addCart } from '@/service/api/order.js';
+import mixinsGoods from '@/mixins/goods.js';
+import mixinsCommon from '@/mixins/common.js';
+let that;
+export default {
+	mixins: [mixinsCommon, mixinsGoods],
+	data() {
+		return {
+			state: null,
+			examineList: [],
+			courseIndex: -1,
+			showContent: 'detail',
+			showCart: false,
+			hasLoad: false,
+			loadingType: 1,
+			loadingText: ''
+		};
+	},
+	onLoad(options) {
+		that = this;
+		this.scheduleId = options.sid;
+		this.loadDetail();
+	},
+	computed: {
+		orderPayment() {
+			return this.state.card_auth && this.state.card_price ? this.state.card_price : this.state.price;
+		}
+	},
+	onShareAppMessage(res) {
+		console.log('onShareAppMessage', res);
+		if (res.from === 'button') {
+			// 来自页面内分享按钮
+			console.log(res.target);
+		}
+		return {
+			title: this.state.name,
+			path: '/pages/schedule/detail?cid=' + this.scheduleId,
+			imageUrl: this.state.photo_list[0]['url']
+		};
+	},
+	methods: {
+		// 培训课程详情
+		loadDetail() {
+			this.$api.getScheduleDetail({ id: this.scheduleId }, function (res) {
+				console.log('5656', res);
+				if (res.code == 1) {
+					if (!that.hasLoad) {
+						if (res.data.auth_state == 3) {
+							that.showContent = 'course';
+						}
+					}
+					that.hasLoad = true;
+					that.loadingType = -1;
+					that.state = res.data;
+					if (res.data.has_examine) {
+						that.loadExamine();
+					}
+					uni.setNavigationBarTitle({
+						title: res.data.name
+					});
+				} else {
+					that.loadingType = 3;
+					that.loadingText = '加载失败';
+				}
+			});
+			// getScheduleDetail(this.scheduleId).then(([err, res]) => {
+			// 	console.log('getScheduleDetail', err, res);
+			// 	if (!err) {
+			// 		if (!this.hasLoad) {
+			// 			if (res.auth_state == 3) {
+			// 				this.showContent = 'course';
+			// 			}
+			// 		}
+			// 		this.hasLoad = true;
+			// 		this.loadingType = -1;
+			// 		this.state = res;
+			// 		if (res.has_examine) {
+			// 			this.loadExamine();
+			// 		}
+			// 		uni.setNavigationBarTitle({
+			// 			title: res.name
+			// 		});
+			// 	} else {
+			// 		this.loadingType = 3;
+			// 		this.loadingText = err.data.msg || '加载失败';
+			// 	}
+			// });
+		},
+		loadExamine() {
+			getScheduleExamine(this.scheduleId).then(([err, res]) => {
+				console.log('getScheduleExamine', err, res);
+				if (!err) {
+					this.examineList = res;
+				}
+			});
+		},
+		onContentSwitch(type) {
+			this.showContent = type;
+		},
+		onPreviewPhoto(index) {
+			let photos = [];
+			for (let i = 0; i < this.state.photo_list.length; i++) {
+				photos.push(this.state.photo_list[i].url);
+			}
+			uni.previewImage({
+				current: index,
+				urls: photos
+			});
+		},
+		onJumpHome() {
+			uni.switchTab({
+				url: '/pages/home/index'
+			});
+		},
+		onJumpCourse(id) {
+			uni.navigateTo({
+				url: '/pages/course/detail?cid=' + id
+			});
+		},
+		onHandleLike() {
+			if (!this.checkLogin()) {
+				return;
+			}
+			var action = this.state.is_like ? 'no' : 'yes';
+			handleLike(this.scheduleId, action).then(([err, res]) => {
+				console.log('handleLike', err, res);
+				if (!err) {
+					if (action === 'yes') {
+						this.state.is_like = 1;
+					} else {
+						this.state.is_like = 0;
+					}
+					this.$logic.showToast('操作成功');
+				}
+			});
+		},
+		onCloseCart() {
+			this.showCart = false;
+		},
+		onAddCart() {
+			// if (!this.checkLogin()) {
+			// 	return;
+			// }
+			addCart('schedule', this.scheduleId).then(([err, res]) => {
+				console.log('addCart', err, res);
+				if (!err) {
+					this.$store.commit('addCartItem', {
+						goods_id: this.scheduleId,
+						goods_type: 'schedule',
+						goods_name: this.state.name,
+						goods_cover: this.state.cover_url,
+						goods_price: this.state.price
+					});
+					this.showCart = true;
+					setTimeout(() => {
+						this.showCart = false;
+					}, 5000);
+				}
+			});
+		},
+		onPreviewOrder() {
+			if (!this.checkLogin()) {
+				return;
+			}
+			let goodsData = [
+				{
+					goods_type: 'schedule',
+					goods_id: this.scheduleId
+				}
+			];
+			uni.navigateTo({
+				url: '/pages/order/preview?goods_data=' + JSON.stringify(goodsData)
+			});
+		},
+		onStartLearn() {
+			// if (!this.checkLogin()) {
+			// 	return;
+			// }
+			this.$api.scheduleStartLearn({ id: this.scheduleId }, function (res) {
+				console.log('startLearn', res);
+				if (res.code == 1) {
+					that.$logic.showToast('开通成功,可以开始学习了');
+					that.loadDetail();
+				}
+			});
+			// startLearn(this.scheduleId).then(([err, res]) => {
+			// 	console.log('startLearn', err, res);
+			// 	if (!err) {
+			// 		this.$logic.showToast('开通成功,可以开始学习了');
+			// 		this.loadDetail();
+			// 	}
+			// });
+		},
+		onContinueLearn() {
+			this.showContent = 'course';
+			if (this.state.recent_data) {
+				for (let i = 0; i < this.state.course_list.length; i++) {
+					if (this.state.course_list[i].id == this.state.recent_data.course_id) {
+						this.courseIndex = i;
+						break;
+					}
+				}
+				if (this.courseIndex == -1) {
+					this.courseIndex = 0;
+				}
+			} else {
+				this.courseIndex = 0;
+			}
+		}
+	}
+};
+</script>
+
+<style>
+.xiant {
+	width: 60rpx;
+	height: 3rpx;
+	background-color: #dddedd;
+}
+.wrap {
+	padding-bottom: 150upx;
+}
+
+.b-photos {
+	position: relative;
+	width: 750upx;
+	height: 500upx;
+}
+
+.b-photos swiper {
+	height: 100%;
+}
+
+.b-photos .swiper-item {
+	display: flex;
+	justify-content: center;
+	align-content: center;
+	height: 320upx;
+	overflow: hidden;
+}
+
+.b-photos .swiper-item image {
+	width: 100%;
+	height: 100%;
+}
+
+.b-photos .image-wrapper {
+	width: 100%;
+	height: 100%;
+}
+
+.b-slide {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	background: #fff;
+	border-bottom: 2upx solid #eee;
+}
+
+.b-slide .b-item {
+	flex: 1;
+	height: 80upx;
+	line-height: 80upx;
+	font-size: 28upx;
+	text-align: center;
+}
+
+.b-slide .b-item.f-active {
+	height: 76upx;
+	line-height: 80upx;
+	font-weight: bold;
+	border-bottom: 4upx solid #da5650;
+}
+
+.info {
+	padding: 30upx;
+	background: #fff;
+}
+
+.info .b-title {
+	font-size: 30upx;
+	color: #333;
+}
+
+.info .b-main {
+	margin-top: 20upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.info .b-main .b-price {
+	display: flex;
+	align-items: center;
+}
+
+.info .b-main .b-price .s-payment {
+	margin-right: 20upx;
+	font-size: 36upx;
+	font-weight: bold;
+	color: #dd524d;
+}
+
+.info .b-main .b-price .s-payment.f-small {
+	font-size: 28upx;
+}
+
+.info .b-main .b-price .s-vip-price {
+	margin-right: 20upx;
+	font-size: 26upx;
+	color: #f0ad4e;
+}
+
+.info .b-main .b-price .s-vip-free {
+	margin-right: 20upx;
+	padding: 6upx 10upx;
+	font-size: 24upx;
+	color: #555;
+	background: #f0ad4e;
+	border-radius: 5upx;
+}
+
+.info .b-main .b-opt {
+	display: flex;
+	align-items: center;
+}
+
+.info .b-main .b-opt .s-btn {
+	margin-left: 20upx;
+	font-size: 50upx;
+}
+
+.info .b-main .b-opt .s-btn.f-like .f-yes.iconfont {
+	color: #da5650;
+}
+
+.info .b-main .b-opt .iconfont {
+	font-size: 40upx;
+	color: #999;
+}
+
+.info .b-info {
+	margin-top: 20upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.info .b-info .s-worth {
+	color: #999;
+	font-size: 24upx;
+}
+
+.info .b-info .s-count {
+	color: #999;
+	font-size: 24upx;
+	display: flex;
+	align-items: center;
+}
+
+.info .b-info .s-count .s-gain {
+	margin-left: 40upx;
+}
+
+.content {
+	margin-top: 30upx;
+}
+
+.content .b-title {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.content .b-title .iconfont {
+	color: #ccc;
+}
+
+.content .b-title .s-tit {
+	margin: 0 20upx;
+	font-size: 24upx;
+	color: #666;
+}
+
+.content .b-rich {
+	margin-top: 30upx;
+	padding: 30upx 0;
+	background: #fff;
+	font-size: 28upx;
+}
+
+.content-list {
+	padding: 20upx 30upx;
+	background: #fff;
+}
+
+.content-list .course-item {
+	padding: 30upx 0;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	border-bottom: 2upx solid #eee;
+}
+
+.content-list .course-item:last-child {
+	border-bottom: none;
+}
+
+.content-list .course-item.f-active {
+	font-weight: bold;
+}
+
+.content-list .course-item .b-main {
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+}
+
+.content-list .course-item .b-main .b-name {
+	font-size: 28upx;
+	color: #333;
+	font-weight: bold;
+	width: 498upx;
+	display: inline-block;
+}
+
+.content-list .course-item .b-main .b-percent {
+	margin-top: 20upx;
+	display: flex;
+	flex-direction: column;
+}
+
+.content-list .course-item .b-main .b-percent .b-line {
+	position: relative;
+	width: 100%;
+	height: 20upx;
+	background: #eee;
+}
+
+.content-list .course-item .b-main .b-percent .b-line .s-num {
+	position: absolute;
+	top: 0;
+	left: 0;
+	height: 20upx;
+	background: rgba(218, 86, 80, 0.8);
+}
+
+.content-list .course-item .b-main .b-percent .b-info {
+	margin-top: 10upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.content-list .course-item .b-main .b-percent .b-info .s-time {
+	font-size: 28upx;
+	color: #666;
+}
+
+.content-list .course-item .b-main .b-percent .b-info .s-percent {
+	font-size: 26upx;
+	color: #999;
+}
+
+.content-list .course-item .b-play {
+	margin-left: 30upx;
+	border-left: 2upx solid #eee;
+	width: 160upx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+
+.content-list .course-item .b-play .iconfont {
+	font-size: 40upx;
+	color: #999;
+}
+
+.content-list .course-item .b-play .b-state {
+	margin-top: 20upx;
+	font-size: 24upx;
+	color: #666;
+}
+
+.navbar {
+	padding: 10upx 0;
+	position: fixed;
+	left: 0;
+	bottom: 0;
+	width: 100%;
+	height: 100upx;
+	background: #fff;
+	border-top: 1upx solid #f6f6f6;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.navbar .b-main {
+	margin-left: 30upx;
+	flex: 1;
+	display: flex;
+	align-items: center;
+}
+
+.navbar .b-main .b-amount {
+	flex: 1;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.navbar .b-main .b-amount .s-tit {
+	margin-right: 10upx;
+	font-size: 28upx;
+	color: #333;
+}
+
+.navbar .b-main .b-amount .s-num {
+	font-size: 40upx;
+	color: #da5650;
+}
+
+.navbar .b-main .b-amount .s-num.f-small {
+	font-size: 32upx;
+}
+
+.navbar .b-action {
+	margin-right: 30upx;
+	width: 450upx;
+	display: flex;
+	align-items: center;
+}
+
+.navbar .b-action .b-btn {
+	height: 80upx;
+	line-height: 80upx;
+	font-size: 28upx;
+	color: #fff;
+	text-align: center;
+	letter-spacing: 2upx;
+}
+
+.navbar .b-action .f-cart {
+	flex: 1;
+	background: #ec9c4e;
+	font-size: 26upx;
+	border-radius: 40upx 0 0 40upx;
+}
+
+.navbar .b-action .f-cart.f-disable {
+	background: rgba(218, 86, 80, 0.8);
+}
+
+.navbar .b-action .f-order {
+	flex: 1;
+	background: #da5650;
+	font-size: 26upx;
+	border-radius: 0 40upx 40upx 0;
+}
+
+.navbar .b-action .f-order.f-disable {
+	background: rgba(218, 86, 80, 0.8);
+}
+
+.navbar .b-action .f-learn {
+	flex: 1;
+	letter-spacing: 4upx;
+	background: #da5650;
+	border-radius: 40upx;
+}
+
+.navbar .b-action .f-mute {
+	flex: 1;
+	color: #666;
+	font-size: 26upx;
+	background: #eee;
+	border-radius: 40upx;
+}
+</style>

+ 636 - 0
pages/schedule/index.vue

@@ -0,0 +1,636 @@
+<template>
+	<view class="wrap">
+		<u-navbar :autoBack="true" title="培训" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="search">
+			<view class="b-input">
+				<input class="s-input" :value="keyword" @input="onInput" @confirm="onSearch" placeholder="搜索培训" />
+				<view class="s-submit iconfont icon-search" @click="onSearch"></view>
+			</view>
+		</view>
+		<view class="selecter">
+			<scroll-view scroll-y class="left-aside" :style="{ height: categoryScrollHeight + 'px' }">
+				<block v-for="(item, index) in categoryList" :key="index">
+					<view class="b-item" :class="{ active: index === categoryIndex }" @click="onCategorySelect(index)">
+						{{ item.name }}
+					</view>
+				</block>
+				<!-- 加载中 -->
+				<load-more :loadingType="loadingType" loadingText=" "></load-more>
+			</scroll-view>
+			<view class="right-aside">
+				<view class="goods-state">
+					<text class="b-amount">
+						<text>共有</text>
+						<text class="s-num">{{ totalCount }}</text>
+						<text>个培训</text>
+					</text>
+					<view class="b-filter">
+						<view class="b-item" v-for="(item, index) in filterList" :key="index" :class="{ 'f-active': index == filterIndex }" @click="onFilterSelect(index)">
+							<view class="s-tit">{{ item.name }}</view>
+						</view>
+					</view>
+				</view>
+				<block v-if="typeList.length > 0">
+					<scroll-view class="type-list" scroll-x scroll-with-animation :scroll-into-view="'type-' + typeScroll" v-if="typeList.length > 0">
+						<view class="b-items">
+							<view
+								class="b-item"
+								:id="'type-' + index"
+								v-for="(item, index) in typeList"
+								:key="index"
+								:class="{ active: index === typeIndex }"
+								@click="onTypeSelect(index, true)"
+							>
+								{{ item.name }}
+							</view>
+						</view>
+					</scroll-view>
+					<scroll-view
+						class="group-list"
+						scroll-y
+						scroll-with-animation
+						:upper-threshold="100"
+						:lower-threshold="100"
+						:scroll-top="scrollTop"
+						:scroll-into-view="'group-' + groupScroll"
+						@scroll="onScroll"
+						:style="{ height: groupScrollHeight + 'px' }"
+					>
+						<block v-if="groupLoad">
+							<view class="group-item" v-for="(group, index) in groupList" :id="'group-' + index" :key="index">
+								<view class="group-title">{{ group.name }}</view>
+								<view class="group-main">
+									<view class="schedule-com" v-for="item in group.scheduleList" :key="item.id">
+										<schedule-item :item="item" scene="index"></schedule-item>
+									</view>
+									<!-- 加载中 -->
+									<load-more :loadingType="group.loadingType" :loadingText="group.loadingText"></load-more>
+								</view>
+							</view>
+						</block>
+						<!-- 加载中 -->
+						<load-more v-else :loadingType="loadingType" :loadingText="loadingText"></load-more>
+					</scroll-view>
+				</block>
+				<scroll-view
+					v-else
+					class="schedule-list"
+					scroll-y
+					scroll-with-animation
+					:lower-threshold="100"
+					@scrolltolower="onScrollToLower"
+					:style="{ height: goodsScrollHeight + 'px' }"
+				>
+					<view class="schedule-com" v-for="(item, index) in scheduleList" :key="index">
+						<schedule-item :item="item" scene="index"></schedule-item>
+					</view>
+					<!-- 加载中 -->
+					<load-more :loadingType="loadingType" :loadingText="loadingText"></load-more>
+				</scroll-view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+// import { getCategoryList, getScheduleList } from '@/service/api/schedule.js';
+import mixinsCommon from '@/mixins/common.js';
+let that;
+export default {
+	mixins: [mixinsCommon],
+	data() {
+		return {
+			keyword: '',
+			scrollTop: 0,
+			categoryIndex: 0,
+			categoryList: [
+				{
+					id: 0,
+					name: '所有培训',
+					level: 1,
+					children: []
+				}
+			],
+			categoryScrollHeight: 100,
+			typeScroll: 0,
+			typeIndex: 0,
+			typeList: [],
+			filterIndex: 0,
+			filterList: [
+				{
+					name: '全部',
+					value: 'all'
+				},
+				{
+					name: '免费',
+					value: 'free'
+				},
+				{
+					name: 'VIP',
+					value: 'vip'
+				}
+			],
+			totalCount: 0,
+			groupLoad: false,
+			groupScroll: 0,
+			groupList: [],
+			groupScrollHeight: 100,
+			scheduleList: [],
+			goodsScrollHeight: 100,
+			page: 1,
+			loadingType: -1,
+			loadingText: ''
+		};
+	},
+	onLoad() {
+		that = this;
+		this.initScrollHeight();
+		this.loadingType = 1;
+		this.$api.getCategoryList({}, function (res) {
+			console.log(res, 6969);
+			that.loadingType = -1;
+			if (res.code == 1) {
+				that.categoryList = [...that.categoryList, ...res.data];
+				that.onCategorySelect(0);
+			}
+		});
+		// getCategoryList().then(([err, res]) => {
+		// 	this.loadingType = -1;
+		// 	if (!err) {
+		// 		this.categoryList = [...this.categoryList, ...res];
+		// 		this.onCategorySelect(0);
+		// 	}
+		// });
+	},
+	methods: {
+		redirect(type, data) {
+			switch (type) {
+				case 'audit':
+					this.$app.routePage(null, '/pages/goods/audit');
+					break;
+			}
+		},
+		onInput(e) {
+			console.log('onInput', e);
+			this.keyword = e.detail.value;
+		},
+		onFilterSelect(index) {
+			this.filterIndex = index;
+			this.onCategorySelect(this.categoryIndex);
+		},
+		onSearch() {
+			if (this.keyword) {
+				this.onCategorySelect(0);
+			}
+		},
+		// 选择大类
+		onCategorySelect(index) {
+			// 清除搜索
+			if (this.keyword && index !== 0) {
+				this.keyword = '';
+			}
+			this.loadingType = 1;
+			this.totalCount = 0;
+			this.categoryIndex = index;
+			this.groupLoad = false;
+			if (!this.keyword && this.categoryList[index].children && this.categoryList[index].children.length > 0) {
+				this.typeList = this.categoryList[index].children;
+				let groupList = [];
+				this.typeList.forEach((item) => {
+					groupList.push({
+						id: item.id,
+						name: item.name,
+						scrollTop: -1,
+						scheduleList: [],
+						loadingType: 2,
+						loadingText: '暂无数据'
+					});
+				});
+				this.groupList = groupList;
+				this.onTypeSelect(0, true);
+			} else {
+				this.typeList = [];
+				this.loadScheduleList(true);
+			}
+		},
+		// 选择小类
+		onTypeSelect(index, scrole) {
+			console.log('onTypeSelect', index);
+			// 清除搜索
+			if (this.keyword) {
+				this.keyword = '';
+			}
+			this.typeIndex = index;
+			this.typeScroll = index;
+			this.loadGroupGoods(index, scrole); // 加载当前组
+			this.loadPrevGoods(); // 加载上一组
+			this.loadNextGoods(); // 加载下一组
+		},
+		// 监听右侧栏滚动
+		onScroll(e) {
+			// console.log('onScroll', e)
+			// 待优化
+			let scrollTop = e.detail.scrollTop;
+			let groupIndex = 0;
+			this.groupList.forEach((item, index) => {
+				if (item.scrollTop <= scrollTop && item.scheduleList.length > 0) {
+					groupIndex = index;
+				}
+			});
+			if (this.typeIndex != groupIndex) {
+				console.log('scroll', groupIndex, scrollTop);
+				this.onTypeSelect(groupIndex); // 选中子分类
+			}
+		},
+		// 右侧栏滚动到底
+		onScrollToLower(e) {
+			console.log('onScrollToLower', e);
+			this.loadScheduleList();
+		},
+		// 向前加载数据
+		loadPrevGoods() {
+			if (this.typeIndex > 0) {
+				this.loadGroupGoods(this.typeIndex - 1);
+			}
+		},
+		// 向后加载数据
+		loadNextGoods() {
+			if (this.typeIndex < this.typeList.length - 1) {
+				this.loadGroupGoods(this.typeIndex + 1);
+			}
+		},
+		loadGroupGoods(index, scroll) {
+			console.log('loadGroupGoods', index, scroll);
+			if (this.groupList[index].scheduleList.length === 0) {
+				this.groupList[index].loadingType = 1;
+				if (this.groupLoad === false && this.loadingType === -1) {
+					this.loadingType = 1;
+				}
+				console.log('groupList', this.groupList);
+				const typeId = this.typeList[this.typeIndex].id;
+				const filterGroup = this.filterList[this.filterIndex].value;
+				this.$api.getScheduleList(
+					{
+						category_id: this.typeList[this.typeIndex].id,
+						group: this.filterList[this.filterIndex].value,
+						keyword: this.keyword,
+						page: this.page,
+						page_size: 10
+					},
+					function (res) {
+						console.log('5555', res);
+						that.groupList[index].loadingType = -1;
+						if (that.groupLoad === false && that.loadingType === 1) {
+							that.loadingType = -1;
+							that.groupLoad = true;
+						}
+						console.log('groupLoad', that.groupLoad);
+						if (res.code == 1) {
+							that.totalCount += res.data.total;
+							if (res.data.items.length > 0) {
+								that.groupList[index].scheduleList = res.data.items;
+							} else {
+								that.groupList[index].loadingType = 2;
+								that.groupList[index].loadingText = '暂无数据';
+							}
+							// 计算group的偏移
+							setTimeout(() => {
+								that.calcGroupTop();
+								if (scroll) {
+									that.groupScroll = index;
+								}
+							}, 100);
+						} else {
+							that.groupList[index].loadingType = 3;
+						}
+					}
+				);
+
+				// getScheduleList(typeId, filterGroup, this.keyword, 1, 100).then(([err, res]) => {
+				// 	console.log('getScheduleList', err, res);
+				// 	this.groupList[index].loadingType = -1;
+				// 	if (this.groupLoad === false && this.loadingType === 1) {
+				// 		this.loadingType = -1;
+				// 		this.groupLoad = true;
+				// 	}
+				// 	console.log('groupLoad', this.groupLoad);
+				// 	if (!err) {
+				// 		this.totalCount += res.total;
+				// 		if (res.items.length > 0) {
+				// 			this.groupList[index].scheduleList = res.items;
+				// 		} else {
+				// 			this.groupList[index].loadingType = 2;
+				// 			this.groupList[index].loadingText = '暂无数据';
+				// 		}
+				// 		// 计算group的偏移
+				// 		setTimeout(() => {
+				// 			this.calcGroupTop();
+				// 			if (scroll) {
+				// 				this.groupScroll = index;
+				// 			}
+				// 		}, 100);
+				// 	} else {
+				// 		this.groupList[index].loadingType = 3;
+				// 	}
+				// });
+			} else {
+				if (scroll) {
+					this.groupScroll = index;
+				}
+			}
+		},
+		loadScheduleList(refresh) {
+			console.log('loadScheduleList', refresh);
+			if (refresh) {
+				this.page = 1;
+				this.scheduleList = [];
+			} else {
+				this.page++;
+			}
+			this.loadingType = 1;
+			this.loadingText = '';
+			const categoryId = this.categoryList[this.categoryIndex].id;
+			const filterGroup = this.filterList[this.filterIndex].value;
+			this.$api.getScheduleList(
+				{
+					category_id: this.categoryList[this.categoryIndex].id,
+					group: this.filterList[this.filterIndex].value,
+					keyword: this.keyword,
+					page: this.page,
+					page_size: 10
+				},
+				function (res) {
+					console.log(res, 3636);
+					that.loadingType = -1;
+					if (res.code == 1) {
+						that.totalCount = res.data.total;
+						if (res.data.items.length > 0) {
+							that.scheduleList = [...that.scheduleList, ...res.data.items];
+						} else {
+							that.loadingType = 2;
+							if (that.page == 1) {
+								that.loadingText = '暂无数据';
+							}
+						}
+					} else {
+						that.loadingType = 3;
+					}
+				}
+			);
+			// getScheduleList(categoryId, filterGroup, this.keyword, this.page, 10).then(([err, res]) => {
+			// 	console.log('getScheduleList', err, res);
+			// 	this.loadingType = -1;
+			// 	if (!err) {
+			// 		this.totalCount = res.total;
+			// 		if (res.items.length > 0) {
+			// 			this.scheduleList = [...this.scheduleList, ...res.items];
+			// 		} else {
+			// 			this.loadingType = 2;
+			// 			if (this.page == 1) {
+			// 				this.loadingText = '暂无数据';
+			// 			}
+			// 		}
+			// 	} else {
+			// 		this.loadingType = 3;
+			// 	}
+			// });
+		},
+		// 计算分组偏移
+		calcGroupTop() {
+			let height = 0;
+			let calc = false;
+			this.groupList.forEach((item, index) => {
+				// if (calc === false && item.scheduleList.length === 0) {
+				// 	calc = true
+				// }
+				// if (calc) {
+				let groupView = uni
+					.createSelectorQuery()
+					.in(this)
+					.select('#group-' + index);
+				groupView
+					.fields(
+						{
+							size: true
+						},
+						(res) => {
+							console.log('Query fields', index, res);
+							if (res) {
+								item.scrollTop = height;
+								height += res.height;
+							}
+						}
+					)
+					.exec();
+				// } else {
+				// 	height += item.scrollTop
+				// }
+			});
+			this.sizeCalcState = true;
+		},
+		initScrollHeight() {
+			const systemInfo = uni.getSystemInfoSync();
+			const windowHeight = systemInfo.windowHeight;
+			const searchBarHeight = this.$logic.rpx2px(90);
+			const stateBarHeight = this.$logic.rpx2px(90);
+			const typeListHeight = this.$logic.rpx2px(90);
+			this.categoryScrollHeight = windowHeight - searchBarHeight;
+			this.goodsScrollHeight = this.categoryScrollHeight - stateBarHeight;
+			this.groupScrollHeight = this.goodsScrollHeight - typeListHeight;
+		}
+	}
+};
+</script>
+
+<style>
+.wrap {
+	height: 100%;
+	background-color: #f8f8f8;
+}
+
+.wrap {
+	position: relative;
+}
+
+.search {
+	margin: auto;
+	padding: 0 30upx;
+	width: 690upx;
+	height: 90upx;
+	background: #da5650;
+	display: flex;
+	align-items: center;
+}
+
+.search .b-input {
+	padding: 0 20upx;
+	flex: 1;
+	height: 70upx;
+	background: #fff;
+	border-radius: 10upx;
+	display: flex;
+	align-items: center;
+}
+
+.search .b-input .s-input {
+	flex: 1;
+	color: #333;
+	font-size: 26upx;
+}
+
+.search .b-input .s-submit {
+	margin-left: 20upx;
+	color: #c3c3c3;
+	font-size: 40upx;
+}
+
+.selecter {
+	display: flex;
+	height: 100%;
+}
+
+.left-aside {
+	padding-bottom: 100upx;
+	flex-shrink: 0;
+	width: 145rpx;
+	height: 100%;
+	background-color: #f1f2f1;
+}
+
+.left-aside .b-item {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: 100%;
+	height: 90upx;
+	font-size: 28upx;
+	position: relative;
+}
+
+.left-aside .b-item.active {
+	color: #da5650;
+	background: #f8f8f8;
+}
+
+.left-aside .b-item.active:before {
+	content: '';
+	position: absolute;
+	left: 0;
+	top: 50%;
+	transform: translateY(-50%);
+	height: 36upx;
+	width: 8upx;
+	background-color: #da5650;
+	border-radius: 0 4px 4px 0;
+	opacity: 0.8;
+}
+
+.right-aside {
+	flex: 1;
+}
+
+.right-aside .goods-state {
+	padding: 0 20upx;
+	height: 90upx;
+	background: #f1f2f1;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+}
+
+.right-aside .goods-state .b-amount {
+	color: #999;
+	font-size: 26upx;
+}
+
+.right-aside .goods-state .b-amount .s-num {
+	margin: 0 5upx;
+}
+
+.right-aside .goods-state .b-filter {
+	display: flex;
+	align-items: center;
+}
+
+.right-aside .goods-state .b-filter .b-item {
+	padding: 0 20upx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.right-aside .goods-state .b-filter .b-item.f-active {
+	font-weight: bold;
+}
+
+.right-aside .goods-state .b-filter .b-item .s-tit {
+	color: #666666;
+	font-size: 26upx;
+}
+
+.right-aside .type-list {
+	display: flex;
+	width: 550upx;
+	height: 90upx;
+	background: #fff;
+	white-space: nowrap;
+}
+
+.right-aside .type-list .b-items {
+	padding: 20upx;
+}
+
+.right-aside .type-list .b-item {
+	display: inline-block;
+	margin-right: 20upx;
+	padding: 0 20upx;
+	height: 50upx;
+	line-height: 50upx;
+	background: #f8f8f8;
+	border-radius: 10upx;
+	color: rgba(0, 0, 0, 0.5);
+	font-size: 24upx;
+}
+
+.right-aside .type-list .b-item:last-child {
+	margin-right: 0;
+}
+
+.right-aside .type-list .b-item.active {
+	color: #fff;
+	background: #da5650;
+}
+
+.right-aside .group-list {
+	height: 100%;
+	background: #f8f8f8;
+}
+
+.right-aside .group-list .group-item {
+	padding-top: 30upx;
+}
+
+.right-aside .group-list .group-title {
+	padding: 0 20upx;
+	margin-bottom: 10upx;
+	color: #666;
+	font-size: 28upx;
+	font-weight: bold;
+}
+
+.right-aside .group-list .group-main .schedule-com {
+	border-bottom: 1upx solid #eee;
+}
+
+.right-aside .group-list .group-main .schedule-com:last-child {
+	border-bottom: none;
+}
+
+.right-aside .schedule-list .schedule-com {
+	border-bottom: 1upx solid #eee;
+}
+
+.right-aside .schedule-list .schedule-com:last-child {
+	border-bottom: none;
+}
+</style>

+ 205 - 0
pages/teacher/detail.vue

@@ -0,0 +1,205 @@
+<template>
+	<view class="wrap">
+		<u-navbar :autoBack="true" title="讲师" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="user-view">
+			<view class="b-avatar">
+				<image :src="teacherData.avatar_url || '/static/imgs/user.png'" mode="aspectFill"></image>
+			</view>
+			<view class="b-info">
+				<view class="s-name">{{ teacherData.name }}</view>
+				<view class="s-title" v-if="teacherData.intro">{{ teacherData.intro }}</view>
+			</view>
+		</view>
+		<view class="box">
+			<!-- <view class="box-head">全部课程</view> -->
+			<view class="box-main course-list">
+				<course-item v-for="(item, index) in courseList" :key="index" :item="item"></course-item>
+			</view>
+		</view>
+		<!-- 加载中 -->
+		<load-more :loadingType="loadingType" :loadingText="loadingText"></load-more>
+		<!-- 首页 -->
+		<app-home></app-home>
+	</view>
+</template>
+
+<script>
+// import {
+// 	getTeacherDetail,
+// 	getCourseList
+// } from '@/service/api/teacher.js'
+import mixinsCommon from '@/mixins/common.js';
+let that;
+export default {
+	mixins: [mixinsCommon],
+	data() {
+		return {
+			teacherData: {},
+			courseList: [],
+			loadingType: 1,
+			loadingText: ''
+		};
+	},
+	onLoad(options) {
+		that = this;
+		this.teacherId = options.id;
+		this.$api.getTeacherDetail({ id: this.teacherId }, function (res) {
+			console.log('getTeacherDetail', res);
+			if (res.code == 1) {
+				that.loadingType = -1;
+				that.teacherData = res.data;
+				uni.setNavigationBarTitle({
+					title: res.data.name
+				});
+			} else {
+				that.loadingType = 3;
+				// this.loadingText = err.data.msg || '加载失败';
+			}
+		});
+
+		// getTeacherDetail(this.teacherId).then(([err, res]) => {
+		// 	console.log('getTeacherDetail', err, res);
+		// 	if (!err) {
+		// 		this.loadingType = -1;
+		// 		this.teacherData = res;
+		// 		uni.setNavigationBarTitle({
+		// 			title: res.name
+		// 		});
+		// 	} else {
+		// 		this.loadingType = 3;
+		// 		this.loadingText = err.data.msg || '加载失败';
+		// 	}
+		// });
+		this.loadCourseList(true);
+	},
+	onReachBottom() {
+		if (this.loadingType !== 1 && this.loadingType !== 2) {
+			this.loadCourseList();
+		}
+	},
+	methods: {
+		loadCourseList(refresh) {
+			console.log('loadCourseList', refresh);
+			if (refresh) {
+				this.page = 1;
+				this.courseList = [];
+			} else {
+				this.page++;
+			}
+			this.loadingType = 1;
+			this.loadingText = '';
+			this.$api.getCourseList(
+				{
+					teacherId: that.teacherId,
+					page: that.page,
+					page_size: 10
+				},
+				function (res) {
+					console.log(res, 6565);
+					that.loadingType = -1;
+					if (res.code == 1) {
+						if (res.data.items.length > 0) {
+							that.courseList = [...that.courseList, ...res.data.items];
+						} else {
+							that.loadingType = 2;
+							if (that.page == 1) {
+								that.loadingText = '暂无数据';
+							}
+							that.page--; // 重置分页
+						}
+					} else {
+						that.loadingType = 3;
+					}
+				}
+			);
+			// getCourseList(this.teacherId, this.page, 10).then(([err, res]) => {
+			// 	console.log('getCourseList', err, res);
+			// 	this.loadingType = -1;
+			// 	if (!err) {
+			// 		if (res.items.length > 0) {
+			// 			this.courseList = [...this.courseList, ...res.items];
+			// 		} else {
+			// 			this.loadingType = 2;
+			// 			if (this.page == 1) {
+			// 				this.loadingText = '暂无数据';
+			// 			}
+			// 			this.page--; // 重置分页
+			// 		}
+			// 	} else {
+			// 		this.loadingType = 3;
+			// 	}
+			// });
+		}
+	}
+};
+</script>
+
+<style>
+.wrap {
+	background: #fff;
+}
+
+.user-view {
+	padding: 50upx 0 50upx 0;
+	display: flex;
+	align-items: center;
+	flex-direction: column;
+	z-index: 1;
+	background: #eee;
+}
+
+.user-view .b-avatar {
+	width: 180upx;
+	height: 180upx;
+}
+
+.user-view .b-avatar image {
+	width: 180upx;
+	height: 180upx;
+	border: 5upx solid #fff;
+	border-radius: 50%;
+}
+
+.user-view .b-info {
+	margin-top: 20upx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+
+.user-view .b-info .s-name {
+	margin-top: 20upx;
+	font-weight: bold;
+	font-size: 32upx;
+	color: #333;
+}
+
+.user-view .b-info .s-title {
+	margin-top: 10upx;
+	font-size: 28upx;
+	color: #666;
+}
+
+.box {
+	background: #fff;
+}
+
+.box .box-head {
+	padding: 0 30upx;
+	text-align: center;
+	height: 100upx;
+	line-height: 100upx;
+	font-size: 30upx;
+	color: #333;
+	border-top: 2upx solid #eee;
+	border-bottom: 2upx solid #eee;
+}
+
+.course-list .course-item {
+	border-bottom: 1upx solid #eee;
+}
+
+.course-list .course-item:last-child {
+	border-bottom: none;
+}
+</style>

+ 912 - 0
pages/user/index.vue

@@ -0,0 +1,912 @@
+<template>
+	<view class="">
+		<view class="box">
+			<!-- <u-navbar title="个人中心" :placeholder="true" bgColor="rgba(255,255,255,0.3)" :leftIconSize="0" titleStyle="font-weight:bold;color:#7a5831"></u-navbar> -->
+			<view class="group_1">
+				<view class="group_6">
+					<view class="group_7">
+						<view class="section_14">
+							<view class="single-avatar_1">
+								<image
+									style="width: 100%; height: 100%; border-radius: 50%"
+									src="https://lanhu-dds-backend.oss-cn-beijing.aliyuncs.com/merge_image/imgs/94a543a125164a2a9c1702cd6f202535_mergeImage.png"
+									class=""
+								></image>
+							</view>
+							<text lines="1" class="text_9">白云下的棉絮</text>
+							<view style="position: absolute; right: 50rpx; top: 190rpx">
+								<u-icon name="arrow-right" color="#312520" size="24"></u-icon>
+							</view>
+						</view>
+
+						<view class="mn_wd">
+							<view class="" @click="myLiktBtn(0)">
+								<view class="md_item_wd">
+									<uni-icons type="upload-filled" color="#329fff" size="25"></uni-icons>
+								</view>
+								<view style="margin-top: 10rpx">我的投稿</view>
+							</view>
+							<view class="" @click="myLiktBtn(1)">
+								<view class="md_item_wd">
+									<uni-icons type="star-filled" size="25" color="#ff9617"></uni-icons>
+								</view>
+								<view style="margin-top: 10rpx">我的收藏</view>
+							</view>
+							<view class="" @click="myLiktBtn(2)">
+								<view class="md_item_wd">
+									<uni-icons type="heart-filled" size="25" color="#ff6644"></uni-icons>
+								</view>
+								<view style="margin-top: 10rpx">我的喜欢</view>
+							</view>
+						</view>
+						<!-- 订单管理 -->
+
+						<view class="mn_dd">
+							<view class="block_9">
+								<view class="image-text_15">
+									<uni-icons type="cart-filled" color="#312520" size="24"></uni-icons>
+									<text lines="1" class="text-group_4">订单管理</text>
+								</view>
+								<text lines="1" class="text_10">查看更多》</text>
+							</view>
+						</view>
+						<view class="mn_dd_item">
+							<view class="juli">
+								<view style="margin-bottom: 10rpx">待付款</view>
+								<view class="">
+									<uni-icons type="wallet" color="#ca5642" size="25"></uni-icons>
+								</view>
+							</view>
+							<view class="juli">
+								<view style="margin-bottom: 10rpx">待收获</view>
+								<view class="">
+									<uni-icons type="wallet-filled" color="#ca5642" size="25"></uni-icons>
+								</view>
+							</view>
+							<view class="juli">
+								<view style="margin-bottom: 10rpx">待评价</view>
+								<view class="">
+									<uni-icons type="chat-filled" color="#ca5642" size="25"></uni-icons>
+								</view>
+							</view>
+							<view class="juli">
+								<view style="margin-bottom: 10rpx">已完成</view>
+								<view class="">
+									<uni-icons type="checkbox-filled" color="#ca5642" size="25"></uni-icons>
+								</view>
+							</view>
+							<view class="juli">
+								<view style="margin-bottom: 10rpx">售后</view>
+								<view class="">
+									<uni-icons type="headphones" color="#ca5642" size="25"></uni-icons>
+								</view>
+							</view>
+						</view>
+
+						<!-- 订单管理 -->
+					</view>
+					<view class="image-text_14">
+						<u-icon name="bookmark" color="#312520" size="24"></u-icon>
+
+						<text lines="1" class="text-group_1">文化之路</text>
+					</view>
+					<view class="group_11">
+						<!-- <view class="" style="background-color: rgba(255, 255, 255, 1)"> -->
+						<view class="block_8">
+							<view class="group_12"></view>
+							<text lines="1" class="text_16">已参加课程</text>
+							<text lines="1" class="text_17">查看更多》</text>
+						</view>
+						<!-- 已参加课程 -->
+						<view class="section_5" v-for="item in 2" :key="item">
+							<view class="section_6">
+								<image style="width: 100%; height: 100%; border-radius: 10rpx" src="../../static/image/mn.png"></image>
+							</view>
+							<view class="group_21">
+								<text lines="1" class="text_18">1天前</text>
+								<text lines="1" class="text_19">青少年闽南话讲古传承红色历史</text>
+								<view class="" style="margin-top: 18rpx">
+									<u-line-progress :showText="false" height="4" :percentage="30" activeColor="#CA5642"></u-line-progress>
+								</view>
+							</view>
+						</view>
+						<!-- </view> -->
+						<!-- 已参加课程end -->
+						<!-- 已参加活动 -->
+						<view class="section_9"></view>
+						<view class="section_10">
+							<view class="box_18">
+								<view class="group_13"></view>
+								<text lines="1" class="text_22">已参加活动</text>
+								<text lines="1" class="text_23">查看更多》</text>
+							</view>
+							<view class="box_7" v-for="item in 2" :key="item">
+								<view class="group_14">
+									<image style="width: 100%; height: 100%; border-radius: 10rpx" src="../../static/image/hd.png"></image>
+								</view>
+								<view class="text-wrapper_11">
+									<text lines="1" class="text_24">活动未开始</text>
+									<text lines="1" class="text_25">非遗大课堂·漆线雕丨盘它!</text>
+								</view>
+							</view>
+						</view>
+						<!-- 已参加活动end -->
+
+						<!-- 已分享文章 -->
+						<view class="section_9"></view>
+						<view class="section_12">
+							<view class="box_19">
+								<view class="box_10"></view>
+								<text lines="1" class="text_28">已分享文章</text>
+								<text lines="1" class="text_29">查看更多》</text>
+							</view>
+							<view class="group_16" v-for="item in 2" :key="item">
+								<view class="block_5"><image style="width: 100%; height: 100%; border-radius: 10rpx" src="../../static/image/fx.png"></image></view>
+								<view class="text-wrapper_13">
+									<text lines="1" class="text_30">1天前</text>
+									<text lines="1" class="text_31">国家级“非遗”邂逅“闽南儿歌”</text>
+								</view>
+							</view>
+						</view>
+					</view>
+					<!-- 已分享文章end -->
+					<!-- 文化收藏 -->
+					<view class="block_9">
+						<view class="image-text_15">
+							<u-icon name="bookmark" color="#312520" size="24"></u-icon>
+							<text lines="1" class="text-group_4">文化收藏</text>
+						</view>
+						<text lines="1" class="text_10">查看更多》</text>
+					</view>
+					<view class="block_10">
+						<view class="block_4">
+							<view class="text-wrapper_1">
+								<text lines="1" class="text_11">非遗文化</text>
+							</view>
+						</view>
+						<view class="block_4">
+							<view class="text-wrapper_1">
+								<text lines="1" class="text_11">非遗文化</text>
+							</view>
+						</view>
+					</view>
+					<!-- 文化收藏end -->
+				</view>
+				<!-- 文化笔记 -->
+				<view class="block_11">
+					<view class="image-text_16">
+						<u-icon name="bookmark" color="#312520" size="24"></u-icon>
+						<text lines="1" class="text-group_5">文化笔记</text>
+					</view>
+					<text lines="1" class="text_13">查看更多》</text>
+				</view>
+				<view class="group_23">
+					<view class="list_8" v-for="item in 2" :key="item">
+						<view class="list-items_3-0">
+							<view class="image-text_17-0">
+								<!-- 六边形 -->
+								<text lines="1" class="text-group_6-0">闽南传统工艺蔡氏漆线雕</text>
+							</view>
+
+							<text lines="1" class="text_14-0">厦门漆线雕技艺形成于明末清初,至晚清逐渐成熟,是厦门传统的手工线雕技艺。</text>
+							<text lines="1" decode="true" class="text_15-0">2023年05月23日&nbsp;20:14</text>
+						</view>
+					</view>
+					<!-- 文化笔记end -->
+				</view>
+			</view>
+			<mntabBar footerTab="4" :messageCount="0"></mntabBar>
+		</view>
+	</view>
+</template>
+<script>
+var _token = '';
+var _this;
+
+import { uploadImage } from '@/service/api/common.js';
+import { mapState } from 'vuex';
+export default {
+	components: {},
+	data() {
+		return {
+			isLogin: false,
+			show: false,
+			username: '未登录',
+			face: '',
+			user: {
+				nickname: '未登录',
+				id: '未登录'
+			},
+			avatarUrl: '',
+			wxnickname: '',
+			getFace: false,
+			userdata: {
+				friendsLists: [],
+				friendsTotal: 0,
+				user: {
+					score: '0',
+					exp: '0'
+				}
+			}
+		};
+	},
+	onShow() {
+		/* 调用userInfo()从本地获取用户信息 */
+		this.user = this.$common.userInfo();
+
+		if (this.user && this.user.nickname.indexOf('微信') >= 0) {
+			this.getFace = true;
+		}
+	},
+	onLoad(option) {
+		/* 来到我的页面判断用户是否登录 */
+		_this = this;
+		this.user = this.$common.userInfo();
+		console.log(this.user);
+		if (this.user === 'undefined' || this.user === '' || this.user === [] || this.user === null) {
+			/* 跳转到登录页 */
+			this.$common.toLogin();
+		} else {
+			/* 刷新 */
+			this.$api.refreshUser({}, (val) => {
+				console.log(val);
+				if (val.code == 401) {
+					this.$common.navigateTo('/pages/user/login');
+					return;
+				}
+
+				this.user = val.data.user;
+				this.avatarUrl = this.user.avatar;
+				this.auth = val.data.auth;
+				this.$db.set('user', val.data.user);
+				this.$db.set('auth', val.data.auth);
+				this.$api.getWuyuanUser({}, (val) => {
+					console.log(val);
+					this.userdata = val.data;
+				});
+			});
+			this.isLogin = true;
+		}
+	},
+	computed: {
+		...mapState(['ceShi'])
+	},
+	methods: {
+		// qieHuan() {
+		// 	this.showCeshi = false;
+		// },
+		myLiktBtn(id) {
+			uni.navigateTo({
+				url: '/user_fenbao/myLike?id=' + id
+			});
+		},
+		// 积分
+		jifenBtn() {
+			uni.navigateTo({
+				url: '/user_fenbao/cs_fenbao/jiFen/jiFen'
+			});
+		}
+	}
+};
+</script>
+<style>
+.mn_wd {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	background: #ffffff;
+	padding: 35rpx;
+	border-radius: 20rpx;
+	margin: 20rpx 32rpx 0 32rpx;
+}
+.md_item_wd {
+	text-align: center;
+}
+.mn_dd {
+	margin-bottom: 20rpx;
+}
+.mn_dd_item {
+	padding: 35rpx;
+	display: flex;
+	justify-content: space-around;
+	background-color: #ffffff;
+
+	border-radius: 20rpx;
+}
+.juli {
+	text-align: center;
+}
+.box {
+	height: auto;
+	width: 100%;
+	/* background-image: url('https://huli-app.wenlvti.net/app_static/wuyuan/static/shouhu/wyj-feiyi3-001.png'); */
+	/* background-size: 100% 100%; */
+	background-color: #f0f2f5;
+	background-attachment: fixed;
+	border-radius: 16px 16px 0 0;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+/* .u-icon__icon.data-v-2ee87dc9 {
+	left: 200rpx;
+} */
+.fenge {
+	width: 638rpx;
+	height: 1rpx;
+	background: #dedede;
+	margin: auto;
+}
+.group_1 {
+	width: 750rpx;
+	display: flex;
+	flex-direction: column;
+}
+.section_9 {
+	background-color: #f8f8f8;
+	border-radius: 15rpx;
+	width: 640rpx;
+	height: 30rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 30rpx 0 0 25rpx;
+}
+.group_6 {
+	background-color: rgba(248, 248, 248, 1);
+	width: 750rpx;
+
+	display: flex;
+	flex-direction: column;
+}
+.group_7 {
+	position: relative;
+	width: 750rpx;
+	height: 452rpx;
+	background: linear-gradient(180deg, #ffe7ba, #f8f8f8);
+	display: flex;
+	flex-direction: column;
+}
+
+.section_14 {
+	width: 674rpx;
+	height: 120rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 150rpx 0 0 45rpx;
+}
+.single-avatar_1 {
+	width: 120rpx;
+	height: 120rpx;
+	border-radius: 50%;
+}
+.text_9 {
+	width: 243rpx;
+	height: 40rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 42rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 42rpx;
+	margin: 41rpx 0 0 35rpx;
+}
+
+.icon_2-0 {
+	width: 15rpx;
+	height: 25rpx;
+	margin: 39rpx 35rpx 0 493rpx;
+}
+
+.image-text_14 {
+	width: 160rpx;
+	height: 32rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 300rpx 0 0 53rpx;
+}
+xt-group_3 {
+	width: 119rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+	margin-top: 2rpx;
+}
+.group_11 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 20rpx;
+	width: 690rpx;
+
+	display: flex;
+	flex-direction: column;
+	justify-content: flex-end;
+	margin: 23rpx 0 0 30rpx;
+}
+.block_8 {
+	width: 671rpx;
+	height: 41rpx;
+	margin-top: 24rpx;
+	flex-direction: row;
+	display: flex;
+}
+.group_12 {
+	background-color: rgba(202, 86, 66, 1);
+	width: 8rpx;
+	height: 41rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text_16 {
+	width: 137rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin: 7rpx 0 0 17rpx;
+}
+.text_17 {
+	width: 89rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 22rpx;
+	margin: 10rpx 0 0 420rpx;
+}
+.section_5 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 690rpx;
+
+	margin-top: 1rpx;
+	flex-direction: row;
+	display: flex;
+}
+.section_6 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	width: 199rpx;
+	height: 111rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 29rpx 0 0 25rpx;
+}
+.group_21 {
+	width: 335rpx;
+	height: 95rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 42rpx 113rpx 0 18rpx;
+}
+.text_18 {
+	width: 59rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(153, 153, 153, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-left: 1rpx;
+}
+.text_19 {
+	width: 335rpx;
+	height: 24rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-top: 24rpx;
+}
+
+.section_10 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 20rpx;
+	width: 690rpx;
+	margin-top: 20rpx;
+	display: flex;
+	flex-direction: column;
+}
+.box_18 {
+	width: 671rpx;
+	height: 41rpx;
+	margin-top: 24rpx;
+	flex-direction: row;
+	display: flex;
+}
+.group_13 {
+	background-color: rgba(202, 86, 66, 1);
+	width: 8rpx;
+	height: 41rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text_22 {
+	width: 136rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin: 7rpx 0 0 17rpx;
+}
+.text_23 {
+	width: 89rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin: 10rpx 0 0 421rpx;
+}
+.box_7 {
+	border-radius: 10rpx;
+	width: 690rpx;
+	margin-top: 1rpx;
+	flex-direction: row;
+	display: flex;
+}
+.group_14 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	width: 199rpx;
+	height: 111rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 29rpx 0 0 25rpx;
+}
+.text-wrapper_11 {
+	width: 287rpx;
+	height: 70rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 42rpx 162rpx 0 17rpx;
+}
+.text_24 {
+	width: 119rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-left: 1rpx;
+}
+.text_25 {
+	width: 287rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-top: 24rpx;
+}
+
+.section_12 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 20rpx;
+	width: 690rpx;
+	display: flex;
+	flex-direction: column;
+}
+.box_19 {
+	width: 671rpx;
+	height: 41rpx;
+	margin-top: 24rpx;
+	flex-direction: row;
+	display: flex;
+}
+.box_10 {
+	background-color: rgba(202, 86, 66, 1);
+	width: 8rpx;
+	height: 41rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text_28 {
+	width: 137rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin: 7rpx 0 0 17rpx;
+}
+.text_29 {
+	width: 89rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin: 10rpx 0 0 420rpx;
+}
+.group_16 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 690rpx;
+
+	margin-top: 1rpx;
+	flex-direction: row;
+	display: flex;
+}
+.block_5 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	width: 199rpx;
+	height: 111rpx;
+	display: flex;
+	flex-direction: column;
+	margin: 29rpx 0 0 25rpx;
+}
+.text-wrapper_13 {
+	width: 345rpx;
+	height: 70rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 42rpx 103rpx 0 18rpx;
+}
+.text_30 {
+	width: 59rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(153, 153, 153, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-left: 1rpx;
+}
+.text_31 {
+	width: 345rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-top: 24rpx;
+}
+
+.block_9 {
+	width: 648rpx;
+	height: 33rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 40rpx 0 0 53rpx;
+}
+.image-text_15 {
+	width: 165rpx;
+	height: 33rpx;
+	flex-direction: row;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.text-group_4 {
+	width: 119rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+	margin-top: 3rpx;
+}
+.text_10 {
+	width: 89rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 7rpx;
+}
+.block_10 {
+	width: 687rpx;
+	height: 166rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 32rpx 0 0 32rpx;
+}
+.block_4 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 20rpx;
+	height: 166rpx;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+}
+.text-wrapper_1 {
+	height: 166rpx;
+	background: url(https://lanhu.oss-cn-beijing.aliyuncs.com/psavh7feffxa7l23xrfrl7zl9wkqtfn7b96po9joumqwptlnmi9006fb82-30dc-439a-a4ba-91c459305e8f) 100% no-repeat;
+	background-size: 100% 100%;
+	display: flex;
+	flex-direction: column;
+	width: 330rpx;
+}
+.text_11 {
+	width: 109rpx;
+	height: 27rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 228, 176, 1);
+	font-size: 28rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin: 70rpx 0 0 110rpx;
+}
+.block_11 {
+	width: 647rpx;
+	height: 31rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 37rpx 0 7rpx 54rpx;
+}
+.image-text_16 {
+	width: 159rpx;
+	height: 31rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+}
+.text-group_5 {
+	width: 119rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+	margin-top: 1rpx;
+}
+.text_13 {
+	width: 89rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 5rpx;
+}
+.group_23 {
+	width: 750rpx;
+	display: flex;
+	flex-direction: column;
+	padding-bottom: 20rpx;
+}
+.list_8 {
+	width: 690rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 27rpx 0 0 30rpx;
+}
+.list-items_3-0 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 20rpx;
+	width: 690rpx;
+	display: flex;
+	flex-direction: column;
+}
+.image-text_17-0 {
+	width: 366rpx;
+	height: 29rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 34rpx 0 0 30rpx;
+}
+
+.text-group_6-0 {
+	width: 327rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+}
+
+.text_14-0 {
+	width: 622rpx;
+	height: 66rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	line-height: 28rpx;
+	margin: 24rpx 0 0 29rpx;
+}
+.text_15-0 {
+	width: 242rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(153, 153, 153, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Normal;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 26rpx 0 30rpx 422rpx;
+}
+</style>

+ 435 - 0
pages/user/learn.vue

@@ -0,0 +1,435 @@
+<template>
+	<view class="wrap">
+		<u-navbar :autoBack="true" title="我的学习" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="filter-box">
+			<view class="b-item" v-for="(item, index) in groupList" :key="index" :class="{ 'f-active': index == groupIndex }" @click="onGroupSelect(index)">
+				<view class="s-tit">{{ item.name }}</view>
+			</view>
+		</view>
+		<view class="course-list" v-if="groupList[groupIndex].value === 'course' && recordList.length > 0">
+			<view class="course-item" @click="onJumpDetail('course', item.course_id)" v-for="(item, index) in recordList" :key="index">
+				<view class="b-cover">
+					<image :src="item.course_data.cover_url" mode="aspectFill"></image>
+				</view>
+				<view class="b-main">
+					<text class="b-title too-long">{{ item.course_data.name }}</text>
+					<view class="b-percent">
+						<view class="b-line">
+							<view class="s-num" :style="'width:' + item.learn_percent + '%'"></view>
+						</view>
+						<view class="b-data">
+							<view class="s-time">{{ item.course_data.total_length }}课时</view>
+							<view class="s-percent">已学{{ item.learn_percent }}%</view>
+						</view>
+					</view>
+					<view class="b-info">
+						<view class="s-category">{{ item.course_data.category_name }}</view>
+						<!-- <view class="s-option">
+							<view class="iconfont icon-option"></view>
+						</view> -->
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="schedule-list" v-if="groupList[groupIndex].value === 'schedule' && recordList.length > 0">
+			<view class="schedule-item" @click="onJumpDetail('schedule', item.schedule_id)" v-for="(item, index) in recordList" :key="index">
+				<view class="b-cover">
+					<image :src="item.schedule_data.cover_url" mode="aspectFill"></image>
+				</view>
+				<view class="b-main">
+					<text class="b-title too-long">{{ item.schedule_data.name }}</text>
+					<view class="b-percent">
+						<view class="b-line">
+							<view class="s-num" :style="'width:' + item.learn_percent + '%'"></view>
+						</view>
+						<view class="b-data">
+							<view class="s-time">{{ item.schedule_data.total_length }}课时</view>
+							<view class="s-percent">已学{{ item.learn_percent }}%</view>
+						</view>
+					</view>
+					<view class="b-info">
+						<view class="s-category">{{ item.schedule_data.category_name }}</view>
+						<!-- <view class="s-option">
+							<view class="iconfont icon-option"></view>
+						</view> -->
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- 加载中 -->
+		<load-more :loadingType="loadingType" :loadingText="loadingText" color="#888888"></load-more>
+	</view>
+</template>
+
+<script>
+// import { getMineCourseList } from '@/service/api/course.js';
+// import { getMineScheduleList } from '@/service/api/schedule.js';
+import Util from '@/common/util';
+import mixinsCommon from '@/mixins/common.js';
+export default {
+	mixins: [mixinsCommon],
+	data() {
+		return {
+			groupList: [
+				{
+					name: '我的课程',
+					value: 'course'
+				},
+				{
+					name: '我的培训',
+					value: 'schedule'
+				}
+			],
+			groupIndex: 0,
+			recordList: [],
+			hasLoad: false,
+			refreshTime: 0,
+			loadingType: 1,
+			loadingText: ''
+		};
+	},
+	onLoad(options) {
+		if (!this.$store.state.learnType) {
+			this.refreshTime = Util.getTimestamp();
+			this.loadRecordList(true);
+		}
+	},
+	onShow() {
+		// switchTab时通过这种方式传参
+		console.log('onShow', this.$store.state.learnType);
+		const learnType = this.$store.state.learnType;
+		if (learnType) {
+			this.$store.commit('delLearnType');
+			if (learnType === 'course') {
+				this.groupIndex = 0;
+			} else if (learnType === 'schedule') {
+				this.groupIndex = 1;
+			}
+			this.loadRecordList(true);
+		} else {
+			if (this.hasLoad) {
+				const timestamp = Util.getTimestamp();
+				if (timestamp - this.refreshTime >= 5) {
+					this.refreshTime = timestamp;
+					this.loadRecordList(true);
+				}
+			}
+		}
+	},
+	onReachBottom() {
+		if (this.loadingType !== 1 && this.loadingType !== 2) {
+			this.loadRecordList();
+		}
+	},
+	methods: {
+		loadRecordList(refresh) {
+			if (this.isLogin) {
+				if (this.groupList[this.groupIndex].value === 'course') {
+					this.loadCourseList(refresh);
+				} else if (this.groupList[this.groupIndex].value === 'schedule') {
+					this.loadScheduleList(refresh);
+				}
+			} else {
+				this.loadingType = 2;
+				this.loadingText = '暂无数据,请先登录吧';
+			}
+		},
+		loadCourseList(refresh) {
+			console.log('loadCourseList', refresh);
+			if (refresh) {
+				this.page = 1;
+				this.recordList = [];
+			} else {
+				this.page++;
+			}
+			this.loadingType = 1;
+			this.loadingText = '';
+			// this.$api.getMineCourseList({},function(res){
+
+			// })
+			// getMineCourseList(this.page, 10).then(([err, res]) => {
+			// 	console.log('getMineCourseList', err, res);
+			// 	this.loadingType = -1;
+			// 	this.hasLoad = true;
+			// 	if (!err) {
+			// 		if (res.items.length > 0) {
+			// 			this.recordList = [...this.recordList, ...res.items];
+			// 		} else {
+			// 			this.loadingType = 2;
+			// 			if (this.page == 1) {
+			// 				this.loadingText = '暂无记录,快去学习吧';
+			// 			}
+			// 			this.page--; // 重置分页
+			// 		}
+			// 	} else {
+			// 		this.loadingType = 2;
+			// 	}
+			// });
+		},
+		loadScheduleList(refresh) {
+			console.log('loadScheduleList', refresh);
+			if (refresh) {
+				this.page = 1;
+				this.recordList = [];
+			} else {
+				this.page++;
+			}
+			this.loadingType = 1;
+			this.loadingText = '';
+			getMineScheduleList(this.page, 10).then(([err, res]) => {
+				console.log('getMineScheduleList', err, res);
+				this.loadingType = -1;
+				this.hasLoad = true;
+				if (!err) {
+					if (res.items.length > 0) {
+						this.recordList = [...this.recordList, ...res.items];
+					} else {
+						this.loadingType = 2;
+						if (this.page == 1) {
+							this.loadingText = '暂无记录,快去参加吧';
+						}
+						this.page--; // 重置分页
+					}
+				} else {
+					this.loadingType = 2;
+				}
+			});
+		},
+		onGroupSelect(index) {
+			this.groupIndex = index;
+			this.loadRecordList(true);
+		},
+		onJumpDetail(type, id) {
+			if (type === 'schedule') {
+				uni.navigateTo({
+					url: '/pages/schedule/detail?sid=' + id
+				});
+			} else if (type === 'course') {
+				uni.navigateTo({
+					url: '/pages/course/detail?cid=' + id
+				});
+			}
+		}
+	}
+};
+</script>
+
+<style>
+.wrap {
+	padding-bottom: 150upx;
+}
+
+.filter-box {
+	padding: 30upx 50upx 0 50upx;
+	margin-bottom: 30upx;
+	background: #fff;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+}
+
+.filter-box .b-item {
+	margin: 0 40upx;
+	height: 80upx;
+	line-height: 80upx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	font-size: 30upx;
+	padding-bottom: 6upx;
+	position: relative;
+}
+
+.filter-box .b-item.f-active {
+	padding-bottom: 0;
+	border-bottom: 6upx solid #da5650;
+}
+
+.filter-box .b-item.f-active .s-tit {
+	color: #da5650;
+}
+
+.filter-box .b-item .s-tit {
+	color: #333;
+}
+
+.course-list .course-item {
+	padding: 30upx;
+	background: #fff;
+	display: flex;
+	align-items: center;
+	border-bottom: 2upx solid #eee;
+}
+
+.course-list .course-item:last-child {
+	border-bottom: none;
+	margin-bottom: 0;
+}
+
+.course-list .course-item .b-cover {
+	width: 140upx;
+	height: 160upx;
+}
+
+.course-list .course-item .b-cover image {
+	width: 100%;
+	height: 100%;
+}
+
+.course-list .course-item .b-main {
+	flex: 1;
+	margin-left: 20upx;
+}
+
+.course-list .course-item .b-main .b-title {
+	font-size: 30upx;
+	color: #333;
+	width: 530upx;
+	display: inline-block;
+}
+
+.course-list .course-item .b-main .b-percent {
+	margin-top: 10upx;
+	display: flex;
+	flex-direction: column;
+}
+
+.course-list .course-item .b-main .b-percent .b-line {
+	position: relative;
+	width: 100%;
+	height: 20upx;
+	background: #eee;
+}
+
+.course-list .course-item .b-main .b-percent .b-line .s-num {
+	position: absolute;
+	top: 0;
+	left: 0;
+	height: 20upx;
+	background: rgba(218, 86, 80, 0.8);
+}
+
+.course-list .course-item .b-main .b-percent .b-data {
+	margin-top: 10upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.course-list .course-item .b-main .b-percent .b-data .s-time {
+	font-size: 26upx;
+	color: #666;
+}
+
+.course-list .course-item .b-main .b-percent .b-data .s-percent {
+	font-size: 24upx;
+	color: #999;
+}
+
+.course-list .course-item .b-main .b-info {
+	margin-top: 20upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.course-list .course-item .b-main .b-info .s-category {
+	font-size: 24upx;
+	color: #666;
+}
+
+.course-list .course-item .b-main .b-info .s-option {
+	font-size: 32upx;
+	color: #999;
+}
+
+.schedule-list .schedule-item {
+	padding: 30upx;
+	background: #fff;
+	display: flex;
+	align-items: center;
+	border-bottom: 2upx solid #eee;
+}
+
+.schedule-list .schedule-item:last-child {
+	border-bottom: none;
+	margin-bottom: 0;
+}
+
+.schedule-list .schedule-item .b-cover {
+	width: 140upx;
+	height: 160upx;
+}
+
+.schedule-list .schedule-item .b-cover image {
+	width: 100%;
+	height: 100%;
+}
+
+.schedule-list .schedule-item .b-main {
+	flex: 1;
+	margin-left: 20upx;
+}
+
+.schedule-list .schedule-item .b-main .b-title {
+	font-size: 30upx;
+	color: #333;
+	width: 530upx;
+	display: inline-block;
+}
+
+.schedule-list .schedule-item .b-main .b-percent {
+	margin-top: 10upx;
+	display: flex;
+	flex-direction: column;
+}
+
+.schedule-list .schedule-item .b-main .b-percent .b-line {
+	position: relative;
+	width: 100%;
+	height: 20upx;
+	background: #eee;
+}
+
+.schedule-list .schedule-item .b-main .b-percent .b-line .s-num {
+	position: absolute;
+	top: 0;
+	left: 0;
+	height: 20upx;
+	background: rgba(218, 86, 80, 0.8);
+}
+
+.schedule-list .schedule-item .b-main .b-percent .b-data {
+	margin-top: 10upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.schedule-list .schedule-item .b-main .b-percent .b-data .s-time {
+	font-size: 26upx;
+	color: #333;
+}
+
+.schedule-list .schedule-item .b-main .b-percent .b-data .s-percent {
+	font-size: 24upx;
+	color: #666;
+}
+
+.schedule-list .schedule-item .b-main .b-info {
+	margin-top: 16upx;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.schedule-list .schedule-item .b-main .b-info .s-category {
+	font-size: 24upx;
+	color: #666;
+}
+
+.schedule-list .schedule-item .b-main .b-info .s-option {
+	font-size: 32upx;
+	color: #999;
+}
+</style>

+ 420 - 0
pages/user/login.vue

@@ -0,0 +1,420 @@
+<template>
+	<view class="body">
+		<u-navbar title="登录" bgColor="rgba(255,255,255,0.3)" :leftIconSize="0" titleStyle="font-weight:bold;color:#7a5831"></u-navbar>
+		<block>
+			<!--  #ifndef  MP-WEIXIN	 -->
+			<view class="login-bg">
+				<view class="login-card">
+					<view class="login-head">
+						<image class="logoimg" :src="baseLogo" mode="widthFix"></image>
+					</view>
+					<view class="login-input login-margin-b">
+						<input type="number" v-model="username" placeholder="请输入手机号" />
+					</view>
+					<view class="login-input">
+						<input :password="true" v-model="password" placeholder="请输入密码(6-16位)" />
+					</view>
+					<view class="cu-bar btn-group margin-top">
+						<button class="cu-btn bg-orange shadow-blur round" :loading="loading" @tap="login">{{ loading ? '登录中...' : '登 录' }}</button>
+					</view>
+					<view class="flex justify-center">
+						<view class="text-gray text-sm margin-top-xl" @tap="register">注册新账户</view>
+					</view>
+				</view>
+			</view>
+			<!--  #endif -->
+
+			<!--  #ifdef  MP-WEIXIN	 -->
+			<view class="logView">
+				<button @click="onGetUserProfile" class="logbt">
+					<view class="login-head">
+						<image class="logoimg" :src="baseLogo" mode="widthFix"></image>
+					</view>
+					<view class="loginTitile"><text decode="true">请点击微信登录,并授权获取公开信息, 登录后您将获得更多权益</text></view>
+					<view class="cu-btn bg-orange shadow-blur round">
+						<text class="cuIcon-lightauto"></text>
+						微信登录
+					</view>
+				</button>
+				<!-- <view class="text-gray text-sm margin-top-xl" @click="changMobileLogin()">手机登录</view> -->
+			</view>
+			<!--  #endif -->
+		</block>
+	</view>
+</template>
+
+<script>
+var _this;
+import { baseLogo } from '../../config/config.js';
+export default {
+	data() {
+		return {
+			loading: false,
+			user: [],
+			username: '',
+			password: '',
+			class_id: '',
+			ismobile: false,
+			group_id: 1,
+			code: '',
+			baseLogo: baseLogo,
+			redirect: ''
+		};
+	},
+	mounted() {
+		_this = this;
+	},
+	onLoad(e) {
+		console.log(e);
+		if (e.redirect) {
+			this.redirect = e.redirect;
+		}
+	},
+	onShow() {
+		this.user = this.$common.userInfo();
+		console.log('this.user: ', this.user);
+		if (typeof this.user == 'undefined' || this.user == '' || this.user == null) {
+		} else {
+			this.$common.navigateTo('index');
+		}
+		// #ifdef MP-WEIXIN
+		this.wxLogin();
+		// #endif
+	},
+	methods: {
+		wxLogin() {
+			wx.login({
+				success: (res) => {
+					this.code = res.code;
+				},
+				fail: function (error) {
+					console.log('login failed ' + error);
+				}
+			});
+		},
+		//切换微信登录
+		// wechatLogin(){
+		// 	_this.ismobile=false;
+		// },
+		//切换手机登录
+		// changMobileLogin(){
+		// 	_this.ismobile=true;
+
+		// },
+		register() {
+			this.$common.navigateTo('register');
+		},
+		login() {
+			_this.loading = true;
+			if (_this.username == '' || _this.username.length < 11) {
+				uni.showToast({
+					icon: 'none',
+					title: '请输入正确的手机号'
+				});
+				_this.loading = false;
+				return;
+			}
+			if (_this.password == '') {
+				uni.showToast({
+					icon: 'none',
+					title: '请输入密码'
+				});
+				_this.loading = false;
+				return;
+			}
+			_this.$api.login(
+				{
+					account: _this.username,
+					password: _this.password
+				},
+				(data) => {
+					//console.log(data);
+					if (data.code == 1) {
+						_this.loading = false;
+						//console.log(data);
+
+						try {
+							/* 存入本地 */
+							_this.$db.set('upload', 1);
+							_this.$db.set('login', 1);
+							_this.$db.set('token', data.data.userinfo.token);
+							_this.$db.set('user', data.data.userinfo);
+							_this.$db.set('auth', data.data.auth);
+							_this.$store.commit('setAccessToken', data.data.userinfo.token);
+							_this.$store.commit('setActivityId', 0);
+						} catch (e) {}
+
+						_this.$common.successToShow(data.msg, function () {
+							// _this.$common.navigateTo('index');
+
+							if (_this.redirect != '') {
+								console.log(_this.redirect);
+								if (_this.redirect.indexOf('%2F') > 0) {
+									_this.redirect = '/' + unescape(_this.redirect);
+								}
+								_this.$common.navigateTo(_this.redirect);
+								return;
+							}
+							uni.navigateBack();
+						});
+					} else {
+						_this.loading = false;
+						uni.showToast({
+							duration: 1500,
+							icon: 'none',
+							title: data.msg
+						});
+					}
+				}
+			);
+		},
+
+		onGetUserProfile() {
+			// uni.showLoading({
+			// 	title:"正在登录中..."
+			// })
+			var platform = 'wechat';
+			var that = this;
+			var fid = uni.getStorageSync('parentid') ? uni.getStorageSync('parentid') : '';
+			uni.getUserProfile({
+				desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
+				success: (res) => {
+					console.log(res, 888888);
+					var invite_id = _this.$db.get('invite_id');
+					if (!invite_id) invite_id = 0;
+					console.log(invite_id);
+					_this.$api.third(
+						{
+							code: _this.code,
+							platform: platform,
+							encrypted_data: res.encryptedData,
+							iv: res.iv,
+							raw_data: res.rawData,
+							signature: res.signature,
+							invite_id: invite_id,
+							appid: 'wx9a27d13d29890754',
+							diyname: 'xiamen'
+						},
+						(data) => {
+							console.log(data);
+							// console.log(data.data.userinfo)
+							var res = data.data;
+							if (data.code == 1) {
+								this.$common.successToShow('登录成功!');
+								try {
+									this.$db.set('upload', 1);
+									this.$db.set('login', 1);
+									this.$db.set('auth', res.auth);
+									this.$db.set('user', res.userinfo);
+									this.$db.set('token', res.auth.token);
+									this.$store.commit('setAccessToken', res.auth.token);
+									this.$store.commit('setActivityId', 2);
+								} catch (e) {
+									console.log('e: ', e);
+								}
+								uni.switchTab({
+									url: '/pages/index/index'
+								});
+								if (this.redirect != '') {
+									console.log(this.redirect);
+									if (this.redirect.indexOf('%2F') > 0) {
+										this.redirect = '/' + unescape(this.redirect);
+									}
+									this.$common.navigateTo(this.redirect);
+									return;
+								}
+								uni.navigateBack();
+							} else {
+								_this.wxLogin();
+							}
+						}
+					);
+				},
+				fail: (res) => {
+					console.log('res: ', res);
+					_this.wxLogin(); //重新获取登录code
+					uni.hideLoading();
+					if (res.errMsg == 'getUserInfo:cancel' || res.errMsg == 'getUserInfo:fail auth deny') {
+						uni.showModal({
+							title: '用户授权失败',
+							showCancel: false,
+							content: '请点击重新授权,如果未弹出授权,请尝试长按删除小程序,重新进入!',
+							success: function (res) {
+								if (res.confirm) {
+									console.log('用户点击确定');
+									uni.navigateBack();
+								}
+							}
+						});
+					}
+				}
+			});
+			// uni.login({
+			// 	success: loginRes => {
+			// 		uni.hideLoading();
+			// 		console.log('第一次登录'+loginRes.code)
+			// 		if (loginRes.code && loginRes.code!='') {
+			// 			console.log('2222222222222222222')
+
+			// 		}
+			// 	}
+			// })
+		}
+	}
+};
+</script>
+
+<style>
+page {
+	background: #fff;
+}
+
+.content {
+	height: 100%;
+}
+
+.logView {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	flex-direction: column;
+	align-items: center;
+	/* 垂直居中 */
+	width: 100%;
+	position: fixed;
+	left: 50%;
+	top: 50%;
+	transform: translate(-50%, -50%);
+}
+
+.logbt {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	flex-direction: column;
+	align-items: center;
+	/* 垂直居中 */
+	width: 100%;
+	background: none;
+	border: none !important;
+}
+
+.logbt:after {
+	border: none !important;
+}
+
+.logbt .logoimg {
+	width: 200rpx;
+	height: 200rpx;
+	display: block;
+}
+
+.logbt .wechatimg {
+	width: 150rpx;
+	height: 150rpx;
+	display: block;
+}
+
+.loginTitile {
+	padding: 50rpx;
+	font-size: 28rpx;
+	color: #787878;
+	line-height: 1.3;
+	text-align: center;
+}
+
+.loginBtn {
+	width: 300rpx;
+	height: 70rpx;
+	line-height: 70rpx;
+	color: #fff;
+	background: #2562a1;
+	border-radius: 10rpx;
+	border: none;
+}
+
+image {
+	width: 100rpx;
+	height: 100rpx;
+}
+
+.mobileLogin {
+	background: none;
+	color: #999;
+	text-align: center;
+	margin: 40rpx auto;
+	border: none;
+	font-size: 26rpx;
+}
+
+.landing[type='primary'] {
+	height: 84rpx;
+	line-height: 84rpx;
+	border-radius: 44rpx;
+	font-size: 32rpx;
+	/* background: linear-gradient(left, #86B5F4, #4790EF); */
+	background-color: #ffbc32;
+}
+
+.login-btn {
+	padding: 10rpx 20rpx;
+	margin-top: 60rpx;
+}
+
+.login-function {
+	overflow: auto;
+	padding: 20rpx 20rpx 30rpx 20rpx;
+}
+
+.login-forget {
+	float: left;
+	font-size: 26rpx;
+	color: #999;
+}
+
+.login-register {
+	color: #666;
+	float: right;
+	font-size: 26rpx;
+}
+
+.login-input input {
+	background: #f2f5f6;
+	font-size: 28rpx;
+	padding: 10rpx 25rpx;
+	height: 80rpx;
+	line-height: 80rpx;
+	border-radius: 40rpx;
+}
+
+.login-margin-b {
+	margin-bottom: 25rpx;
+}
+
+.login-input {
+	padding: 10rpx 20rpx;
+}
+
+.login-head {
+	font-size: 34rpx;
+	text-align: center;
+	padding: 25rpx 10rpx 55rpx 10rpx;
+}
+
+.login-head image {
+	width: 200rpx;
+}
+
+.login-card {
+	background: #fff;
+	border-radius: 12rpx;
+	padding: 10rpx 25rpx;
+	position: relative;
+	margin-top: 120rpx;
+}
+
+.login-bg {
+	height: 100%;
+	padding: 25rpx;
+}
+</style>

+ 735 - 0
pages/xueYuan/xueYuan.vue

@@ -0,0 +1,735 @@
+<template>
+	<view class="">
+		<view class="box">
+			<view class="group_1">
+				<u-navbar title="学院" :placeholder="true" bgColor="rgba(255,255,255,0)" :leftIconSize="0" titleStyle="font-weight:bold;color:#7a5831"></u-navbar>
+				<view class="block_2">
+					<view class="an" style="margin-top: 20rpx; margin-bottom: 20rpx">
+						<u-notice-bar text="系统消息提示"></u-notice-bar>
+					</view>
+					<view class="image_16" @click="zhengCe">
+						<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_tp.png" class=""></image>
+					</view>
+
+					<view class="group_2">
+						<view
+							@click="coursesBtn"
+							class="box_1"
+							style="background: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_wb.png'); background-size: 100% 100%"
+						>
+							<view class="text-wrapper_1">
+								<text lines="1" class="text_3">学习课程</text>
+							</view>
+						</view>
+						<view class="box_2">
+							<view class="block_3">
+								<view
+									@click="huodong"
+									class="block_4"
+									style="background: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_ms.png'); background-size: 100% 100%"
+								>
+									<view class="text-wrapper_2">
+										<text lines="1" class="text_4">名师在线</text>
+									</view>
+								</view>
+								<view
+									@click="scheduleBtn"
+									class="text-wrapper_3"
+									style="background: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_cj.png'); background-size: 100% 100%"
+								>
+									<text lines="1" class="text_5">产教融合</text>
+								</view>
+							</view>
+							<button
+								@click="learnBtn"
+								class="button_1"
+								style="background: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_zw.png'); background-size: 100% 100%"
+							>
+								<view class="text-wrapper_4">
+									<text lines="1" class="text_6">自我测验</text>
+								</view>
+							</button>
+						</view>
+					</view>
+					<view class="text-wrapper_5">
+						<text lines="1" class="text_7">名家推荐</text>
+						<text lines="1" class="text_8" @click="ceshiBtn">查看更多》</text>
+					</view>
+					<view class="group_3">
+						<view class="group_4" v-for="item in mingJiaList" :key="item" @click="expertBtn(item)">
+							<view class="image-wrapper_1">
+								<image :src="item.img" class="single-avatar_1"></image>
+							</view>
+							<view class="block_5">
+								<view class="text-group_1">
+									<text lines="1" class="text_9">{{ item.name }}</text>
+									<!-- <text lines="1" class="text_10">职称</text> -->
+								</view>
+							</view>
+							<view class="block_6">
+								<view class="image-text_1">
+									<text lines="1" decode="true" class="text-group_2">&nbsp;教学指数</text>
+									<uni-icons color="#ca5642" type="star-filled" size="18"></uni-icons>
+									<uni-icons color="#ca5642" type="star-filled" size="18"></uni-icons>
+									<uni-icons color="#ca5642" type="star-filled" size="18"></uni-icons>
+									<uni-icons color="#ca5642" type="star-filled" size="18"></uni-icons>
+									<uni-icons color="#ca5642" type="star-filled" size="18"></uni-icons>
+								</view>
+							</view>
+							<view class="block_7">
+								<button bindtap="onClick" class="button_2">
+									<text lines="1" class="text_11">详情</text>
+								</button>
+							</view>
+						</view>
+					</view>
+					<!-- 
+					<view class="text-wrapper_6">
+						<text lines="1" class="text_21">推荐课程</text>
+						<text lines="1" class="text_22">查看更多》</text>
+					</view> -->
+					<!-- 
+					<view class="group_13" v-for="item in tjkcList" :key="item" @click="kcBtn">
+						<image :src="item.img" class="image_12"></image>
+						<view class="group_14">
+							<view class="text-group_9">
+								<text lines="1" class="text_23">课程标题</text>
+								<text lines="1" class="text_24">课程附标题</text>
+							</view>
+							<view class="text-wrapper_7">
+								<text lines="1" class="text_25">会员价</text>
+								<text lines="1" class="text_26">¥99</text>
+							</view>
+						</view>
+						<button bindtap="onClick" class="button_6">
+							<text lines="1" class="text_27">立即报名</text>
+						</button>
+					</view> -->
+				</view>
+			</view>
+		</view>
+		<!-- 文保课程 -->
+		<view class="box">
+			<view class="box-head">
+				<view class="text-wrapper_6">
+					<text lines="1" class="text_21">推荐课程</text>
+					<text lines="1" class="text_22" @click="onRedirect('course-home')">查看更多》</text>
+				</view>
+			</view>
+			<view class="box-main course-list">
+				<course-item v-for="(item, index) in state.course_list" :key="index" :item="item"></course-item>
+			</view>
+		</view>
+
+		<mntabBar footerTab="3" :messageCount="0"></mntabBar>
+	</view>
+</template>
+
+<script>
+import { mapState } from 'vuex';
+let that;
+export default {
+	components: {},
+	data() {
+		return {
+			state: null,
+
+			mingJiaList: [
+				{
+					img: 'https://feicheng.16fw.cn:1443/uploads/20230602/5ee294b117a1f6d134245dc074152b3b.jpg',
+					id: 1,
+					name: '李向群老师'
+				},
+				{
+					img: 'https://feicheng.16fw.cn:1443/uploads/20230602/7957d5904f92e16f6fdc9559768edf7b.jpg',
+					id: 2,
+					name: '黄国富老师'
+				}
+			],
+			bannerlist: [],
+
+			tjkcList: [
+				{
+					img: 'https://i1.hdslb.com/bfs/archive/acffcc28ff54120aa48199faba07f0409fc07110.jpg'
+				},
+				{
+					img: 'https://img1.baidu.com/it/u=1515823842,2345646418&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=256'
+				}
+			]
+		};
+	},
+	onLoad(option) {
+		that = this;
+		// this.getBannerList();
+		this.getHomeData();
+	},
+	computed: {
+		...mapState(['ceShi'])
+	},
+	methods: {
+		// 新版活动临时跳转
+		huodong() {
+			uni.navigateTo({
+				url: '/xueyuan_fenbao/kcXiangQing/huoDong'
+			});
+		},
+		// 省级政策临时跳转
+		zhengCe() {
+			uni.navigateTo({
+				url: '/xueyuan_fenbao/kcXiangQing/zhengCe'
+			});
+		},
+		ceshiBtn() {
+			uni.navigateTo({
+				url: '/xueyuan_fenbao/jiGou/jiGou'
+			});
+		},
+		getHomeData() {
+			this.$api.getHomeData({}, function (res) {
+				// console.log(res, 1010);
+				// this.hasLoad = true
+				// this.loadingType = -1
+				that.state = res.data;
+				console.log(that.state, 1010);
+			});
+		},
+
+		onRedirect(type) {
+			console.log('onRedirect', type);
+			var pages = {
+				'course-home': '/pages/course/index',
+				'schedule-home': '/pages/schedule/index'
+			};
+			var page = pages[type] || '';
+			if (page) {
+				if (type === 'course-home' || type === 'schedule-home') {
+					uni.navigateTo({
+						url: page
+					});
+				} else {
+					uni.navigateTo({
+						url: page
+					});
+				}
+			}
+		},
+		// 合并的教育小程序方法end
+		// 学习课程
+		coursesBtn() {
+			uni.navigateTo({
+				url: '/pages/course/index'
+			});
+		},
+		// 产教融合
+		scheduleBtn() {
+			uni.navigateTo({
+				url: '/pages/schedule/index'
+			});
+		},
+		// 自我检验
+		learnBtn() {
+			uni.navigateTo({
+				url: '/pages/user/learn'
+			});
+		},
+
+		// 专家介绍
+		expertBtn(item) {
+			console.log(item);
+			uni.navigateTo({
+				url: `/xueyuan_fenbao/zhuangJia/zhuangJia?id=${item.id}`
+			});
+		},
+		// 课程详情
+		kcBtn() {
+			uni.navigateTo({
+				url: '/xueyuan_fenbao/kcXiangQing/kcXiangQing'
+			});
+		},
+		getBannerList() {
+			this.$api.getBannerList({ block: 'home' }, function (res) {
+				// console.log(res);
+				if (res.code > 0) {
+					that.bannerlist = [];
+					for (var i = 0; i < res.data.length; i++) {
+						if (res.data[i].type == 'banner') {
+							that.bannerlist.push({
+								title: res.data[i].title,
+								url: that.$config.baseUrl + res.data[i].image,
+								page: res.data[i].url
+							});
+						}
+					}
+				}
+			});
+		}
+	}
+};
+</script>
+
+<style>
+.box {
+	height: auto;
+	width: 100%;
+	background-color: #f8f8f8;
+	background-attachment: fixed;
+	border-radius: 16px 16px 0 0;
+	position: relative;
+	display: flex;
+	flex-direction: column;
+}
+
+.group_1 {
+	position: relative;
+	width: 750rpx;
+	background-size: 100% 100%;
+	display: flex;
+	flex-direction: column;
+}
+
+.block_2 {
+	position: relative;
+	width: 750rpx;
+	margin-bottom: 10rpx;
+	display: flex;
+	flex-direction: column;
+}
+
+.text_2 {
+	width: 319rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(153, 153, 153, 1);
+	font-size: 24rpx;
+	font-family: PingFang-SC-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 21rpx 281rpx 0 23rpx;
+}
+.image_3 {
+	width: 650rpx;
+	height: 240rpx;
+	margin: 52rpx 0 0 52rpx;
+}
+.group_2 {
+	width: 686rpx;
+	height: 362rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 10rpx 0 0 32rpx;
+}
+.box_1 {
+	height: 362rpx;
+
+	display: flex;
+	flex-direction: column;
+	width: 179rpx;
+}
+.text-wrapper_1 {
+	width: 179rpx;
+	height: 362rpx;
+
+	display: flex;
+	flex-direction: column;
+}
+.text_3 {
+	width: 117rpx;
+	height: 28rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 30rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+	margin: 167rpx 0 0 31rpx;
+}
+.box_2 {
+	width: 479rpx;
+	height: 358rpx;
+	margin-top: 3rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+.block_3 {
+	/* width: 686rpx; */
+	height: 440rpx;
+	flex-direction: row;
+	display: flex;
+	/* justify-content: space-between; */
+}
+.block_4 {
+	height: 238rpx;
+	background: url(https://lanhu.oss-cn-beijing.aliyuncs.com/psac2t2wtcm0h8semihka78i97rgy3z0k9d0vxy3322c323xr5f050ebd-fda6-4691-8385-e2c10199e339) 100% no-repeat;
+	background-size: 100% 100%;
+	display: flex;
+	flex-direction: column;
+	width: 225rpx;
+}
+.text-wrapper_2 {
+	height: 238rpx;
+	background: url(https://lanhu.oss-cn-beijing.aliyuncs.com/ps6gz05f11kuxiggb90g6bbl0ya23uwhfrthp4zs0v1hdgf1or45037c24-24f9-4599-ad7f-a6f45ff324f0) 100% no-repeat;
+	background-size: 100% 100%;
+	display: flex;
+	flex-direction: column;
+	width: 225rpx;
+}
+.text_4 {
+	width: 117rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 30rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+	margin: 104rpx 0 0 53rpx;
+}
+.text-wrapper_3 {
+	height: 238rpx;
+	/* background: url(https://lanhu.oss-cn-beijing.aliyuncs.com/ps5k0mpe16d8bvgqfrqxr3q4pqkie5qaor6ga6dg9pyyrgrpb96ba7e5d9-a3dc-4877-a3b6-f0818f0b8455) 100% no-repeat; */
+	/* background-size: 100% 100%; */
+	display: flex;
+	flex-direction: column;
+	width: 225rpx;
+	margin-left: 30rpx;
+}
+.text_5 {
+	width: 118rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 30rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+	margin: 104rpx 0 0 53rpx;
+}
+.button_1 {
+	height: 120rpx;
+	/* background: url(https://lanhu.oss-cn-beijing.aliyuncs.com/psua2f69ld98fzjjor2xu0ehhq2vwe9udidkige5zsdf91kyb9813eb2ef-246e-4904-898c-23cc6da2b558) 100% no-repeat;
+	background-size: 100% 100%; */
+	/* margin-top: 28rpx; */
+	display: flex;
+	flex-direction: column;
+	width: 479rpx;
+}
+.text-wrapper_4 {
+	height: 92rpx;
+	background: url(https://lanhu.oss-cn-beijing.aliyuncs.com/pssewpti4kxwasjornjm2vyq8r467p66r8k2ra76301pxpqfr3b9eaf00-08f2-40bd-887f-0ebafa6a232e) 100% no-repeat;
+	background-size: 100% 100%;
+	display: flex;
+	flex-direction: column;
+	width: 479rpx;
+}
+.text_6 {
+	width: 114rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 30rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin: 33rpx 0 0 183rpx;
+}
+.text-wrapper_5 {
+	width: 650rpx;
+	height: 28rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 32rpx 0 32rpx 49rpx;
+}
+.text_7 {
+	width: 110rpx;
+	height: 28rpx;
+	overflow-wrap: break-word;
+	color: rgba(18, 18, 18, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text_8 {
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 7rpx;
+}
+.group_3 {
+	/* width: 686rpx; */
+	display: flex;
+	flex-flow: wrap;
+	margin-left: 30rpx;
+	/* margin: 33rpx 0 0 32rpx; */
+}
+.group_4 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	height: 440rpx;
+	width: 330rpx;
+	display: flex;
+	margin-bottom: 25rpx;
+	margin-right: 25rpx;
+	flex-direction: column;
+}
+.image-wrapper_1 {
+	width: 140rpx;
+	height: 140rpx;
+	display: flex;
+	flex-direction: row;
+
+	margin: 38rpx 0 0 95rpx;
+}
+.single-avatar_1 {
+	width: 100%;
+	height: 100%;
+	border-radius: 50%;
+}
+.block_5 {
+	width: 118rpx;
+	height: 62rpx;
+	display: flex;
+	flex-direction: row;
+	margin: 26rpx 0 0 80rpx;
+}
+.text-group_1 {
+	width: 118rpx;
+	height: 62rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+.text_9 {
+	width: 118rpx;
+	height: 30rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
+}
+.text_10 {
+	width: 47rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 9rpx 0 0 34rpx;
+}
+.block_6 {
+	width: 245rpx;
+	height: 24rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin-left: 42rpx;
+}
+.image-text_1 {
+	width: 163rpx;
+	height: 24rpx;
+	flex-direction: row;
+	align-items: center;
+	display: flex;
+	justify-content: space-between;
+}
+.text-group_2 {
+	width: 95rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-ExtraLight;
+	font-weight: 250;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin-top: 2rpx;
+}
+
+.block_7 {
+	width: 156rpx;
+	height: 45rpx;
+	display: flex;
+	flex-direction: row;
+	margin: 23rpx 0 59rpx 87rpx;
+}
+.button_2 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	height: 45rpx;
+	display: flex;
+	flex-direction: column;
+	width: 156rpx;
+}
+.text_11 {
+	width: 46rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(248, 226, 175, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 11rpx 0 0 25rpx;
+}
+.text-wrapper_6 {
+	width: 651rpx;
+	height: 28rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 20rpx 0 0 48rpx;
+}
+.text_21 {
+	width: 111rpx;
+	height: 28rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.text_22 {
+	color: rgba(102, 102, 102, 1);
+	font-size: 24rpx;
+	line-height: 24rpx;
+	margin-top: 7rpx;
+}
+.group_13 {
+	background-color: rgba(255, 255, 255, 1);
+	border-radius: 10rpx;
+	width: 686rpx;
+	height: 170rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 28rpx 0 0 32rpx;
+}
+.image_12 {
+	width: 307rpx;
+	height: 171rpx;
+}
+.group_14 {
+	width: 130rpx;
+	height: 122rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+	margin: 29rpx 0 0 20rpx;
+}
+.text-group_9 {
+	width: 111rpx;
+	height: 61rpx;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+.text_23 {
+	width: 110rpx;
+	height: 26rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+	margin-left: 1rpx;
+}
+.text_24 {
+	width: 107rpx;
+	height: 21rpx;
+	overflow-wrap: break-word;
+	color: rgba(102, 102, 102, 1);
+	font-size: 22rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 22rpx;
+	margin-top: 14rpx;
+}
+.text-wrapper_7 {
+	width: 125rpx;
+	height: 22rpx;
+	flex-direction: row;
+	display: flex;
+	justify-content: space-between;
+	margin: 39rpx 0 0 5rpx;
+}
+.text_25 {
+	width: 60rpx;
+	height: 20rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 20rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 20rpx;
+	margin-top: 2rpx;
+}
+.text_26 {
+	width: 56rpx;
+	height: 22rpx;
+	overflow-wrap: break-word;
+	color: rgba(202, 86, 66, 1);
+	font-size: 28rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 28rpx;
+}
+.button_6 {
+	background-color: rgba(202, 86, 66, 1);
+	border-radius: 10rpx;
+	height: 44rpx;
+	display: flex;
+	flex-direction: column;
+	width: 129rpx;
+	margin: 115rpx 18rpx 0 82rpx;
+}
+.text_27 {
+	color: rgba(248, 226, 175, 1);
+	font-size: 24rpx;
+	white-space: nowrap;
+	line-height: 45rpx;
+	margin-left: -10rpx;
+}
+
+.image_16 {
+	width: 686rpx;
+	height: 240rpx;
+	margin: 0 auto;
+}
+</style>

+ 57 - 0
service/api/common.js

@@ -0,0 +1,57 @@
+/**
+ * 授权 API
+ */
+import {
+	http
+} from '../request/main.js'
+
+/**
+ * 获取配置数据
+ * 
+ * @returns {Promise}
+ */
+export function getConfig() {
+	return http.post('/common/getConfig', {}, {
+		muteLogin: true
+	})
+}
+
+/**
+ * 获取活动列表
+ *
+ * @returns {Promise}
+ */
+// export function getActivityList(group, page, page_size) {
+// 	return http.post('/common/getActivityList', {
+// 		group,
+// 		page,
+// 		page_size
+// 	}, {
+// 		muteLogin: true
+// 	})
+// }
+export function getActivityList(activity_type, page, page_size) {
+	return http.post('/common/getActivityList', {
+		activity_type,
+		page,
+		page_size
+	}, {
+		muteLogin: true
+	})
+}
+
+/**
+ * 上传图片
+ * 
+ * @returns {Promise}
+ */
+export function uploadImage(imageUrl) {
+	return http.post('/common/uploadImage', {
+		file: {
+			file: imageUrl,
+			name: 'image'
+		}
+	}, {
+		uploadFile: true
+	})
+}

+ 105 - 0
service/api/examine.js

@@ -0,0 +1,105 @@
+/**
+ * 授权 API
+ */
+import {
+	http
+} from '../request/main.js'
+/**
+ * 开始答题
+ * 
+ * @returns {Promise}
+ */
+export function startChallenge() {
+	return http.post('/examine/startChallenge')}
+
+/**
+ * 获取新题
+ * 
+ * @returns {Promise}
+ */
+export function getNew(session_id) {
+	return http.post('/examine/getNew', {
+		session_id
+	})}
+
+/**
+ * 提交答案
+ * 
+ * @returns {Promise}
+ */
+export function submitAnswer(id, answer) {
+	return http.post('/examine/submitAnswer', {
+		id,
+		answer
+	})
+}
+
+/**
+ * 获取考核结果
+ * 
+ * @returns {Promise}
+ */
+export function getSummary(session_id) {
+	return http.post('/examine/getSummary', {
+		session_id
+	})
+}
+
+/**
+ * 获取考核历史
+ * 
+ * @returns {Promise}
+ */
+export function getHistory(session_id, page, page_size) {
+	return http.post('/examine/getHistory', {
+		session_id,
+		page,
+		page_size
+	})
+}
+
+/**
+ * 获取答题结果
+ * 
+ * @returns {Promise}
+ */
+export function getResult(id) {
+	return http.post('/examine/getResult', {
+		id
+	})
+}
+
+/**
+ * 获取排行数据
+ * 
+ * @returns {Promise}
+ */
+export function getTopList(group, page, page_size) {
+	return http.post('/examine/getTopList', {
+		group,
+		page,
+		page_size
+	})
+}
+
+/**
+ * 获取我的排行
+ * 
+ * @returns {Promise}
+ */
+export function getMineTop(group) {
+	return http.post('/examine/getMineTop', {
+		group
+	})
+}
+
+/**
+ * 获取全部排行和个人排行
+ * 比赛专用
+ * 
+ * @returns {Promise}
+ */
+export function getRankingList() {
+	return http.post('/examine/getRankingList', {
+	})
+}

+ 98 - 0
service/api/gift.js

@@ -0,0 +1,98 @@
+/**
+ * 授权 API
+ */
+import {
+	http
+} from '../request/main.js';
+
+
+/**
+ * 获取整体数据
+ * 
+ * @returns {Promise}
+ */
+export function getWrapData() {
+	return http.post('/gift/getWrapData');
+}
+
+/**
+ * 获取奖品详情
+ * 
+ * @returns {Promise}
+ */
+export function getDetail(id) {
+	return http.post('/gift/getDetail', {
+		id
+	});
+}
+
+
+/**
+ * 获取兑换预览
+ * 
+ * @returns {Promise}
+ */
+export function getPreview(gift_id, gift_spec_id) {
+	return http.post('/gift/getPreview', {
+		gift_id,
+		gift_spec_id
+	});
+}
+
+/**
+ * 进行兑换
+ * 
+ * @returns {Promise}
+ */
+export function exchange(formData) {
+	return http.post('/gift/exchange', formData);
+}
+
+
+/**
+ * 取消订单
+ * 
+ * @returns {Promise}
+ */
+export function orderCancel(order_id) {
+	return http.post('/gift/orderCancel', {
+		order_id
+	});
+}
+
+
+
+/**
+ * 获取兑换列表
+ * 
+ * @returns {Promise}
+ */
+export function getOrderList(group, page, page_size) {
+	return http.post('/gift/getOrderList', {
+		group,
+		page,
+		page_size
+	});
+}
+
+/**
+ * 获取兑换详情
+ * 
+ * @returns {Promise}
+ */
+export function getOrderDetail(id) {
+	return http.post('/gift/getOrderDetail', {
+		id
+	});
+}
+
+/**
+ * 获取物流动态
+ * 
+ * @returns {Promise}
+ */
+export function getExpressFeed(id) {
+	return http.post('/gift/getExpressFeed', {
+		id
+	});
+}

+ 57 - 0
service/api/mock.js

@@ -0,0 +1,57 @@
+/**
+ * 模拟 API
+ */
+import {
+	http
+} from '../request/index.js' // 请求拦截
+import Cache from '../../common/cache.js'
+
+/**
+ * 数据列表
+ * 
+ * @returns {Promise}
+ */
+export function getList() {
+	return new Promise(resolve => {
+		const cacheKey = 'data:list'		const data = Cache.get(cacheKey)		if (data) {
+			resolve([0, data])		} else {
+			setTimeout(() => {
+				resolve([0, [{
+					id: 1,
+					type: 1
+				}, {
+					id: 2,
+					type: 2
+				}, {
+					id: 3,
+					type: 1
+				}, {
+					id: 4,
+					type: 2
+				}]])			}, 500)			// http.get('/v1/data/list').then(([err, res]) => {
+			// 	if (! err) {
+			// 		Cache.put(cacheKey, res, 60)			// 		resolve([0, res])			// 	} else {
+			// 		resolve([err])			// 	}	
+			// })		}
+	})}
+
+/**
+ * 数据详情
+ * 
+ * @returns {Promise}
+ */
+export function getDetail(id, refresh) {
+	return new Promise(resolve => {
+		const cacheKey = 'data:detail:' + id		const data = Cache.get(cacheKey)		if (data && !refresh) {
+			resolve([0, data])		} else {
+			setTimeout(() => {
+				resolve([0, {
+					id: 1,
+					type: 1,
+					name: '测试内容'
+				}])			}, 500)			// http.get('/v1/data/detail').then(([err, res]) => {
+			// 	if (! err) {
+			// 		Cache.put(cacheKey, res, 60)			// 		resolve([0, res])			// 	} else {
+			// 		resolve([err])			// 	}	
+			// })		}
+	})}

+ 13 - 0
service/api/page.js

@@ -0,0 +1,13 @@
+/**
+ * 授权 API
+ */
+import {
+	http
+} from '../request/main.js'
+/**
+ * 获取首页数据
+ * 
+ * @returns {Promise}
+ */
+export function getHomeData() {
+	return http.post('/page/getHomeData')}

+ 163 - 0
service/api/user.js

@@ -0,0 +1,163 @@
+/**
+ * 授权 API
+ */
+import {
+	http
+} from '../request/main.js'
+
+/**
+ * 用户登录 - 姓名登录码
+ * 
+ * @returns {Promise}
+ */
+export function loginByNameCode(name, code, wx_code) {
+	return http.post('/user/loginByNameCode', {
+		name,
+		code,
+		wx_code
+	}, {
+		muteLogin: true
+	})
+}
+
+/**
+ * 用户登录 - 编号登录码
+ *
+ * @returns {Promise}
+ */
+export function loginByNumberCode(number, code, wx_code) {
+	return http.post('/user/loginByNumberCode', {
+		number,
+		code,
+		wx_code
+	}, {
+		muteLogin: true
+	})
+}
+
+/**
+ * 用户登录 - 手机验证码
+ * 
+ * @returns {Promise}
+ */
+export function loginByPhoneCaptcha(phone, captcha, wx_code) {
+	return http.post('/user/loginByPhoneCaptcha', {
+		phone,
+		captcha,
+		wx_code
+	}, {
+		muteLogin: true
+	})
+}
+
+/**
+ * 用户登录 - 微信快捷登录
+ * 
+ * @returns {Promise}
+ */
+export function loginByWechatPhone(encrypted_data, iv, code, wx_code) {
+	return http.post('/user/loginByWechatPhone', {
+		encrypted_data,
+		iv,
+		code,
+		wx_code
+	}, {
+		muteLogin: true
+	})
+}
+
+/**
+ * 小程序自动登录
+ * 
+//  * @returns {Promise}
+//  */
+export function wechatAutoLogin(wx_code) {
+	return http.post('/user/wechatAutoLogin', {
+		wx_code
+	}, {
+		muteLogin: true
+	})
+}
+
+
+/**
+ * 发送手机验证吗
+ * 
+ * @returns {Promise}
+ */
+export function sendPhoneCaptcha(phone, wx_code, muteLogin) {
+	return http.post('/user/sendPhoneCaptcha', {
+		phone,
+		wx_code
+	}, {
+		muteLogin: muteLogin
+	})
+}
+
+
+/**
+ * 用户登出
+ * 
+ * @returns {Promise}
+ */
+export function logout() {
+	return http.post('/user/logout')
+}
+
+/**
+ * 更新用户信息
+ * 
+ * @returns {Promise}
+ */
+export function updateUserInfo(avatar_url) {
+	return http.post('/user/updateUserInfo', {
+		avatar_url
+	})
+}
+
+/**
+ * 获取用户信息
+ * 
+ * @returns {Promise}
+ */
+export function getUserInfo() {
+	return http.post('/user/getUserInfo')
+}
+
+/**
+ * 修改登录码
+ * 
+ * @returns {Promise}
+ */
+export function changeCode(oldCode, newCode) {
+	return http.post('/user/changeCode', {
+		oldCode,
+		newCode
+	})
+}
+
+/**
+ * 修改手机号
+ * 
+ * @returns {Promise}
+ */
+export function changePhone(phone, captcha) {
+	return http.post('/user/changePhone', {
+		phone,
+		captcha
+	})
+}
+
+/**
+ * 修改手机号 - 授权微信手机号
+ * 
+ * @returns {Promise}
+ */
+export function changeWechatPhone(encrypted_data, iv, code, wx_code) {
+	return http.post('/user/changeWechatPhone', {
+		encrypted_data,
+		iv,
+		code,
+		wx_code
+	})
+}

+ 7 - 0
service/config.js

@@ -0,0 +1,7 @@
+import * as Config from '../config/config.js'
+let baseUrl =Config.baseUrl+'/addons/yunexamine'
+
+export default {
+	baseUrl
+}
+

+ 234 - 0
service/request/main.js

@@ -0,0 +1,234 @@
+import store from '../../store' // 状态管理
+import {
+	encodeRedirectUrl
+} from '../../common/util.js'
+import Request from './request.js'
+import Config from '../config.js'
+import {
+	wechatAutoLogin
+} from '../api/user.js';
+
+export const http = new Request();
+
+// 设置全局配置
+http.setConfig((config) => {
+	config.baseUrl = Config.baseUrl;
+	config.header = {
+		'Content-Type': 'application/json;charset=UTF-8'
+	};
+
+	return config
+})
+
+
+// 请求之前拦截器
+http.interceptor.beforeRequest((config, cancel) => {
+	// console.log('请求前拦截', config.url, config)
+
+	// 登录校验
+	let accessToken = store.getters.accessToken;
+	let activityId = store.getters.activityId;
+	// console.log('get.accessToken', accessToken, activityId);
+	if (!config.muteLogin) {
+		if (!accessToken) {
+			console.error('needLogin request');
+			cancel('登录过期,尝试重试'); // 取消请求
+			console.info('needLogin request', 'silentReload');
+			silentReload(config.curd === 'save');
+			return;
+		}
+		config.header['token'] = accessToken;
+
+		// config.url += '?token=' + accessToken;
+		// config.header['Cookie'] = 'token=' + accessToken;  // uploadFile时,不能传header,慎用这种方式
+	}
+	config.url += (config.url.indexOf('?') === -1 ? '?' : '&') + 'activity_id=' + activityId;
+
+	return config;
+})
+
+// 请求之后拦截器 
+http.interceptor.afterRequest((response) => {
+	// console.log('请求后拦截', response);
+
+	// 系统错误
+	if (response.statusCode === 500) {
+		console.error('系统错误');
+		setTimeout(() => {
+			uni.showToast({
+				title: '系统错误',
+				icon: 'none',
+				mask: true,
+				duration: 2000
+			})
+		}, 50);
+		return [response];
+	}
+
+	let data = response.data;
+
+	// 网络错误
+	if (!data) {
+		console.error('网络错误');
+		setTimeout(() => {
+			uni.showToast({
+				title: '网络错误',
+				icon: 'none',
+				mask: true,
+				duration: 2000
+			})
+		}, 50)
+		return [response];
+	}
+
+	if (typeof data === 'string') {
+		data = JSON.parse(data)
+	}
+
+	// 正常请求
+	if (data.code === 1) {
+		return [0, data.data || data.msg];
+	}
+
+	// 系统错误
+	console.warn('invalid request', data.msg);
+	switch (data.code) {
+		case 401: // 认证失败
+			console.error('needLogin 401');
+			store.commit('delAccessToken'); // 删除token
+			console.info('needLogin 401', 'silentReload');
+			silentReload(response.config.curd === 'save');
+			break;
+		case 402: // 小程序自动登录失败
+			break;
+		default: // 错误提示
+			setTimeout(() => {
+				uni.showToast({
+					title: data.msg || '网络错误',
+					icon: 'none',
+					mask: true,
+					duration: 2000
+				})
+			}, 50)
+			if (data.code === 403) { // 活动无效
+				store.commit('delAccessToken'); // 删除token
+				store.commit('delActivityId'); // 删除活动ID
+				smartLogin('');
+			}
+			break;
+	}
+
+	return [response];
+})
+
+/**
+ * 获取 login code
+ */
+export function silentReload(warning = false, redirectUrl = null) {
+	if (warning) {
+		setTimeout(() => {
+			uni.showToast({
+				title: '鉴权失败,请重新操作',
+				icon: 'none',
+				mask: true,
+				duration: 2000
+			})
+		}, 50)
+		return false
+	}
+	if (store.getters.isLock('silentReload')) {
+		return false
+	}
+	console.info('needLogin silentReload')
+	store.commit('lock', 'silentReload')
+	if (redirectUrl === null) {
+		const pages = getCurrentPages()
+		const currentPage = pages[pages.length - 1]
+		redirectUrl = encodeRedirectUrl(currentPage.route, currentPage.options)
+	}
+
+	// #ifdef  MP-WEIXIN
+	// 微信小程序自动登录
+	uni.reLaunch({
+		url: '/pages/user/login?redirect=' + redirectUrl
+	})
+	/* #endif */
+
+	// #ifdef  H5
+	// 跳到登录页面或活动列表页
+	smartLogin(redirectUrl)
+	/* #endif */
+
+	return true
+}
+
+/**
+ * 获取 login code
+ */
+export function smartLogin(redirectUrl, loginCheck) {
+	if (store.getters.activityId) { // 有缓存的活动ID
+		if (!loginCheck) {
+			// 直接到登录页面
+			uni.reLaunch({
+				url: '/pages/user/login?redirect=' + redirectUrl
+			})
+		}
+
+		return true;
+	}
+	const globalConfig = store.getters.globalConfig
+
+	// 配置未正确加载
+	if (!globalConfig) {
+		setTimeout(() => {
+			uni.showToast({
+				title: '数据加载失败,请点击右上角“重新进入小程序“',
+				icon: 'none',
+				mask: true,
+				duration: 2000
+			})
+		}, 50)
+		return true;
+	}
+
+	// 存在默认活动
+	if (globalConfig.default_activity) {
+		if (!loginCheck) {
+			// 直接到登录页面
+			uni.reLaunch({
+				url: '/answer_pages/user/login?redirect=' + redirectUrl
+			})
+		}
+		return true;
+	}
+
+	// 可以选择活动
+	if (globalConfig.select_activity) {
+		// 直接到活动列表
+		uni.reLaunch({
+			url: '/answer_pages/home/dashboard'
+		})
+		return true;
+	}
+
+	// 需要扫码进入
+	setTimeout(() => {
+		uni.reLaunch({
+			url: '/answer_pages/user/tips'
+		})
+	}, 50)
+
+	return true
+}
+export function getRedirectUrl() {
+	let redirectUrl = '/pages/home/index'
+	const pages = getCurrentPages()
+	const currentPage = pages[pages.length - 1]
+	if (currentPage) {
+		if (currentPage.$page) {
+			redirectUrl = currentPage.$page.fullPath
+		}
+	}
+
+	return redirectUrl
+}

+ 156 - 0
service/request/request.js

@@ -0,0 +1,156 @@
+export default class Request {
+	// 判断url是否为绝对路径
+	static absolutelyUrl(url) {
+		return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)
+	};
+
+	// 发起请求前
+	static beforeRequest(config) {
+		return config
+	};
+
+	// 发起请求后
+	static afterRequest(response) {
+		return response
+	};
+
+	// 基本配置
+	config = {
+		baseUrl: '',
+		header: {
+			'Content-Type': 'application/json;charset=UTF-8'
+		},
+		method: 'GET',
+		dataType: 'json',
+		responseType: 'text',
+		success() {},
+		fail() {},
+		complete() {}
+	};
+
+	// 过滤器
+	interceptor = {
+		beforeRequest(callback) {
+			if (callback) {
+				Request.beforeRequest = callback
+			}
+		},
+		afterRequest(callback) {
+			if (callback) {
+				Request.afterRequest = callback
+			}
+		}
+	};
+
+	// 设置配置
+	setConfig(callback) {
+		this.config = callback(this.config)
+	}
+
+	// 发起请求
+	request(options = {}) {
+		// 基本参数
+		options.baseUrl = options.baseUrl || this.config.baseUrl
+		options.dataType = options.dataType || this.config.dataType
+		options.url = Request.absolutelyUrl(options.url) ? options.url : (options.baseUrl + options.url)
+		options.data = options.data || {}
+		options.header = options.header || this.config.header
+		options.method = options.method || this.config.method
+
+		// console.log(options.header);
+		// options.
+
+		// promise 请求
+		return new Promise((resolve, reject) => {
+			let execute = true
+			let _config = null
+			// 请求完成
+			options.complete = (response) => {
+				response.config = _config
+				return resolve(Request.afterRequest(response))
+			}
+			// 默认配置 + 用户配置【复制作用】
+			let mConfig = {
+				...this.config,
+				...options
+			}
+			// 取消请求 - 回调
+			let cancel = (msg = 'request cancel') => {
+				execute = false
+				return resolve([{
+					config: mConfig,
+					data: {
+						code: 0,
+						msg: msg
+					}
+				}])
+			}
+			// 默认配置 + 用户配置 + 初始配置【复制作用】
+			_config = {
+				...mConfig,
+				...Request.beforeRequest(mConfig, cancel)
+			}
+			// 是否取消请求【如果execute == false, 那么已经resolve了,所以不需要return resolve】
+			if (!execute) return
+
+			// 发起请求
+			if (_config.hasOwnProperty('uploadFile')) {
+				const data = _config.data
+				let tConfig = {
+					url: _config.url,
+					filePath: data.file.file,
+					name: data.file.name,
+					formData: data.form,
+					// #ifdef  MP-WEIXIN
+					header: _config.header,
+					// #endif
+					success: _config.success,
+					fail: _config.fail,
+					complete: _config.complete,
+				}
+				uni.uploadFile(tConfig)
+			} else {
+				uni.request(_config)
+			}
+		})
+	};
+
+	// 接口请求 - 支持重试
+	autoRetry(options, retryMax = 3) {
+		// console.log('autoRetry', options, retryMax);
+		return new Promise((resolve, reject) => {
+			if (retryMax <= 0) {
+				return resolve(['网络错误']);
+			}
+			if (retryMax == 2) {
+				// console.log('this.request exect');
+				this.request(options).then(([err, res]) => {
+					// console.log('this.request', err, res);
+					if (!err) {
+						resolve([err, res]);
+					} else {
+						this.autoRetry(options, retryMax - 1);
+					}
+				});
+			} else {
+				return this.autoRetry(options, retryMax - 1);
+			}
+		});
+	}
+
+	// GET 请求
+	get(url, data, options = {}) {
+		options.url = url
+		options.data = data
+		options.method = 'GET'
+		return this.request(options)
+	}
+
+	// POST 请求
+	post(url, data, options = {}) {
+		options.url = url
+		options.data = data
+		options.method = 'POST'
+		return this.request(options)
+	}
+}

BIN=BIN
static/image/13-系统消息-icon.png


BIN=BIN
static/image/2019-07-03000000000018.png


BIN=BIN
static/image/BSV.png


BIN=BIN
static/image/baseLogo.png


BIN=BIN
static/image/cs_bjx.png


BIN=BIN
static/image/flower.png


BIN=BIN
static/image/fx.png


BIN=BIN
static/image/hd.png


BIN=BIN
static/image/hh.png


BIN=BIN
static/image/home_a.png


BIN=BIN
static/image/hs.png


BIN=BIN
static/image/jf.png


BIN=BIN
static/image/kctp.png


BIN=BIN
static/image/mn.png


BIN=BIN
static/image/star.png


BIN=BIN
static/image/sz.png


BIN=BIN
static/image/tg.png


BIN=BIN
static/image/传统吉祥纹样17.png


BIN=BIN
static/image/余额.png


BIN=BIN
static/image/圆角矩形 840 拷贝.png


BIN=BIN
static/image/椭圆 839.png


BIN=BIN
static/image/账期 拷贝.png


BIN=BIN
static/image/账期(1).png


+ 0 - 0
static/image/账期(2).png


Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio