ソースを参照

工作台静态页面

lgh 1 年間 前
コミット
2e10b99968
47 ファイル変更37241 行追加5995 行削除
  1. 27 0
      .gitignore
  2. 34 2
      App.vue
  3. 171 0
      components/nav-bar/nav-bar.vue
  4. 21 1
      main.js
  5. 14 2
      manifest.json
  6. 120 0
      package-lock.json
  7. 43 5
      pages.json
  8. 208 0
      pages/gallery/index.vue
  9. 0 52
      pages/index/index.vue
  10. 461 0
      pages/mall/mallRecharge/index.vue
  11. 67 0
      pages/news/index.vue
  12. 9 0
      pages/order/index.vue
  13. 9 0
      pages/statistics/index.vue
  14. 23 0
      static/icon/iconfont.css
  15. 9 0
      static/style/common.scss
  16. 15 0
      store/index.js
  17. 45 0
      store/modules/emptyStatus.js
  18. 43 0
      store/modules/info.js
  19. 3 1
      uni.scss
  20. 25 0
      uni_modules/uni-table/changelog.md
  21. 455 0
      uni_modules/uni-table/components/uni-table/uni-table.vue
  22. 29 0
      uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
  23. 90 0
      uni_modules/uni-table/components/uni-td/uni-td.vue
  24. 511 0
      uni_modules/uni-table/components/uni-th/filter-dropdown.vue
  25. 285 0
      uni_modules/uni-table/components/uni-th/uni-th.vue
  26. 129 0
      uni_modules/uni-table/components/uni-thead/uni-thead.vue
  27. 179 0
      uni_modules/uni-table/components/uni-tr/table-checkbox.vue
  28. 171 0
      uni_modules/uni-table/components/uni-tr/uni-tr.vue
  29. 9 0
      uni_modules/uni-table/i18n/en.json
  30. 9 0
      uni_modules/uni-table/i18n/es.json
  31. 9 0
      uni_modules/uni-table/i18n/fr.json
  32. 12 0
      uni_modules/uni-table/i18n/index.js
  33. 9 0
      uni_modules/uni-table/i18n/zh-Hans.json
  34. 9 0
      uni_modules/uni-table/i18n/zh-Hant.json
  35. 83 0
      uni_modules/uni-table/package.json
  36. 13 0
      uni_modules/uni-table/readme.md
  37. 4 26
      unpackage/dist/dev/mp-weixin/app.js
  38. 44 1
      unpackage/dist/dev/mp-weixin/app.json
  39. 2 2
      unpackage/dist/dev/mp-weixin/app.wxss
  40. 33801 5850
      unpackage/dist/dev/mp-weixin/common/vendor.js
  41. 0 19
      unpackage/dist/dev/mp-weixin/pages/index/index.js
  42. 0 4
      unpackage/dist/dev/mp-weixin/pages/index/index.json
  43. 0 1
      unpackage/dist/dev/mp-weixin/pages/index/index.wxml
  44. 0 23
      unpackage/dist/dev/mp-weixin/pages/index/index.wxss
  45. 20 3
      unpackage/dist/dev/mp-weixin/project.config.json
  46. 12 3
      unpackage/dist/dev/mp-weixin/project.private.config.json
  47. 9 0
      unpackage/dist/dev/mp-weixin/static/style/common.scss

+ 27 - 0
.gitignore

@@ -0,0 +1,27 @@
+.DS_Store
+node_modules/
+unpackage/
+dist/
+.history
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.project
+.idea
+.hbuilderx
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw*
+
+apis/user.js.rej

+ 34 - 2
App.vue

@@ -1,7 +1,32 @@
 <script>
 	export default {
 		onLaunch: function() {
-			console.log('App Launch')
+			const that = this
+			// 存储手机信息
+			uni.getSystemInfo({
+				success(res) {
+					that.$store.commit('SET_SYSTEMINFO', res)
+				}
+			})
+			if (this.$platform === 'APP-PLUS') {
+				const {
+					osName, // 操作系统
+					osVersion // 操作系统版本号
+				} = that.$store.state.info.systemInfo
+				plus.runtime.getProperty(plus.runtime.appid, (info) => {
+					//版本号
+					const {
+						version,
+						versionCode,
+					} = info
+					that.$store.commit('SET_VERSIONINFO', {
+						version: version,
+						versionCode: versionCode,
+						osName: osName,
+						osVersion: osVersion
+					})
+				})
+			}
 		},
 		onShow: function() {
 			console.log('App Show')
@@ -12,6 +37,13 @@
 	}
 </script>
 
-<style>
+<style lang="scss">
+	// @import '@/static/icon/iconfont.css';
+	@import '@/static/style/common.scss';
+
 	/*每个页面公共css */
+	page {
+		height: 100%;
+		background-color: $bg-color-main;
+	}
 </style>

+ 171 - 0
components/nav-bar/nav-bar.vue

@@ -0,0 +1,171 @@
+<template>
+	<view>
+		<view class="nav-bar-wrapper left-0 top-0 width100" :class="fixed ? 'position-f' : 'position-a'"
+			:style="{background: background, borderColor: borderColor}">
+			<view class="status-bar" :style="{height: `${statusBarHeight}px`}"></view>
+			<view class="position-r">
+				<view v-if="!custom" class="height100 width100 flex aic jcc">
+					<view v-if="iconType !== 'none'"
+						class="position-a flex aic jcc icon-wrapper height100 left-0 text-center"
+						@click='leftIconClick'>
+						<re-icon :color="iconColor" v-if="iconName" :name="iconName"
+							:customStyle="{ fontSize: '40rpx', fontWeight: 'bold' }"></re-icon>
+					</view>
+					<text class="bold ellipsis title" :style="{color: titleColor}">{{titleCom}}</text>
+				</view>
+				<slot v-else></slot>
+			</view>
+		</view>
+		<view v-if="!noPlaceholder" class="placeholder" :style="{height: `${navBarHeight}px`}"></view>
+	</view>
+</template>
+
+<script>
+	import {
+		toRpx
+	} from '@/utils/calculate'
+	import {
+		isEmpty
+	} from '@/utils/check-types.js'
+	export default {
+		name: "nav-bar",
+		props: {
+			fixed: { // 是否是fixed定位
+				type: Boolean,
+				default: true
+			},
+			title: String, // 标题
+			custom: Boolean, // 自定义
+			iconType: { // back 返回 home 主页 none 无icon
+				type: String,
+				default: ''
+			},
+			icon: String, // 自定义icon
+			iconColor: {
+				type: String,
+				default: '#152129',
+			},
+			background: { // 背景色
+				type: String,
+				default: '#fff'
+			},
+			borderColor: {
+				type: String,
+				default: '#eee'
+			},
+			titleColor: {
+				type: String,
+				default: '#333'
+			},
+			noPlaceholder: Boolean // 没有占位符
+		},
+		data() {
+			return {
+				isNonePage: false, // 是否有上一个页面
+				navBarHeight: uni.getStorageSync('navBarHeight') // 导航高度
+			}
+		},
+		computed: {
+			// icon类型
+			iconName() {
+				if (this.icon) {
+					return this.icon
+				}
+				if (this.iconType === 'back') {
+					return 'icon-fanhui'
+				}
+				if (this.iconType === 'home') {
+					return 'icon-home'
+				}
+				if (!this.icontype) {
+					const pages = getCurrentPages() //获取加载的页面
+					const currentPage = pages[pages.length - 2] //获取上个页面的对象
+					if (currentPage && !currentPage.route.includes('flashScreen')) {
+						return 'icon-fanhui'
+					} else {
+						return 'icon-home'
+					}
+				}
+			},
+			// 设置title
+			titleCom() {
+				if (this.title) {
+					if (this.title === 'none') {
+						return ''
+					}
+					return this.title
+				} else {
+					let fullPath = this.$Route.path,
+						thisOne = ROUTES.find((item) => item.path == fullPath)
+					return thisOne.style.navigationBarTitleText
+				}
+			},
+			// 状态高度
+			statusBarHeight() {
+				return this.$store.state.info.systemInfo?.statusBarHeight
+			},
+			// 胶囊高度-小程序
+			menuButtonHeight() {
+				if (this.$platform !== 'MP-WEIXIN') {
+					return 44
+				} else {
+					let menuButtonInfo = uni.getMenuButtonBoundingClientRect()
+					if (menuButtonInfo && menuButtonInfo.height) {
+						return menuButtonInfo.height + (menuButtonInfo.top - this.statusBarHeight) * 2
+					} else {
+						return 44
+					}
+				}
+			},
+		},
+		mounted() {
+			let cacheHeight = null
+			if (this.$platform === 'APP-PLUS') {
+				cacheHeight = this.navBarHeight?.data
+			} else {
+				cacheHeight = this.placeholderHeigh
+			}
+			if (cacheHeight) {
+				return
+			} else {
+				this.$nextTick(() => {
+					const navBarHeight = this.menuButtonHeight + this.statusBarHeight + 1 // 1border高度
+					uni.setStorageSync('navBarHeight', navBarHeight)
+					this.navBarHeight = navBarHeight
+				})
+			}
+		},
+		methods: {
+			// 左侧图标点击
+			leftIconClick() {
+				if (this.iconName === 'icon-fanhui') {
+					this.$Router.back()
+				} else if (this.iconName === 'icon-home') {
+					this.$Router.replaceAll({
+						name: 'bus'
+					})
+				} else {
+					this.$emit('iconHandle')
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.nav-bar-wrapper {
+		color: $uni-text-color;
+		z-index: 9999;
+		border-bottom: 1rpx solid #eee;
+
+		.title {
+			max-width: 400rpx;
+		}
+	}
+
+	.icon-wrapper {
+		left: 0;
+		color: #666;
+		width: 80rpx;
+	}
+</style>

+ 21 - 1
main.js

@@ -2,10 +2,30 @@ import App from './App'
 
 // #ifndef VUE3
 import Vue from 'vue'
-import './uni.promisify.adaptor'
+import store from '@/store'
+import uView from '@/plugins/uview-ui'
+// import '@/utils/preCheck.js'
+import '@/utils/prototype.js'
+import platform from "@/utils/platform" // 平台判断方法
+import getEnv from "@/utils/env" // 获取环境变量
+import mixin from "mixins/global.js"
+
+Vue.use(uView)
+
 Vue.config.productionTip = false
 App.mpType = 'app'
+Vue.prototype.$store = store
+Vue.prototype.$platform = platform()
+Vue.prototype.$ENV = getEnv()
+Vue.mixin(mixin)
+
+if (platform() === 'H5' && getEnv() !== 'prod') {
+	const vconsole = require('vconsole')
+	Vue.prototype.$vconsole = new vconsole() // 使用vconsole
+}
+
 const app = new Vue({
+	store,
   ...App
 })
 app.$mount()

+ 14 - 2
manifest.json

@@ -1,5 +1,5 @@
 {
-    "name" : "paly-center-distribution",
+    "name" : "retail-app",
     "appid" : "",
     "description" : "",
     "versionName" : "1.0.0",
@@ -68,5 +68,17 @@
     "uniStatistics" : {
         "enable" : false
     },
-    "vueVersion" : "3"
+    "vueVersion" : "2",
+    "h5":{
+        "title":"游戏币分销",
+        "devServer":{
+            "port": 80,
+            "disableHostCheck": true
+        },
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        }
+    }
 }

+ 120 - 0
package-lock.json

@@ -0,0 +1,120 @@
+{
+	"name": "name",
+	"version": "1.0.0",
+	"lockfileVersion": 2,
+	"requires": true,
+	"packages": {
+		"": {
+			"name": "name",
+			"version": "1.0.0",
+			"dependencies": {
+				"jweixin-module": "^1.6.0",
+				"vconsole": "^3.15.0"
+			}
+		},
+		"node_modules/@babel/runtime": {
+			"version": "7.23.9",
+			"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
+			"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
+			"dependencies": {
+				"regenerator-runtime": "^0.14.0"
+			},
+			"engines": {
+				"node": ">=6.9.0"
+			}
+		},
+		"node_modules/copy-text-to-clipboard": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz",
+			"integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==",
+			"engines": {
+				"node": ">=12"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/core-js": {
+			"version": "3.36.0",
+			"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz",
+			"integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==",
+			"hasInstallScript": true,
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/core-js"
+			}
+		},
+		"node_modules/jweixin-module": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/jweixin-module/-/jweixin-module-1.6.0.tgz",
+			"integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w=="
+		},
+		"node_modules/mutation-observer": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/mutation-observer/-/mutation-observer-1.0.3.tgz",
+			"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA=="
+		},
+		"node_modules/regenerator-runtime": {
+			"version": "0.14.1",
+			"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+			"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+		},
+		"node_modules/vconsole": {
+			"version": "3.15.1",
+			"resolved": "https://registry.npmjs.org/vconsole/-/vconsole-3.15.1.tgz",
+			"integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
+			"dependencies": {
+				"@babel/runtime": "^7.17.2",
+				"copy-text-to-clipboard": "^3.0.1",
+				"core-js": "^3.11.0",
+				"mutation-observer": "^1.0.3"
+			}
+		}
+	},
+	"dependencies": {
+		"@babel/runtime": {
+			"version": "7.23.9",
+			"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
+			"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
+			"requires": {
+				"regenerator-runtime": "^0.14.0"
+			}
+		},
+		"copy-text-to-clipboard": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz",
+			"integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q=="
+		},
+		"core-js": {
+			"version": "3.36.0",
+			"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz",
+			"integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw=="
+		},
+		"jweixin-module": {
+			"version": "1.6.0",
+			"resolved": "https://registry.npmjs.org/jweixin-module/-/jweixin-module-1.6.0.tgz",
+			"integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w=="
+		},
+		"mutation-observer": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/mutation-observer/-/mutation-observer-1.0.3.tgz",
+			"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA=="
+		},
+		"regenerator-runtime": {
+			"version": "0.14.1",
+			"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+			"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+		},
+		"vconsole": {
+			"version": "3.15.1",
+			"resolved": "https://registry.npmjs.org/vconsole/-/vconsole-3.15.1.tgz",
+			"integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
+			"requires": {
+				"@babel/runtime": "^7.17.2",
+				"copy-text-to-clipboard": "^3.0.1",
+				"core-js": "^3.11.0",
+				"mutation-observer": "^1.0.3"
+			}
+		}
+	}
+}

+ 43 - 5
pages.json

@@ -1,9 +1,27 @@
 {
+	"easycom": {
+		"^u-(.*)": "@/plugins/uview-ui/components/u-$1/u-$1.vue"
+	},
 	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
 		{
-			"path": "pages/index/index",
+			"path": "pages/gallery/index",
+			"style": {
+				"navigationBarTitleText": "工作台",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/statistics/index",
+			"style": {
+				"navigationBarTitleText": "统计",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/news/index",
 			"style": {
-				"navigationBarTitleText": "uni-app"
+				"navigationBarTitleText": "消息",
+				"enablePullDownRefresh": false
 			}
 		},
 		{
@@ -14,23 +32,43 @@
 			}
 		}
 	],
+	"subPackages": [{
+		"root": "pages/mall",
+		"pages": [{
+			"path": "mallRecharge/index",
+			"style": {
+				"navigationStyle": "custom",
+				"navigationBarTitleText": "确认充值"
+			}
+		}]
+	}],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",
 		"navigationBarTitleText": "uni-app",
 		"navigationBarBackgroundColor": "#F8F8F8",
 		"backgroundColor": "#F8F8F8"
 	},
-	"tabBar":{
+	"tabBar": {
 		"color": "#7A7E83",
 		"selectedColor": "#3cc51f",
 		"borderStyle": "black",
 		"backgroundColor": "#ffffff",
 		"list": [{
-			"pagePath": "pages/index/index",
+			"pagePath": "pages/gallery/index",
 			"iconPath": "",
 			"selectedIconPath": "",
 			"text": "工作台"
 		}, {
+			"pagePath": "pages/statistics/index",
+			"iconPath": "",
+			"selectedIconPath": "",
+			"text": "统计"
+		}, {
+			"pagePath": "pages/news/index",
+			"iconPath": "",
+			"selectedIconPath": "",
+			"text": "消息"
+		}, {
 			"pagePath": "pages/my/index",
 			"iconPath": "",
 			"selectedIconPath": "",
@@ -38,4 +76,4 @@
 		}]
 	},
 	"uniIdRouter": {}
-}
+}

+ 208 - 0
pages/gallery/index.vue

@@ -0,0 +1,208 @@
+<template>
+	<view class="gallery" :style="{background:'url('+ bannerImage +')#ffffff'}">
+		<view><nav-bar title="none" icon="none" background="transparent" border-color="transparent" noPlaceholder></nav-bar></view>
+		<view class="logo"><re-image imgSrc="/retail/main/img_logo.png" width="300" height="56"></re-image></view>
+		<view class="content">
+			<view class="news">
+				<view class="info flex">
+					<re-image imgSrc="/" width="104" height="104"></re-image>
+					<view class="info-text flex-column jcsa">
+						<view class="info-top flex">
+							<view class="name">王安安</view>
+							<view class="level flex aic">
+								<re-image imgSrc="/retail/main/ic_chuji.png" width="40" height="44"></re-image>
+								<view class="level-text">初级</view>
+							</view>
+						</view>
+						<view class="phone">13630639549</view>
+					</view>
+				</view>
+				<view class="news-total flex jcsa">
+					<view class="total-item">
+						<view class="item-num">156</view>
+						<view class="item-text">总销订单</view>
+					</view>
+					<view class="total-item">
+						<view class="item-num">156</view>
+						<view class="item-text">总销游戏币</view>
+					</view>
+					<view class="total-item">
+						<view class="item-num orange">¥156</view>
+						<view class="item-text">预估总收益</view>
+					</view>
+				</view>
+			</view>
+			<div class="list-title-wrapper flex jcsb aic">
+				<div class="list-title flex aic">
+					<span class="title-line"></span>
+					套餐充值
+				</div>
+				<div class="timer">
+					赠送游戏币倒计时
+					<span>
+						<span class="lb" id="day">2</span>
+						天
+						<span class="lb" id="hours">17</span>
+						时
+						<span class="lb" id="mins">56</span>
+						分
+					</span>
+				</div>
+			</div>
+			<div class="list-wrapper"></div>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	import {
+		toRpx
+	} from '@/utils/calculate.js'
+	import defaultConfig from '@/config/default.js'
+
+	export default {
+		components: {},
+		computed: {
+			statusBarHeight() {
+				return this.$store.state.info.systemInfo?.statusBarHeight
+			},
+		},
+		data() {
+			return {
+				bannerImage: defaultConfig.ossImgUrl + '/retail/main/img_bgtop.png',
+				title: 'Hello',
+				navBarHeight:uni.getStorageSync('navBarHeight')
+			}
+		},
+		onLoad() {
+
+		},
+		
+		methods: {
+
+		},
+		mounted() {
+			
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.gallery {
+		background-repeat: no-repeat !important;
+		background-size: contain !important;
+		// background-position: top;
+		width: 100%;
+		position: absolute;
+		top: 0;
+		bottom: 0;
+
+		.logo {
+			margin-top: 16rpx;
+			margin-left: 24rpx;
+		}
+
+		.content {
+			padding: 32rpx;
+
+			.news {
+				background: #FFFFFF;
+				box-shadow: 0rpx 6rpx 16rpx 0rpx #E3E6F2;
+				border-radius: 24rpx;
+				margin-top: 48rpx;
+				padding: 40rpx;
+
+				.info {
+					.info-text {
+						.info-top {
+							.name {
+								font-weight: 500;
+								font-size: 32rpx;
+								color: #363531;
+							}
+
+							.level {
+								margin-left: 12rpx;
+
+								.level-text {
+									width: 80rpx;
+									height: 36rpx;
+									padding: 6rpx 12rpx 6rpx 20rpx;
+									background: linear-gradient(130deg, #FFB873 0%, #FEC287 0%, #E69349 100%);
+									border-radius: 0rpx 18rpx 18rpx 0rpx;
+									font-weight: 500;
+									font-size: 24rpx;
+									color: #FFFFFF;
+									line-height: 24rpx;
+									margin-left: -12rpx;
+									// text-align: left;
+								}
+							}
+						}
+
+					}
+
+					.phone {
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #989897;
+					}
+				}
+
+				.news-total {
+					margin-top: 44rpx;
+
+					.item-num {
+						font-weight: bold;
+						font-size: 40rpx;
+						color: #363531;
+					}
+
+					.orange {
+						color: #FF6400;
+					}
+
+					.item-text {
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #9598A6;
+					}
+				}
+
+			}
+			.list-title-wrapper {
+				margin-top: 48rpx;
+				.list-title {
+					color: #363531;
+					font-weight: bold;
+					font-size: 36rpx;
+					line-height: 36rpx;
+
+					.title-line {
+						width: 8rpx;
+						height: 32rpx;
+						background-color: #FF8800;
+						margin-right: 20rpx;
+					}
+				}
+				.timer{
+					font-size: 24rpx;
+					.lb{
+						display: inline-block;
+						vertical-align: top;
+						width: 32rpx;
+						height: 32rpx;
+						background-color: #FFE4DA;
+						color: #FF4300;
+						text-align: center;
+						line-height: 32rpx;
+						border-radius: 6rpx;
+						margin: 0 2rpx;
+					}
+				}
+			}
+		}
+
+	}
+</style>

+ 0 - 52
pages/index/index.vue

@@ -1,52 +0,0 @@
-<template>
-	<view class="content">
-		<image class="logo" src="/static/logo.png"></image>
-		<view class="text-area">
-			<text class="title">{{title}}</text>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		data() {
-			return {
-				title: 'Hello'
-			}
-		},
-		onLoad() {
-
-		},
-		methods: {
-
-		}
-	}
-</script>
-
-<style>
-	.content {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-	}
-
-	.logo {
-		height: 200rpx;
-		width: 200rpx;
-		margin-top: 200rpx;
-		margin-left: auto;
-		margin-right: auto;
-		margin-bottom: 50rpx;
-	}
-
-	.text-area {
-		display: flex;
-		justify-content: center;
-	}
-
-	.title {
-		font-size: 36rpx;
-		color: #8f8f94;
-	}
-</style>

+ 461 - 0
pages/mall/mallRecharge/index.vue

@@ -0,0 +1,461 @@
+<template>
+	<!-- 充值套餐 -->
+	<view class="mall-recharge">
+		<view class="white-box">
+			<view class="account-text">充值账号</view>
+			<u-input class="account-name" v-model="phone" type="text" placeholder="请输入手机号" :customStyle="{ padding: '0'}" clearable></u-input>
+		</view>
+		<view class="list-title flex aic">
+			<span class="title-line"></span>
+			您选择的游戏币套餐
+		</view>
+		<view class="order-info">
+			<view class="info-top">
+				<view class="top-nums flex jcsb aic">
+					<view>
+						<span class="yxb-num">888</span>
+						<span class="yxb-text">游戏币</span>
+					</view>
+					<view>
+						<span class="price-text">¥</span>
+						<span class="price-num"></span>
+					</view>
+				</view>
+				<view class="info-msg flex jcsb aic">
+					<view class="msg-left">
+						<span class="zeng ${additionalGameCurrency || grabTimes || trafficSize ? 'show' : 'hide'}">赠</span>
+						<span class="${additionalGameCurrency ? 'show' : 'hide'}">
+							<span class="game-num">1000</span>游戏币
+						</span>
+						<!-- <span class="og">
+							<span class="${additionalGameCurrency && trafficSize ? 'show' : 'hide'}">+</span>
+							<span class="bold ${trafficSize ? 'show' : 'hide'}">2M</span>
+						</span> -->
+						<span class="og red ${grabTimes? '' : 'hide'}">
+							<span class="${additionalGameCurrency && grabTimes? 'show' : 'hide'}"
+								style="margin-left:2px">+</span>
+							<view class="red-box">
+								<!-- <image class="red_img"/> -->
+								<span>红包机会x2</span>
+							</view>
+						</span>
+					</view>
+					<span class="time-text">30天有效</span>
+				</view>
+			</view>
+			<view class="info-btm">
+				<view class="date-wrapper flex jcsb aic">
+					<view>立即生效</view>
+					<view class="date-box">2023年10月23</view>
+				</view>
+				<!-- <view class="jubaopen-ctrl margin-top-20 flex jcsb aic jbp">
+					<view class="jubaop">
+						<view class="juntop">
+							<image class="img-4" src="" alt="" />
+							<span>聚宝盆余额抵扣</span>
+							<i class="fx-icon icon-wenhao-xianxingyuankuang"></i>
+						</view>
+						<view class="dikou">
+							<span class="gongyou dikoujine"></span>
+							<span class="kedi kedikoujine"></span>
+						</view>
+						<view class="desc">聚宝盆余额整数部分可参与抵扣</view>
+					</view>
+					<image class="img-2 check-icon3-i" src="" alt="" />
+					<span class="check-icon check-icon3"></span>
+				</view> -->
+				<!-- <view class="margin-top-30 flex jcsb aic" id="zfbCtrl">
+					<view class="flex aic">
+						<image class="img-3" src="" alt="" />
+						<span>支付宝支付</span>
+					</view>
+					<image class="img-2 check-icon2-i" src="" alt="" />
+					<span class="check-icon check-icon2"></span>
+				</view> -->
+
+				<view class="wx-ctrl flex jcsb aic">
+					<view class="flex aic">
+						<re-image width="48" height="48" imgSrc="/retail/mall/weixin-icon.png" alt="" />
+						<span style="margin-left:16rpx">微信支付</span>
+					</view>
+					<re-image width="48" height="48" imgSrc="/retail/mall/yigou.png" alt="" />
+					<span class="check-icon check-icon1"></span>
+				</view>
+			</view>
+		</view>
+		<!-- 支付按钮 -->
+		<view class="btn-wrapper">
+			<view id="checkBox" class="margin-bottom-17">
+				<view class="check-text text-center">点击“确认支付”,即代表您已阅读并同意<span id="agreeEl" class="red">《用户购买协议》</span></view>
+			</view>
+			<view class="btns flex jcsb aic safe-area-inset-bottom">
+				<view>
+					<span class="btn-price-text1">应付款:</span>
+					<span class="btn-price-text2">¥</span>
+					<span class="price-num btn-price-num"></span>
+				</view>
+				<u-button class="primary-btn" id="buyBtn">确认支付</u-button>
+			</view>
+		</view>
+	</view>
+</template>
+<script>
+	export default{
+		// components:{
+		// 	'u-input': () => import('@/plugins/uview-ui/components/u-input') 
+		// }
+		data(){
+			return{
+				phone:''
+			}
+			
+		}
+	}
+	// const data = reactive({
+		
+	// })
+</script>
+<style lang="scss">
+	.mall-recharge {
+		padding: 32rpx;
+		.white-box {
+			padding: 48rpx 48rpx 56rpx;
+			background-color: #fff;
+			border-radius: 32rpx;
+
+			.account-text {
+				font-size: 32rpx;
+				font-weight: 500;
+				color: #2C2B28;
+				line-height: 14rpx;
+				margin-bottom: 40rpx;
+				
+			}
+
+			.account-name {
+				// color: #2C2B28;
+				// font-weight: bold;
+				// font-size: 28rpx;
+				// line-height: 32rpx;
+			}
+		}
+		.list-title {
+		  color: #363531;
+		  font-weight: bold;
+		  font-size: 36rpx;
+		  line-height: 36rpx;
+		  margin: 48rpx 0 32rpx;
+		
+		  .title-line {
+		    width: 8rpx;
+		    height: 32rpx;
+		    background-color: #FF8800;
+		    margin-right: 10rpx;
+		  }
+		}
+
+		.order-info {
+			background-color: #fff;
+			border-radius: 32rpx;
+
+			.info-top {
+				padding: 40rpx;
+				border-bottom: 1rpx solid #E8E8E8;
+			}
+
+			.top-nums {
+				font-weight: bold;
+				color: #2C2B28;
+
+				.yxb-num {
+					font-size: 48rpx;
+				}
+
+				.yxb-text {
+					font-size: 24rpx;
+					color: #564C47;
+				}
+
+				.price-num {
+					font-size: 48rpx;
+				}
+
+				.price-text {
+					font-size: 28rpx;
+				}
+			}
+
+			.info-msg {
+				margin-top: 32rpx;
+				font-size: 32rpx;
+				color: #2C2B28;
+				font-weight: bold;
+				white-space: nowrap;
+
+				.msg-left {
+					width: calc(100% - 142rpx);
+					display: flex;
+					align-items: center;
+					font-weight: normal;
+					font-size: 32rpx;
+
+					.game-num{
+						font-weight: bold;
+					}
+				}
+
+				.red {
+					display: flex;
+					align-items: center;
+
+					.red-box {
+						display: flex;
+						align-items: center;
+					}
+				}
+
+				.og {
+					color: #FF7C00;
+				}
+
+				.time-text {
+					font-size: 24rpx;
+					color: #564C47;
+					font-weight: normal;
+				}
+
+				.zeng {
+					flex-shrink: 0;
+					display: inline-block;
+					background-color: #5CB020;
+					width: 40rpx;
+					height: 32rpx;
+					line-height: 32rpx;
+					color: #fff;
+					font-size: 24rpx;
+					border-radius: 8rpx;
+					text-align: center;
+					font-weight: normal;
+					margin-right: 6rpx;
+				}
+
+				.show {
+					display: inline-block;
+					vertical-align: middle;
+				}
+
+				.hide {
+					display: none;
+				}
+			}
+		}
+
+		// .info-msg {
+		// 	margin-top: 16rpx;
+		// 	font-size: 16rpx;
+		// 	color: #2C2B28;
+		// 	font-weight: bold;
+
+		// 	.msg-left {
+		// 		width: calc(100% - 150rpx);
+		// 		display: flex;
+		// 		align-items: center;
+		// 		font-weight: normal;
+		// 		font-size: 12rpx;
+		// 	}
+
+		// 	.red {
+		// 		display: flex;
+		// 		align-items: center;
+
+		// 		.red-box {
+		// 			display: flex;
+		// 			align-items: center;
+		// 		}
+		// 	}
+
+		// 	.og {
+		// 		color: #FF7C00;
+		// 	}
+
+		// 	.time-text {
+		// 		font-size: 12rpx;
+		// 		color: #564C47;
+		// 		font-weight: normal;
+		// 	}
+
+		// 	.zeng {
+		// 		display: inline-block;
+		// 		background-color: #5CB020;
+		// 		width: 20rpx;
+		// 		height: 16rpx;
+		// 		line-height: 16rpx;
+		// 		color: #fff;
+		// 		font-size: 12rpx;
+		// 		border-radius: 4rpx;
+		// 		text-align: center;
+		// 		font-weight: normal;
+		// 		margin-right: 3rpx;
+		// 	}
+
+		// 	.show {
+		// 		display: inline-block;
+		// 		vertical-align: middle;
+		// 	}
+
+		// 	.hide {
+		// 		display: none;
+		// 	}
+		// }
+
+		.info-btm {
+			padding: 40rpx;
+			font-size: 32rpx;
+			color: #2C2B28;
+			font-weight: 500;
+
+			.date-wrapper{
+				
+			}
+			.wx-ctrl{
+				margin-top: 78rpx;
+				.check-icon1-i{
+					width: 48rpx;
+					height: 48rpx;
+				}
+			}
+			.margin-top-40 {
+				margin-top: 40rpx;
+			}
+
+			.margin-top-30 {
+				margin-top: 30rpx;
+			}
+
+			.margin-top-20 {
+				margin-top: 20rpx;
+			}
+
+			img {
+				width: 24rpx;
+				height: 24rpx;
+			}
+
+			.img-1 {
+				margin-right: 16rpx;
+			}
+
+			.img-4 {
+				margin-right: 16rpx;
+			}
+
+			.img-3 {
+				margin-right: 16rpx;
+				transform: scale(0.9);
+			}
+
+			.check-icon {
+				width: 40rpx;
+				height: 40rpx;
+				border: 1rpx solid #bbb;
+				border-radius: 100%;
+				margin-right: 2rpx;
+			}
+
+			.jbp {
+				padding: 10rpx 0rpx 10rpx 0rpx;
+				border-bottom: 1rpx solid #E8E8E8;
+			}
+
+			.dikou {
+				// height: 42rpx;
+				// float:left;
+				// position:absolute;
+				// margin-top: 70rpx;
+				margin-left: 30rpx;
+
+
+				.gongyou {
+					font-weight: normal;
+					font-size: 28px;
+					color: #8B8B8B;
+				}
+
+				.kedi {
+					font-weight: normal;
+					font-size: 28px;
+					color: #FF7C00;
+				}
+			}
+		}
+
+		.btn-wrapper {
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			right: 0;
+			padding: 24rpx 32rpx 0;
+			z-index: 200;
+			background-color: rgb(252, 252, 252);
+			border-top: 1rpx solid #eee;
+			box-shadow: 0rpx -4rpx 8rpx 0rpx rgba(109,84,52,0.19);
+
+			.btn-price-text1 {
+				color: #2C2B28;
+				font-size: 32rpx;
+				font-weight: bold;
+			}
+
+			.btn-price-text2 {
+				color: #FF6400;
+				font-size: 32rpx;
+				font-weight: bold;
+			}
+
+			.btn-price-num {
+				font-size: 48rpx;
+				color: #FF6400;
+				font-weight: bold;
+			}
+
+			.fx-icon {
+				font-size: 32rpx;
+				margin-right: 12rpx;
+
+				&.check-icon1 {
+					color: #281A13;
+				}
+
+				&.check-icon2 {
+					color: #0087fb;
+				}
+
+				&.check-icon3 {
+					color: #0087fb;
+				}
+			}
+
+			.check-text {
+				color: #281A13;
+				font-size: 24rpx;
+
+				.red {
+					color: #FF6400;
+				}
+			}
+			.btns{
+				margin-top: 24rpx;
+			}
+			.primary-btn {
+				width: 296rpx;
+				height: 96rpx;
+				font-size: 36rpx;
+				color: #FFFFFF;
+				background: linear-gradient(140deg, #FF8500 0%, #FFA600 100%);
+				border-radius: 48rpx;
+				font-weight: bold;
+				margin: 0;
+			}
+		}
+	}
+</style>

+ 67 - 0
pages/news/index.vue

@@ -0,0 +1,67 @@
+<template>
+	<view class="news">
+		<view class="list">
+			<view class="list-item">
+				<view class="time">2024-12-31 12:85</view>
+				<view class="new-card">
+					<view class="news-cons">
+						<view class="name">充值信息</view>
+						<view class="text ellipsis-2">消息内容文本文本文本文本文本文本文本文本</view>
+					</view>
+					<view class="news-detail">
+						<view class="txt">查看详情</view>
+						<re-image imgSrc="/retail/mall/icon_more.png" width="24" height="24"></re-image>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+</script>
+
+<style lang="scss" scoped>
+.news{
+	padding: 32rpx 20rpx;
+	.list{
+		.list-item{
+			.time{
+				text-align: center;
+				font-size: 26rpx;
+				margin-bottom: 20rpx;
+				color: #989897;
+			}
+			.new-card{
+				background-color: #fff;
+				border-radius: 16rpx;
+				.news-cons{
+					padding: 32rpx 32rpx 24rpx;
+					border-bottom: 2rpx solid #F0F2F4;
+					.name{
+						font-size: 32rpx;
+						font-weight: 500;
+						color: #363531;
+						margin-bottom: 16rpx;
+					}
+					.text{
+						font-size: 28rpx;
+						color: #7C7C7B;
+					}
+				}
+				.news-detail{
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					padding: 24rpx 26rpx 32rpx 22rpx;
+					.txt{
+						font-size: 28rpx;
+						font-weight: 400;
+						color: #363531;
+					}
+				}
+			}
+		}
+	}
+}
+</style>

+ 9 - 0
pages/order/index.vue

@@ -0,0 +1,9 @@
+<template>
+	<div>消息</div>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 9 - 0
pages/statistics/index.vue

@@ -0,0 +1,9 @@
+<template>
+	<div>统计</div>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>

+ 23 - 0
static/icon/iconfont.css

@@ -0,0 +1,23 @@
+@font-face {
+    font-family: "iconfont"; /* Project id 4445709 */
+    src: url('https://at.alicdn.com/t/c/font_4445709_hvd2q8eqjq.woff2?t=1709023180531') format('woff2'),
+         url('https://at.alicdn.com/t/c/font_4445709_hvd2q8eqjq.woff?t=1709023180531') format('woff'),
+         url('https://at.alicdn.com/t/c/font_4445709_hvd2q8eqjq.ttf?t=1709023180531') format('truetype');
+  }
+  
+  .iconfont {
+    font-family: "iconfont" !important;
+    font-size: 16px;
+    font-style: normal;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+  }
+  
+  .icon-fanhui:before {
+    content: "\e67e";
+  }
+  
+  .icon-home:before {
+    content: "\e6fe";
+  }
+  

+ 9 - 0
static/style/common.scss

@@ -169,3 +169,12 @@ uni-page-body {
 	-webkit-box-pack: center;//设置高度后只有一行时上下居中
 }
 
+// 底部安全区域
+.safe-area-inset-bottom{
+	padding-bottom: constant(safe-area-inset-bottom) !important;
+	padding-bottom: env(safe-area-inset-bottom) !important;
+}
+.safe-area-issue {
+	margin-bottom: constant(safe-area-inset-bottom) !important;
+	margin-bottom: env(safe-area-inset-bottom) !important;
+}

+ 15 - 0
store/index.js

@@ -0,0 +1,15 @@
+import Vue from "vue";
+import Vuex from "vuex";
+
+Vue.use(Vuex);
+import info from './modules/info.js'
+import emptyStatus from './modules/emptyStatus.js'
+export default new Vuex.Store({
+	state: {},
+	mutations: {},
+	actions: {},
+	modules: {
+		info,
+    	emptyStatus
+	}
+})

+ 45 - 0
store/modules/emptyStatus.js

@@ -0,0 +1,45 @@
+// 空状态图片地址
+export default {
+	state: {
+		status: [
+			{
+				url: '/noData/no-data-1.png',
+				name: '暂无订单',
+				desc: '我的团购订单',
+				type: 1
+			},
+      {
+      	url: '/noData/no-data-3.png',
+      	name: '暂无记录',
+				desc: '提现记录',
+      	type: 3
+      },
+      {
+      	url: '/noData/no-data-4.png',
+      	name: '暂无记录',
+				desc: '钱包零钱',
+      	type: 4
+      },
+      {
+      	url: '/noData/no-data-6.png',
+      	name: '暂无商品',
+				desc: '团购大厅',
+      	type: 6
+      },
+			{
+				url: '/noData/no-data-7.png',
+				name: '购物车空空如也',
+				decs: '购物车',
+				type: 7
+			},
+			{
+				url: '/noData/no-data-8.png',
+				name: '暂无提货点',
+				desc: '官方提货点',
+				type: 8
+			}
+		]
+	},
+	mutations: {},
+	actions: {}
+}

+ 43 - 0
store/modules/info.js

@@ -0,0 +1,43 @@
+export default {
+	state: {
+		token: "",
+		userId: "",
+		versionInfo: null, // 版本信息
+		systemInfo: null, // 系统信息
+		packageEnv: 'prod', // 默认产线环境
+	},
+	mutations: {
+		INIT_DATA(state, data = {}) {
+			let token = uni.getStorageSync('token')
+			let userId = uni.getStorageSync('userId')
+			if (token && userId) {
+				state.token = token
+				state.userId = userId
+			}
+		},
+		SET_PACKAGEENV(state, env){
+			state.packageEnv = env || uni.getStorageSync('packageEnv')
+			uni.getStorageSync('packageEnv',env)
+		},
+		SET_SYSTEMINFO(state, systemInfo) {
+			state.systemInfo = systemInfo
+		},
+		SET_VERSIONINFO(state, versionInfo) {
+			state.versionInfo = versionInfo
+		},
+		SET_FLASHSCREEN(state, data) {
+			console.log('data', data)
+			state.flashScreen = data
+		}
+	},
+	actions: {},
+	getter: {
+		isLogin(state){
+			if(state.token){
+				return true;
+			}else{
+				return false
+			}
+		}
+	}
+}

+ 3 - 1
uni.scss

@@ -13,7 +13,7 @@
  */
 
 /* 颜色变量 */
-
+@import '@/plugins/uview-ui/theme.scss';
 /* 行为相关颜色 */
 $uni-color-primary: #007aff;
 $uni-color-success: #4cd964;
@@ -74,3 +74,5 @@ $uni-color-subtitle: #555555; // 二级标题颜色
 $uni-font-size-subtitle:26px;
 $uni-color-paragraph: #3F536E; // 文章段落颜色
 $uni-font-size-paragraph:15px;
+
+$bg-color-main:#F5F5F5;

+ 25 - 0
uni_modules/uni-table/changelog.md

@@ -0,0 +1,25 @@
+## 1.2.2(2022-11-29)
+- 优化 主题样式
+## 1.2.1(2022-06-06)
+- 修复 微信小程序存在无使用组件的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-table](https://uniapp.dcloud.io/component/uniui/uni-table)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-07-08)
+- 新增 uni-th 支持 date 日期筛选范围
+## 1.0.6(2021-07-05)
+- 新增 uni-th 支持 range 筛选范围
+## 1.0.5(2021-06-28)
+- 新增 uni-th 筛选功能
+## 1.0.4(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的Bug
+## 1.0.3(2021-04-16)
+- 新增 sortable 属性,是否开启单列排序
+- 优化 表格多选逻辑
+## 1.0.2(2021-03-22)
+- uni-tr 添加 disabled 属性,用于 type=selection 时,设置某行是否可由全选按钮控制
+## 1.0.1(2021-02-05)
+- 调整为uni_modules目录规范

+ 455 - 0
uni_modules/uni-table/components/uni-table/uni-table.vue

@@ -0,0 +1,455 @@
+<template>
+	<view class="uni-table-scroll" :class="{ 'table--border': border, 'border-none': !noData }">
+		<!-- #ifdef H5 -->
+		<table class="uni-table" border="0" cellpadding="0" cellspacing="0" :class="{ 'table--stripe': stripe }" :style="{ 'min-width': minWidth + 'px' }">
+			<slot></slot>
+			<view v-if="noData" class="uni-table-loading">
+				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
+			</view>
+			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
+		</table>
+		<!-- #endif -->
+		<!-- #ifndef H5 -->
+		<view class="uni-table" :style="{ 'min-width': minWidth + 'px' }" :class="{ 'table--stripe': stripe }">
+			<slot></slot>
+			<view v-if="noData" class="uni-table-loading">
+				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
+			</view>
+			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
+		</view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+/**
+ * Table 表格
+ * @description 用于展示多条结构类似的数据
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Boolean} 	border 				是否带有纵向边框
+ * @property {Boolean} 	stripe 				是否显示斑马线
+ * @property {Boolean} 	type 					是否开启多选
+ * @property {String} 	emptyText 			空数据时显示的文本内容
+ * @property {Boolean} 	loading 			显示加载中
+ * @event {Function} 	selection-change 	开启多选时,当选择项发生变化时会触发该事件
+ */
+export default {
+	name: 'uniTable',
+	options: {
+		virtualHost: true
+	},
+	emits:['selection-change'],
+	props: {
+		data: {
+			type: Array,
+			default() {
+				return []
+			}
+		},
+		// 是否有竖线
+		border: {
+			type: Boolean,
+			default: false
+		},
+		// 是否显示斑马线
+		stripe: {
+			type: Boolean,
+			default: false
+		},
+		// 多选
+		type: {
+			type: String,
+			default: ''
+		},
+		// 没有更多数据
+		emptyText: {
+			type: String,
+			default: '没有更多数据'
+		},
+		loading: {
+			type: Boolean,
+			default: false
+		},
+		rowKey: {
+			type: String,
+			default: ''
+		}
+	},
+	data() {
+		return {
+			noData: true,
+			minWidth: 0,
+			multiTableHeads: []
+		}
+	},
+	watch: {
+		loading(val) {},
+		data(newVal) {
+			let theadChildren = this.theadChildren
+			let rowspan = 1
+			if (this.theadChildren) {
+				rowspan = this.theadChildren.rowspan
+			}
+			
+			// this.trChildren.length - rowspan
+			this.noData = false
+			// this.noData = newVal.length === 0 
+		}
+	},
+	created() {
+		// 定义tr的实例数组
+		this.trChildren = []
+		this.thChildren = []
+		this.theadChildren = null
+		this.backData = []
+		this.backIndexData = []
+	},
+
+	methods: {
+		isNodata() {
+			let theadChildren = this.theadChildren
+			let rowspan = 1
+			if (this.theadChildren) {
+				rowspan = this.theadChildren.rowspan
+			}
+			this.noData = this.trChildren.length - rowspan <= 0
+		},
+		/**
+		 * 选中所有
+		 */
+		selectionAll() {
+			let startIndex = 1
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			} else {
+				startIndex = theadChildren.rowspan - 1
+			}
+			let isHaveData = this.data && this.data.length > 0
+			theadChildren.checked = true
+			theadChildren.indeterminate = false
+			this.trChildren.forEach((item, index) => {
+				if (!item.disabled) {
+					item.checked = true
+					if (isHaveData && item.keyValue) {
+						const row = this.data.find(v => v[this.rowKey] === item.keyValue)
+						if (!this.backData.find(v => v[this.rowKey] === row[this.rowKey])) {
+							this.backData.push(row)
+						}
+					}
+					if (index > (startIndex - 1) && this.backIndexData.indexOf(index - startIndex) === -1) {
+						this.backIndexData.push(index - startIndex)
+					}
+				}
+			})
+			// this.backData = JSON.parse(JSON.stringify(this.data))
+			this.$emit('selection-change', {
+				detail: {
+					value: this.backData,
+					index: this.backIndexData
+				}
+			})
+		},
+		/**
+		 * 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)
+		 */
+		toggleRowSelection(row, selected) {
+			// if (!this.theadChildren) return
+			row = [].concat(row)
+
+			this.trChildren.forEach((item, index) => {
+				// if (item.keyValue) {
+
+				const select = row.findIndex(v => {
+					//
+					if (typeof v === 'number') {
+						return v === index - 1
+					} else {
+						return v[this.rowKey] === item.keyValue
+					}
+				})
+				let ischeck = item.checked
+				if (select !== -1) {
+					if (typeof selected === 'boolean') {
+						item.checked = selected
+					} else {
+						item.checked = !item.checked
+					}
+					if (ischeck !== item.checked) {
+						this.check(item.rowData||item, item.checked, item.rowData?item.keyValue:null, true)
+					}
+				}
+				// }
+			})
+			this.$emit('selection-change', {
+				detail: {
+					value: this.backData,
+					index:this.backIndexData
+				}
+			})
+		},
+
+		/**
+		 * 用于多选表格,清空用户的选择
+		 */
+		clearSelection() {
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			}
+			// if (!this.theadChildren) return
+			theadChildren.checked = false
+			theadChildren.indeterminate = false
+			this.trChildren.forEach(item => {
+				// if (item.keyValue) {
+					item.checked = false
+				// }
+			})
+			this.backData = []
+			this.backIndexData = []
+			this.$emit('selection-change', {
+				detail: {
+					value: [],
+					index: []
+				}
+			})
+		},
+		/**
+		 * 用于多选表格,切换所有行的选中状态
+		 */
+		toggleAllSelection() {
+			let list = []
+			let startIndex = 1
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			} else {
+				startIndex = theadChildren.rowspan - 1
+			}
+			this.trChildren.forEach((item, index) => {
+				if (!item.disabled) {
+					if (index > (startIndex - 1) ) {
+						list.push(index-startIndex)
+					}
+				}
+			})
+			this.toggleRowSelection(list)
+		},
+
+		/**
+		 * 选中\取消选中
+		 * @param {Object} child
+		 * @param {Object} check
+		 * @param {Object} rowValue
+		 */
+		check(child, check, keyValue, emit) {
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			}
+			
+			
+			
+			let childDomIndex = this.trChildren.findIndex((item, index) => child === item)
+			if(childDomIndex < 0){
+				childDomIndex = this.data.findIndex(v=>v[this.rowKey] === keyValue) + 1
+			}
+			const dataLen = this.trChildren.filter(v => !v.disabled && v.keyValue).length
+			if (childDomIndex === 0) {
+				check ? this.selectionAll() : this.clearSelection()
+				return
+			}
+
+			if (check) {
+				if (keyValue) {
+					this.backData.push(child)
+				}
+				this.backIndexData.push(childDomIndex - 1)
+			} else {
+				const index = this.backData.findIndex(v => v[this.rowKey] === keyValue)
+				const idx = this.backIndexData.findIndex(item => item === childDomIndex - 1)
+				if (keyValue) {
+					this.backData.splice(index, 1)
+				}
+				this.backIndexData.splice(idx, 1)
+			}
+
+			const domCheckAll = this.trChildren.find((item, index) => index > 0 && !item.checked && !item.disabled)
+			if (!domCheckAll) {
+				theadChildren.indeterminate = false
+				theadChildren.checked = true
+			} else {
+				theadChildren.indeterminate = true
+				theadChildren.checked = false
+			}
+
+			if (this.backIndexData.length === 0) {
+				theadChildren.indeterminate = false
+			}
+
+			if (!emit) {
+				this.$emit('selection-change', {
+					detail: {
+						value: this.backData,
+						index: this.backIndexData
+					}
+				})
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-scroll {
+	width: 100%;
+	/* #ifndef APP-NVUE */
+	overflow-x: auto;
+	/* #endif */
+}
+
+.uni-table {
+	position: relative;
+	width: 100%;
+	border-radius: 5px;
+	// box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+	background-color: #fff;
+	/* #ifndef APP-NVUE */
+	box-sizing: border-box;
+	display: table;
+	overflow-x: auto;
+	::v-deep .uni-table-tr:nth-child(n + 2) {
+		&:hover {
+			background-color: #f5f7fa;
+		}
+	}
+	::v-deep .uni-table-thead {
+		.uni-table-tr {
+			// background-color: #f5f7fa;
+			&:hover {
+				background-color:#fafafa;
+			}
+		}
+	}
+	/* #endif */
+}
+
+.table--border {
+	border: 1px $border-color solid;
+	border-right: none;
+}
+
+.border-none {
+	/* #ifndef APP-NVUE */
+	border-bottom: none;
+	/* #endif */
+}
+
+.table--stripe {
+	/* #ifndef APP-NVUE */
+	::v-deep .uni-table-tr:nth-child(2n + 3) {
+		background-color: #fafafa;
+	}
+	/* #endif */
+}
+
+/* 表格加载、无数据样式 */
+.uni-table-loading {
+	position: relative;
+	/* #ifndef APP-NVUE */
+	display: table-row;
+	/* #endif */
+	height: 50px;
+	line-height: 50px;
+	overflow: hidden;
+	box-sizing: border-box;
+}
+.empty-border {
+	border-right: 1px $border-color solid;
+}
+.uni-table-text {
+	position: absolute;
+	right: 0;
+	left: 0;
+	text-align: center;
+	font-size: 14px;
+	color: #999;
+}
+
+.uni-table-mask {
+	position: absolute;
+	top: 0;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	background-color: rgba(255, 255, 255, 0.8);
+	z-index: 99;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	margin: auto;
+	transition: all 0.5s;
+	/* #endif */
+	justify-content: center;
+	align-items: center;
+}
+
+.uni-table--loader {
+	width: 30px;
+	height: 30px;
+	border: 2px solid #aaa;
+	// border-bottom-color: transparent;
+	border-radius: 50%;
+	/* #ifndef APP-NVUE */
+	animation: 2s uni-table--loader linear infinite;
+	/* #endif */
+	position: relative;
+}
+
+@keyframes uni-table--loader {
+	0% {
+		transform: rotate(360deg);
+	}
+
+	10% {
+		border-left-color: transparent;
+	}
+
+	20% {
+		border-bottom-color: transparent;
+	}
+
+	30% {
+		border-right-color: transparent;
+	}
+
+	40% {
+		border-top-color: transparent;
+	}
+
+	50% {
+		transform: rotate(0deg);
+	}
+
+	60% {
+		border-top-color: transparent;
+	}
+
+	70% {
+		border-left-color: transparent;
+	}
+
+	80% {
+		border-bottom-color: transparent;
+	}
+
+	90% {
+		border-right-color: transparent;
+	}
+
+	100% {
+		transform: rotate(-360deg);
+	}
+}
+</style>

+ 29 - 0
uni_modules/uni-table/components/uni-tbody/uni-tbody.vue

@@ -0,0 +1,29 @@
+<template>
+	<!-- #ifdef H5 -->
+	<tbody>
+		<slot></slot>
+	</tbody>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view><slot></slot></view>
+	<!-- #endif -->
+</template>
+
+<script>
+export default {
+	name: 'uniBody',
+	options: {
+		virtualHost: true
+	},
+	data() {
+		return {
+			
+		}
+	},
+	created() {},
+	methods: {}
+}
+</script>
+
+<style>
+</style>

+ 90 - 0
uni_modules/uni-table/components/uni-td/uni-td.vue

@@ -0,0 +1,90 @@
+<template>
+	<!-- #ifdef H5 -->
+	<td class="uni-table-td" :rowspan="rowspan" :colspan="colspan" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
+		<slot></slot>
+	</td>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<!-- :class="{'table--border':border}"  -->
+	<view class="uni-table-td" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
+		<slot></slot>
+	</view>
+	<!-- #endif -->
+	
+</template>
+
+<script>
+	/**
+	 * Td 单元格
+	 * @description 表格中的标准单元格组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+	 * @property {Number} 	align = [left|center|right]	单元格对齐方式
+	 */
+	export default {
+		name: 'uniTd',
+		options: {
+			virtualHost: true
+		},
+		props: {
+			width: {
+				type: [String, Number],
+				default: ''
+			},
+			align: {
+				type: String,
+				default: 'left'
+			},
+			rowspan: {
+				type: [Number,String],
+				default: 1
+			},
+			colspan: {
+					type: [Number,String],
+				default: 1
+			}
+		},
+		data() {
+			return {
+				border: false
+			};
+		},
+		created() {
+			this.root = this.getTable()
+			this.border = this.root.border
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getTable() {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== 'uniTable') {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	$border-color:#EBEEF5;
+
+	.uni-table-td {
+		display: table-cell;
+		padding: 8px 10px;
+		font-size: 14px;
+		border-bottom: 1px $border-color solid;
+		font-weight: 400;
+		color: #606266;
+		line-height: 23px;
+		box-sizing: border-box;
+	}
+
+	.table--border {
+		border-right: 1px $border-color solid;
+	}
+</style>

+ 511 - 0
uni_modules/uni-table/components/uni-th/filter-dropdown.vue

@@ -0,0 +1,511 @@
+<template>
+	<view class="uni-filter-dropdown">
+		<view class="dropdown-btn" @click="onDropdown">
+			<view class="icon-select" :class="{active: canReset}" v-if="isSelect || isRange"></view>
+			<view class="icon-search" :class="{active: canReset}" v-if="isSearch">
+				<view class="icon-search-0"></view>
+				<view class="icon-search-1"></view>
+			</view>
+			<view class="icon-calendar" :class="{active: canReset}" v-if="isDate">
+				<view class="icon-calendar-0"></view>
+				<view class="icon-calendar-1"></view>
+			</view>
+		</view>
+		<view class="uni-dropdown-cover" v-if="isOpened" @click="handleClose"></view>
+		<view class="dropdown-popup dropdown-popup-right" v-if="isOpened" @click.stop>
+			<!-- select-->
+			<view v-if="isSelect" class="list">
+				<label class="flex-r a-i-c list-item" v-for="(item,index) in dataList" :key="index"
+					@click="onItemClick($event, index)">
+					<check-box class="check" :checked="item.checked" />
+					<view class="checklist-content">
+						<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+					</view>
+				</label>
+			</view>
+			<view v-if="isSelect" class="flex-r opera-area">
+				<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSelectReset">
+					{{resource.reset}}</view>
+				<view class="flex-f btn btn-submit" @click="handleSelectSubmit">{{resource.submit}}</view>
+			</view>
+			<!-- search -->
+			<view v-if="isSearch" class="search-area">
+				<input class="search-input" v-model="filterValue" />
+			</view>
+			<view v-if="isSearch" class="flex-r opera-area">
+				<view class="flex-f btn btn-submit" @click="handleSearchSubmit">{{resource.search}}</view>
+				<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSearchReset">
+					{{resource.reset}}</view>
+			</view>
+			<!-- range -->
+			<view v-if="isRange">
+				<view class="input-label">{{resource.gt}}</view>
+				<input class="input" v-model="gtValue" />
+				<view class="input-label">{{resource.lt}}</view>
+				<input class="input" v-model="ltValue" />
+			</view>
+			<view v-if="isRange" class="flex-r opera-area">
+				<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleRangeReset">
+					{{resource.reset}}</view>
+				<view class="flex-f btn btn-submit" @click="handleRangeSubmit">{{resource.submit}}</view>
+			</view>
+			<!-- date -->
+			<view v-if="isDate">
+				<uni-datetime-picker ref="datetimepicker" :value="dateRange" type="datetimerange" return-type="timestamp" @change="datetimechange" @maskClick="timepickerclose">
+					<view></view>
+				</uni-datetime-picker>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import checkBox from '../uni-tr/table-checkbox.vue'
+
+	const resource = {
+		"reset": "重置",
+		"search": "搜索",
+		"submit": "确定",
+		"filter": "筛选",
+		"gt": "大于等于",
+		"lt": "小于等于",
+		"date": "日期范围"
+	}
+
+	const DropdownType = {
+		Select: "select",
+		Search: "search",
+		Range: "range",
+		Date: "date",
+		Timestamp: "timestamp"
+	}
+
+	export default {
+		name: 'FilterDropdown',
+		emits:['change'],
+		components: {
+			checkBox
+		},
+		options: {
+			virtualHost: true
+		},
+		props: {
+			filterType: {
+				type: String,
+				default: DropdownType.Select
+			},
+			filterData: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			mode: {
+				type: String,
+				default: 'default'
+			},
+			map: {
+				type: Object,
+				default () {
+					return {
+						text: 'text',
+						value: 'value'
+					}
+				}
+			},
+			filterDefaultValue: {
+				type: [Array,String],
+				default () {
+					return ""
+				}
+			}
+		},
+		computed: {
+			canReset() {
+				if (this.isSearch) {
+					return this.filterValue.length > 0
+				}
+				if (this.isSelect) {
+					return this.checkedValues.length > 0
+				}
+				if (this.isRange) {
+					return (this.gtValue.length > 0 && this.ltValue.length > 0)
+				}
+				if (this.isDate) {
+					return this.dateSelect.length > 0
+				}
+				return false
+			},
+			isSelect() {
+				return this.filterType === DropdownType.Select
+			},
+			isSearch() {
+				return this.filterType === DropdownType.Search
+			},
+			isRange() {
+				return this.filterType === DropdownType.Range
+			},
+			isDate() {
+				return (this.filterType === DropdownType.Date || this.filterType === DropdownType.Timestamp)
+			}
+		},
+		watch: {
+			filterData(newVal) {
+				this._copyFilters()
+			},
+			indeterminate(newVal) {
+				this.isIndeterminate = newVal
+			}
+		},
+		data() {
+			return {
+				resource,
+				enabled: true,
+				isOpened: false,
+				dataList: [],
+				filterValue: this.filterDefaultValue,
+				checkedValues: [],
+				gtValue: '',
+				ltValue: '',
+				dateRange: [],
+				dateSelect: []
+			};
+		},
+		created() {
+			this._copyFilters()
+		},
+		methods: {
+			_copyFilters() {
+				let dl = JSON.parse(JSON.stringify(this.filterData))
+				for (let i = 0; i < dl.length; i++) {
+					if (dl[i].checked === undefined) {
+						dl[i].checked = false
+					}
+				}
+				this.dataList = dl
+			},
+			openPopup() {
+				this.isOpened = true
+				if (this.isDate) {
+					this.$nextTick(() => {
+						if (!this.dateRange.length) {
+							this.resetDate()
+						}
+						this.$refs.datetimepicker.show()
+					})
+				}
+			},
+			closePopup() {
+				this.isOpened = false
+			},
+			handleClose(e) {
+				this.closePopup()
+			},
+			resetDate() {
+				let date = new Date()
+				let dateText = date.toISOString().split('T')[0]
+				this.dateRange = [dateText + ' 0:00:00', dateText + ' 23:59:59']
+			},
+			onDropdown(e) {
+				this.openPopup()
+			},
+			onItemClick(e, index) {
+				let items = this.dataList
+				let listItem = items[index]
+				if (listItem.checked === undefined) {
+					items[index].checked = true
+				} else {
+					items[index].checked = !listItem.checked
+				}
+
+				let checkvalues = []
+				for (let i = 0; i < items.length; i++) {
+					const item = items[i]
+					if (item.checked) {
+						checkvalues.push(item.value)
+					}
+				}
+				this.checkedValues = checkvalues
+			},
+			datetimechange(e) {
+				this.closePopup()
+				this.dateRange = e
+				this.dateSelect = e
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: e
+				})
+			},
+			timepickerclose(e) {
+				this.closePopup()
+			},
+			handleSelectSubmit() {
+				this.closePopup()
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: this.checkedValues
+				})
+			},
+			handleSelectReset() {
+				if (!this.canReset) {
+					return;
+				}
+				var items = this.dataList
+				for (let i = 0; i < items.length; i++) {
+					let item = items[i]
+					this.$set(item, 'checked', false)
+				}
+				this.checkedValues = []
+				this.handleSelectSubmit()
+			},
+			handleSearchSubmit() {
+				this.closePopup()
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: this.filterValue
+				})
+			},
+			handleSearchReset() {
+				if (!this.canReset) {
+					return;
+				}
+				this.filterValue = ''
+				this.handleSearchSubmit()
+			},
+			handleRangeSubmit(isReset) {
+				this.closePopup()
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: isReset === true ? [] : [parseInt(this.gtValue), parseInt(this.ltValue)]
+				})
+			},
+			handleRangeReset() {
+				if (!this.canReset) {
+					return;
+				}
+				this.gtValue = ''
+				this.ltValue = ''
+				this.handleRangeSubmit(true)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-primary: #1890ff !default;
+	
+	.flex-r {
+		display: flex;
+		flex-direction: row;
+	}
+
+	.flex-f {
+		flex: 1;
+	}
+
+	.a-i-c {
+		align-items: center;
+	}
+
+	.j-c-c {
+		justify-content: center;
+	}
+
+	.icon-select {
+		width: 14px;
+		height: 16px;
+		border: solid 6px transparent;
+		border-top: solid 6px #ddd;
+		border-bottom: none;
+		background-color: #ddd;
+		background-clip: content-box;
+		box-sizing: border-box;
+	}
+
+	.icon-select.active {
+		background-color: $uni-primary;
+		border-top-color: $uni-primary;
+	}
+
+	.icon-search {
+		width: 12px;
+		height: 16px;
+		position: relative;
+	}
+
+	.icon-search-0 {
+		border: 2px solid #ddd;
+		border-radius: 8px;
+		width: 7px;
+		height: 7px;
+	}
+
+	.icon-search-1 {
+		position: absolute;
+		top: 8px;
+		right: 0;
+		width: 1px;
+		height: 7px;
+		background-color: #ddd;
+		transform: rotate(-45deg);
+	}
+
+	.icon-search.active .icon-search-0 {
+		border-color: $uni-primary;
+	}
+
+	.icon-search.active .icon-search-1 {
+		background-color: $uni-primary;
+	}
+
+	.icon-calendar {
+		color: #ddd;
+		width: 14px;
+		height: 16px;
+	}
+
+	.icon-calendar-0 {
+		height: 4px;
+		margin-top: 3px;
+		margin-bottom: 1px;
+		background-color: #ddd;
+		border-radius: 2px 2px 1px 1px;
+		position: relative;
+	}
+	.icon-calendar-0:before, .icon-calendar-0:after {
+		content: '';
+		position: absolute;
+		top: -3px;
+		width: 4px;
+		height: 3px;
+		border-radius: 1px;
+		background-color: #ddd;
+	}
+	.icon-calendar-0:before {
+		left: 2px;
+	}
+	.icon-calendar-0:after {
+		right: 2px;
+	}
+
+	.icon-calendar-1 {
+		height: 9px;
+		background-color: #ddd;
+		border-radius: 1px 1px 2px 2px;
+	}
+
+	.icon-calendar.active {
+		color: $uni-primary;
+	}
+
+	.icon-calendar.active .icon-calendar-0,
+	.icon-calendar.active .icon-calendar-1,
+	.icon-calendar.active .icon-calendar-0:before,
+	.icon-calendar.active .icon-calendar-0:after {
+		background-color: $uni-primary;
+	}
+
+	.uni-filter-dropdown {
+		position: relative;
+		font-weight: normal;
+	}
+
+	.dropdown-popup {
+		position: absolute;
+		top: 100%;
+		background-color: #fff;
+		box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
+		min-width: 150px;
+		z-index: 1000;
+	}
+
+	.dropdown-popup-left {
+		left: 0;
+	}
+
+	.dropdown-popup-right {
+		right: 0;
+	}
+
+	.uni-dropdown-cover {
+		position: fixed;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		background-color: transparent;
+		z-index: 100;
+	}
+
+	.list {
+		margin-top: 5px;
+		margin-bottom: 5px;
+	}
+
+	.list-item {
+		padding: 5px 10px;
+		text-align: left;
+	}
+
+	.list-item:hover {
+		background-color: #f0f0f0;
+	}
+
+	.check {
+		margin-right: 5px;
+	}
+
+	.search-area {
+		padding: 10px;
+	}
+
+	.search-input {
+		font-size: 12px;
+		border: 1px solid #f0f0f0;
+		border-radius: 3px;
+		padding: 2px 5px;
+		min-width: 150px;
+		text-align: left;
+	}
+
+	.input-label {
+		margin: 10px 10px 5px 10px;
+		text-align: left;
+	}
+
+	.input {
+		font-size: 12px;
+		border: 1px solid #f0f0f0;
+		border-radius: 3px;
+		margin: 10px;
+		padding: 2px 5px;
+		min-width: 150px;
+		text-align: left;
+	}
+
+	.opera-area {
+		cursor: default;
+		border-top: 1px solid #ddd;
+		padding: 5px;
+	}
+
+	.opera-area .btn {
+		font-size: 12px;
+		border-radius: 3px;
+		margin: 5px;
+		padding: 4px 4px;
+	}
+
+	.btn-default {
+		border: 1px solid #ddd;
+	}
+
+	.btn-default.disable {
+		border-color: transparent;
+	}
+
+	.btn-submit {
+		background-color: $uni-primary;
+		color: #ffffff;
+	}
+</style>

+ 285 - 0
uni_modules/uni-table/components/uni-th/uni-th.vue

@@ -0,0 +1,285 @@
+<template>
+	<!-- #ifdef H5 -->
+	<th :rowspan="rowspan" :colspan="colspan" class="uni-table-th" :class="{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }">
+		<view class="uni-table-th-row">
+			<view class="uni-table-th-content" :style="{ 'justify-content': contentAlign }" @click="sort">
+				<slot></slot>
+				<view v-if="sortable" class="arrow-box">
+					<text class="arrow up" :class="{ active: ascending }" @click.stop="ascendingFn"></text>
+					<text class="arrow down" :class="{ active: descending }" @click.stop="descendingFn"></text>
+				</view>
+			</view>
+			<dropdown v-if="filterType || filterData.length" :filterDefaultValue="filterDefaultValue" :filterData="filterData" :filterType="filterType" @change="ondropdown"></dropdown>
+		</view>
+	</th>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view class="uni-table-th" :class="{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }"><slot></slot></view>
+	<!-- #endif -->
+</template>
+
+<script>
+	// #ifdef H5
+	import dropdown from './filter-dropdown.vue'
+	// #endif
+/**
+ * Th 表头
+ * @description 表格内的表头单元格组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Number | String} 	width 	单元格宽度(支持纯数字、携带单位px或rpx)
+ * @property {Boolean} 	sortable 					是否启用排序
+ * @property {Number} 	align = [left|center|right]	单元格对齐方式
+ * @value left   	单元格文字左侧对齐
+ * @value center	单元格文字居中
+ * @value right		单元格文字右侧对齐
+ * @property {Array}	filterData 筛选数据
+ * @property {String}	filterType	[search|select] 筛选类型
+ * @value search	关键字搜素
+ * @value select	条件选择
+ * @event {Function} sort-change 排序触发事件
+ */
+export default {
+	name: 'uniTh',
+	options: {
+		virtualHost: true
+	},
+	components: {
+		// #ifdef H5
+		dropdown
+		// #endif
+	},
+	emits:['sort-change','filter-change'],
+	props: {
+		width: {
+			type: [String, Number],
+			default: ''
+		},
+		align: {
+			type: String,
+			default: 'left'
+		},
+		rowspan: {
+			type: [Number, String],
+			default: 1
+		},
+		colspan: {
+			type: [Number, String],
+			default: 1
+		},
+		sortable: {
+			type: Boolean,
+			default: false
+		},
+		filterType: {
+			type: String,
+			default: ""
+		},
+		filterData: {
+			type: Array,
+			default () {
+				return []
+			}
+		},
+		filterDefaultValue: {
+			type: [Array,String],
+			default () {
+				return ""
+			}
+		}
+	},
+	data() {
+		return {
+			border: false,
+			ascending: false,
+			descending: false
+		}
+	},
+	computed: {
+		// 根据props中的width属性 自动匹配当前th的宽度(px)
+		customWidth(){
+			if(typeof this.width === 'number'){
+				return this.width
+			} else if(typeof this.width === 'string') {
+				let regexHaveUnitPx = new RegExp(/^[1-9][0-9]*px$/g)
+				let regexHaveUnitRpx = new RegExp(/^[1-9][0-9]*rpx$/g)
+				let regexHaveNotUnit = new RegExp(/^[1-9][0-9]*$/g)
+				if (this.width.match(regexHaveUnitPx) !== null) { // 携带了 px
+					return this.width.replace('px', '')
+				} else if (this.width.match(regexHaveUnitRpx) !== null) { // 携带了 rpx
+					let numberRpx = Number(this.width.replace('rpx', ''))
+					let widthCoe = uni.getSystemInfoSync().screenWidth / 750
+					return Math.round(numberRpx * widthCoe)
+				} else if (this.width.match(regexHaveNotUnit) !== null) { // 未携带 rpx或px 的纯数字 String
+					return this.width
+				} else { // 不符合格式
+					return ''
+				}
+			} else {
+				return ''
+			}
+		},
+		contentAlign() {
+			let align = 'left'
+			switch (this.align) {
+				case 'left':
+					align = 'flex-start'
+					break
+				case 'center':
+					align = 'center'
+					break
+				case 'right':
+					align = 'flex-end'
+					break
+			}
+			return align
+		}
+	},
+	created() {
+		this.root = this.getTable('uniTable')
+		this.rootTr = this.getTable('uniTr')
+		this.rootTr.minWidthUpdate(this.customWidth ? this.customWidth : 140)
+		this.border = this.root.border
+		this.root.thChildren.push(this)
+	},
+	methods: {
+		sort() {
+			if (!this.sortable) return
+			this.clearOther()
+			if (!this.ascending && !this.descending) {
+				this.ascending = true
+				this.$emit('sort-change', { order: 'ascending' })
+				return
+			}
+			if (this.ascending && !this.descending) {
+				this.ascending = false
+				this.descending = true
+				this.$emit('sort-change', { order: 'descending' })
+				return
+			}
+
+			if (!this.ascending && this.descending) {
+				this.ascending = false
+				this.descending = false
+				this.$emit('sort-change', { order: null })
+			}
+		},
+		ascendingFn() {
+			this.clearOther()
+			this.ascending = !this.ascending
+			this.descending = false
+			this.$emit('sort-change', { order: this.ascending ? 'ascending' : null })
+		},
+		descendingFn() {
+			this.clearOther()
+			this.descending = !this.descending
+			this.ascending = false
+			this.$emit('sort-change', { order: this.descending ? 'descending' : null })
+		},
+		clearOther() {
+			this.root.thChildren.map(item => {
+				if (item !== this) {
+					item.ascending = false
+					item.descending = false
+				}
+				return item
+			})
+		},
+		ondropdown(e) {
+			this.$emit("filter-change", e)
+		},
+		/**
+		 * 获取父元素实例
+		 */
+		getTable(name) {
+			let parent = this.$parent
+			let parentName = parent.$options.name
+			while (parentName !== name) {
+				parent = parent.$parent
+				if (!parent) return false
+				parentName = parent.$options.name
+			}
+			return parent
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+$uni-primary: #007aff !default;
+
+.uni-table-th {
+	padding: 12px 10px;
+	/* #ifndef APP-NVUE */
+	display: table-cell;
+	box-sizing: border-box;
+	/* #endif */
+	font-size: 14px;
+	font-weight: bold;
+	color: #909399;
+	border-bottom: 1px $border-color solid;
+}
+
+.uni-table-th-row {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: row;
+}
+
+.table--border {
+	border-right: 1px $border-color solid;
+}
+.uni-table-th-content {
+	display: flex;
+	align-items: center;
+	flex: 1;
+}
+.arrow-box {
+}
+.arrow {
+	display: block;
+	position: relative;
+	width: 10px;
+	height: 8px;
+	// border: 1px red solid;
+	left: 5px;
+	overflow: hidden;
+	cursor: pointer;
+}
+.down {
+	top: 3px;
+	::after {
+		content: '';
+		width: 8px;
+		height: 8px;
+		position: absolute;
+		left: 2px;
+		top: -5px;
+		transform: rotate(45deg);
+		background-color: #ccc;
+	}
+	&.active {
+		::after {
+			background-color: $uni-primary;
+		}
+	}
+}
+.up {
+	::after {
+		content: '';
+		width: 8px;
+		height: 8px;
+		position: absolute;
+		left: 2px;
+		top: 5px;
+		transform: rotate(45deg);
+		background-color: #ccc;
+	}
+	&.active {
+		::after {
+			background-color: $uni-primary;
+		}
+	}
+}
+</style>

+ 129 - 0
uni_modules/uni-table/components/uni-thead/uni-thead.vue

@@ -0,0 +1,129 @@
+<template>
+	<!-- #ifdef H5 -->
+	<thead class="uni-table-thead">
+		<tr class="uni-table-tr">
+			<th :rowspan="rowspan" colspan="1" class="checkbox" :class="{ 'tr-table--border': border }">
+				<table-checkbox :indeterminate="indeterminate" :checked="checked" @checkboxSelected="checkboxSelected"></table-checkbox>
+			</th>
+		</tr>
+		<slot></slot>
+	</thead>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view class="uni-table-thead"><slot></slot></view>
+	<!-- #endif -->
+</template>
+
+<script>
+import tableCheckbox from '../uni-tr/table-checkbox.vue'
+export default {
+	name: 'uniThead',
+	components: {
+		tableCheckbox
+	},
+	options: {
+		virtualHost: true
+	},
+	data() {
+		return {
+			border: false,
+			selection: false,
+			rowspan: 1,
+			indeterminate: false,
+			checked: false
+		}
+	},
+	created() {
+		this.root = this.getTable()
+		// #ifdef H5
+		this.root.theadChildren = this
+		// #endif
+		this.border = this.root.border
+		this.selection = this.root.type
+	},
+	methods: {
+		init(self) {
+			this.rowspan++
+		},
+		checkboxSelected(e) {
+			this.indeterminate = false
+			const backIndexData = this.root.backIndexData
+			const data = this.root.trChildren.filter(v => !v.disabled && v.keyValue)
+			if (backIndexData.length === data.length) {
+				this.checked = false
+				this.root.clearSelection()
+			} else {
+				this.checked = true
+				this.root.selectionAll()
+			}
+		},
+		/**
+		 * 获取父元素实例
+		 */
+		getTable(name = 'uniTable') {
+			let parent = this.$parent
+			let parentName = parent.$options.name
+			while (parentName !== name) {
+				parent = parent.$parent
+				if (!parent) return false
+				parentName = parent.$options.name
+			}
+			return parent
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-thead {
+	display: table-header-group;
+}
+
+.uni-table-tr {
+	/* #ifndef APP-NVUE */
+	display: table-row;
+	transition: all 0.3s;
+	box-sizing: border-box;
+	/* #endif */
+	border: 1px red solid;
+	background-color: #fafafa;
+}
+
+.checkbox {
+	padding: 0 8px;
+	width: 26px;
+	padding-left: 12px;
+	/* #ifndef APP-NVUE */
+	display: table-cell;
+	vertical-align: middle;
+	/* #endif */
+	color: #333;
+	font-weight: 500;
+	border-bottom: 1px $border-color solid;
+	font-size: 14px;
+	// text-align: center;
+}
+
+.tr-table--border {
+	border-right: 1px $border-color solid;
+}
+
+/* #ifndef APP-NVUE */
+.uni-table-tr {
+	::v-deep .uni-table-th {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+
+	::v-deep .uni-table-td {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+}
+
+/* #endif */
+</style>

+ 179 - 0
uni_modules/uni-table/components/uni-tr/table-checkbox.vue

@@ -0,0 +1,179 @@
+<template>
+	<view class="uni-table-checkbox" @click="selected">
+		<view v-if="!indeterminate" class="checkbox__inner" :class="{'is-checked':isChecked,'is-disable':isDisabled}">
+			<view class="checkbox__inner-icon"></view>
+		</view>
+		<view v-else class="checkbox__inner checkbox--indeterminate">
+			<view class="checkbox__inner-icon"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'TableCheckbox',
+		emits:['checkboxSelected'],
+		props: {
+			indeterminate: {
+				type: Boolean,
+				default: false
+			},
+			checked: {
+				type: [Boolean,String],
+				default: false
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			index: {
+				type: Number,
+				default: -1
+			},
+			cellData: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		watch:{
+			checked(newVal){
+				if(typeof this.checked === 'boolean'){
+					this.isChecked = newVal
+				}else{
+					this.isChecked = true
+				}
+			},
+			indeterminate(newVal){
+				this.isIndeterminate = newVal
+			}
+		},
+		data() {
+			return {
+				isChecked: false,
+				isDisabled: false,
+				isIndeterminate:false
+			}
+		},
+		created() {
+			if(typeof this.checked === 'boolean'){
+				this.isChecked = this.checked
+			}
+			this.isDisabled = this.disabled
+		},
+		methods: {
+			selected() {
+				if (this.isDisabled) return
+				this.isIndeterminate = false
+				this.isChecked = !this.isChecked
+				this.$emit('checkboxSelected', {
+					checked: this.isChecked,
+					data: this.cellData
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-primary: #007aff !default;
+	$border-color: #DCDFE6;
+	$disable:0.4;
+
+	.uni-table-checkbox {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		position: relative;
+		margin: 5px 0;
+		cursor: pointer;
+
+		// 多选样式
+		.checkbox__inner {
+			/* #ifndef APP-NVUE */
+			flex-shrink: 0;
+			box-sizing: border-box;
+			/* #endif */
+			position: relative;
+			width: 16px;
+			height: 16px;
+			border: 1px solid $border-color;
+			border-radius: 2px;
+			background-color: #fff;
+			z-index: 1;
+
+			.checkbox__inner-icon {
+				position: absolute;
+				/* #ifdef APP-NVUE */
+				top: 2px;
+				/* #endif */
+				/* #ifndef APP-NVUE */
+				top: 2px;
+				/* #endif */
+				left: 5px;
+				height: 7px;
+				width: 3px;
+				border: 1px solid #fff;
+				border-left: 0;
+				border-top: 0;
+				opacity: 0;
+				transform-origin: center;
+				transform: rotate(45deg);
+				box-sizing: content-box;
+			}
+
+			&.checkbox--indeterminate {
+				border-color: $uni-primary;
+				background-color: $uni-primary;
+
+				.checkbox__inner-icon {
+					position: absolute;
+					opacity: 1;
+					transform: rotate(0deg);
+					height: 2px;
+					top: 0;
+					bottom: 0;
+					margin: auto;
+					left: 0px;
+					right: 0px;
+					bottom: 0;
+					width: auto;
+					border: none;
+					border-radius: 2px;
+					transform: scale(0.5);
+					background-color: #fff;
+				}
+			}
+			&:hover{
+				border-color: $uni-primary;
+			}
+			// 禁用
+			&.is-disable {
+				/* #ifdef H5 */
+				cursor: not-allowed;
+				/* #endif */
+				background-color: #F2F6FC;
+				border-color: $border-color;
+			}
+
+			// 选中
+			&.is-checked {
+				border-color: $uni-primary;
+				background-color: $uni-primary;
+
+				.checkbox__inner-icon {
+					opacity: 1;
+					transform: rotate(45deg);
+				}
+
+				// 选中禁用
+				&.is-disable {
+					opacity: $disable;
+				}
+			}
+			
+		}
+	}
+</style>

+ 171 - 0
uni_modules/uni-table/components/uni-tr/uni-tr.vue

@@ -0,0 +1,171 @@
+<template>
+	<!-- #ifdef H5 -->
+	<tr class="uni-table-tr">
+		<th v-if="selection === 'selection' && ishead" class="checkbox" :class="{ 'tr-table--border': border }">
+			<table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
+		</th>
+		<slot></slot>
+		<!-- <uni-th class="th-fixed">123</uni-th> -->
+	</tr>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view class="uni-table-tr">
+		<view v-if="selection === 'selection' " class="checkbox" :class="{ 'tr-table--border': border }">
+			<table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
+		</view>
+		<slot></slot>
+	</view>
+	<!-- #endif -->
+</template>
+
+<script>
+	import tableCheckbox from './table-checkbox.vue'
+/**
+ * Tr 表格行组件
+ * @description 表格行组件 仅包含 th,td 组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=
+ */
+export default {
+	name: 'uniTr',
+	components: { tableCheckbox },
+	props: {
+		disabled: {
+			type: Boolean,
+			default: false
+		},
+		keyValue: {
+			type: [String, Number],
+			default: ''
+		}
+	},
+	options: {
+		virtualHost: true
+	},
+	data() {
+		return {
+			value: false,
+			border: false,
+			selection: false,
+			widthThArr: [],
+			ishead: true,
+			checked: false,
+			indeterminate:false
+		}
+	},
+	created() {
+		this.root = this.getTable()
+		this.head = this.getTable('uniThead')
+		if (this.head) {
+			this.ishead = false
+			this.head.init(this)
+		}
+		this.border = this.root.border
+		this.selection = this.root.type
+		this.root.trChildren.push(this)
+		const rowData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
+		if(rowData){
+			this.rowData = rowData
+		}
+		this.root.isNodata()
+	},
+	mounted() {
+		if (this.widthThArr.length > 0) {
+			const selectionWidth = this.selection === 'selection' ? 50 : 0
+			this.root.minWidth = this.widthThArr.reduce((a, b) => Number(a) + Number(b)) + selectionWidth
+		}
+	},
+	// #ifndef VUE3
+	destroyed() {
+		const index = this.root.trChildren.findIndex(i => i === this)
+		this.root.trChildren.splice(index, 1)
+		this.root.isNodata()
+	},
+	// #endif
+	// #ifdef VUE3
+	unmounted() {
+		const index = this.root.trChildren.findIndex(i => i === this)
+		this.root.trChildren.splice(index, 1)
+		this.root.isNodata()
+	},
+	// #endif
+	methods: {
+		minWidthUpdate(width) {
+			this.widthThArr.push(width)
+		},
+		// 选中
+		checkboxSelected(e) {
+			let rootData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
+			this.checked = e.checked
+			this.root.check(rootData||this, e.checked,rootData? this.keyValue:null)
+		},
+		change(e) {
+			this.root.trChildren.forEach(item => {
+				if (item === this) {
+					this.root.check(this, e.detail.value.length > 0 ? true : false)
+				}
+			})
+		},
+		/**
+		 * 获取父元素实例
+		 */
+		getTable(name = 'uniTable') {
+			let parent = this.$parent
+			let parentName = parent.$options.name
+			while (parentName !== name) {
+				parent = parent.$parent
+				if (!parent) return false
+				parentName = parent.$options.name
+			}
+			return parent
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-tr {
+	/* #ifndef APP-NVUE */
+	display: table-row;
+	transition: all 0.3s;
+	box-sizing: border-box;
+	/* #endif */
+}
+
+.checkbox {
+	padding: 0 8px;
+	width: 26px;
+	padding-left: 12px;
+	/* #ifndef APP-NVUE */
+	display: table-cell;
+	vertical-align: middle;
+	/* #endif */
+	color: #333;
+	font-weight: 500;
+	border-bottom: 1px $border-color solid;
+	font-size: 14px;
+	// text-align: center;
+}
+
+.tr-table--border {
+	border-right: 1px $border-color solid;
+}
+
+/* #ifndef APP-NVUE */
+.uni-table-tr {
+	::v-deep .uni-table-th {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+
+	::v-deep .uni-table-td {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+}
+
+/* #endif */
+</style>

+ 9 - 0
uni_modules/uni-table/i18n/en.json

@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "Reset",
+	"filter-dropdown.search": "Search",
+	"filter-dropdown.submit": "Submit",
+	"filter-dropdown.filter": "Filter",
+	"filter-dropdown.gt": "Greater or equal to",
+	"filter-dropdown.lt": "Less than or equal to",
+	"filter-dropdown.date": "Date"
+}

+ 9 - 0
uni_modules/uni-table/i18n/es.json

@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "Reiniciar",
+	"filter-dropdown.search": "Búsqueda",
+	"filter-dropdown.submit": "Entregar",
+	"filter-dropdown.filter": "Filtrar",
+	"filter-dropdown.gt": "Mayor o igual a",
+	"filter-dropdown.lt": "Menos que o igual a",
+	"filter-dropdown.date": "Fecha"
+}

+ 9 - 0
uni_modules/uni-table/i18n/fr.json

@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "Réinitialiser",
+	"filter-dropdown.search": "Chercher",
+	"filter-dropdown.submit": "Soumettre",
+	"filter-dropdown.filter": "Filtre",
+	"filter-dropdown.gt": "Supérieur ou égal à",
+	"filter-dropdown.lt": "Inférieur ou égal à",
+	"filter-dropdown.date": "Date"
+}

+ 12 - 0
uni_modules/uni-table/i18n/index.js

@@ -0,0 +1,12 @@
+import en from './en.json'
+import es from './es.json'
+import fr from './fr.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	es,
+	fr,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}

+ 9 - 0
uni_modules/uni-table/i18n/zh-Hans.json

@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "重置",
+	"filter-dropdown.search": "搜索",
+	"filter-dropdown.submit": "确定",
+	"filter-dropdown.filter": "筛选",
+	"filter-dropdown.gt": "大于等于",
+	"filter-dropdown.lt": "小于等于",
+	"filter-dropdown.date": "日期范围"
+}

+ 9 - 0
uni_modules/uni-table/i18n/zh-Hant.json

@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "重置",
+	"filter-dropdown.search": "搜索",
+	"filter-dropdown.submit": "確定",
+	"filter-dropdown.filter": "篩選",
+	"filter-dropdown.gt": "大於等於",
+	"filter-dropdown.lt": "小於等於",
+	"filter-dropdown.date": "日期範圍"
+}

+ 83 - 0
uni_modules/uni-table/package.json

@@ -0,0 +1,83 @@
+{
+  "id": "uni-table",
+  "displayName": "uni-table 表格",
+  "version": "1.2.2",
+  "description": "表格组件,多用于展示多条结构类似的数据,如",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "table",
+    "表格"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss","uni-datetime-picker"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "n",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "n",
+          "联盟": "n"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 13 - 0
uni_modules/uni-table/readme.md

@@ -0,0 +1,13 @@
+
+
+## Table 表单
+> 组件名:``uni-table``,代码块: `uTable`。
+
+用于展示多条结构类似的数据
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-table)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
+
+

+ 4 - 26
unpackage/dist/dev/mp-weixin/app.js

@@ -1,26 +1,4 @@
-"use strict";
-Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
-const common_vendor = require("./common/vendor.js");
-if (!Math) {
-  "./pages/index/index.js";
-}
-const _sfc_main = {
-  onLaunch: function() {
-    console.log("App Launch");
-  },
-  onShow: function() {
-    console.log("App Show");
-  },
-  onHide: function() {
-    console.log("App Hide");
-  }
-};
-const App = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__file", "E:/项目/retail-app/App.vue"]]);
-function createApp() {
-  const app = common_vendor.createSSRApp(App);
-  return {
-    app
-  };
-}
-createApp().app.mount("#app");
-exports.createApp = createApp;
+
+require('./common/runtime.js')
+require('./common/vendor.js')
+require('./common/main.js')

+ 44 - 1
unpackage/dist/dev/mp-weixin/app.json

@@ -1,6 +1,17 @@
 {
   "pages": [
-    "pages/index/index"
+    "pages/gallery/index",
+    "pages/statistics/index",
+    "pages/news/index",
+    "pages/my/index"
+  ],
+  "subPackages": [
+    {
+      "root": "pages/mall",
+      "pages": [
+        "mallRecharge/index"
+      ]
+    }
   ],
   "window": {
     "navigationBarTextStyle": "black",
@@ -8,5 +19,37 @@
     "navigationBarBackgroundColor": "#F8F8F8",
     "backgroundColor": "#F8F8F8"
   },
+  "tabBar": {
+    "color": "#7A7E83",
+    "selectedColor": "#3cc51f",
+    "borderStyle": "black",
+    "backgroundColor": "#ffffff",
+    "list": [
+      {
+        "pagePath": "pages/gallery/index",
+        "iconPath": "",
+        "selectedIconPath": "",
+        "text": "工作台"
+      },
+      {
+        "pagePath": "pages/statistics/index",
+        "iconPath": "",
+        "selectedIconPath": "",
+        "text": "统计"
+      },
+      {
+        "pagePath": "pages/news/index",
+        "iconPath": "",
+        "selectedIconPath": "",
+        "text": "消息"
+      },
+      {
+        "pagePath": "pages/my/index",
+        "iconPath": "",
+        "selectedIconPath": "",
+        "text": "我的"
+      }
+    ]
+  },
   "usingComponents": {}
 }

+ 2 - 2
unpackage/dist/dev/mp-weixin/app.wxss

@@ -1,3 +1,3 @@
+@import './common/main.wxss';
 
-	/*每个页面公共css */
-page{--status-bar-height:25px;--top-window-height:0px;--window-top:0px;--window-bottom:0px;--window-left:0px;--window-right:0px;--window-magin:0px}[data-c-h="true"]{display: none !important;}
+[data-custom-hidden="true"],[bind-data-custom-hidden="true"]{display: none !important;}

ファイルの差分が大きいため隠しています
+ 33801 - 5850
unpackage/dist/dev/mp-weixin/common/vendor.js


+ 0 - 19
unpackage/dist/dev/mp-weixin/pages/index/index.js

@@ -1,19 +0,0 @@
-"use strict";
-const common_vendor = require("../../common/vendor.js");
-const _sfc_main = {
-  data() {
-    return {
-      title: "Hello"
-    };
-  },
-  onLoad() {
-  },
-  methods: {}
-};
-function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
-  return {
-    a: common_vendor.t($data.title)
-  };
-}
-const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "E:/项目/retail-app/pages/index/index.vue"]]);
-wx.createPage(MiniProgramPage);

+ 0 - 4
unpackage/dist/dev/mp-weixin/pages/index/index.json

@@ -1,4 +0,0 @@
-{
-  "navigationBarTitleText": "uni-app",
-  "usingComponents": {}
-}

+ 0 - 1
unpackage/dist/dev/mp-weixin/pages/index/index.wxml

@@ -1 +0,0 @@
-<view class="content"><image class="logo" src="/static/logo.png"></image><view class="text-area"><text class="title">{{a}}</text></view></view>

+ 0 - 23
unpackage/dist/dev/mp-weixin/pages/index/index.wxss

@@ -1,23 +0,0 @@
-
-.content {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-}
-.logo {
-		height: 200rpx;
-		width: 200rpx;
-		margin-top: 200rpx;
-		margin-left: auto;
-		margin-right: auto;
-		margin-bottom: 50rpx;
-}
-.text-area {
-		display: flex;
-		justify-content: center;
-}
-.title {
-		font-size: 36rpx;
-		color: #8f8f94;
-}

+ 20 - 3
unpackage/dist/dev/mp-weixin/project.config.json

@@ -6,7 +6,7 @@
   },
   "setting": {
     "urlCheck": false,
-    "es6": true,
+    "es6": false,
     "postcss": false,
     "minified": false,
     "newFeature": true,
@@ -20,8 +20,25 @@
   "compileType": "miniprogram",
   "libVersion": "3.3.4",
   "appid": "touristappid",
-  "projectname": "paly-center-distribution",
-  "condition": {},
+  "projectname": "retail-app",
+  "condition": {
+    "search": {
+      "current": -1,
+      "list": []
+    },
+    "conversation": {
+      "current": -1,
+      "list": []
+    },
+    "game": {
+      "current": -1,
+      "list": []
+    },
+    "miniprogram": {
+      "current": -1,
+      "list": []
+    }
+  },
   "editorSetting": {
     "tabIndent": "insertSpaces",
     "tabSize": 2

+ 12 - 3
unpackage/dist/dev/mp-weixin/project.private.config.json

@@ -1,7 +1,16 @@
 {
   "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
-  "projectname": "paly-center-distribution",
-  "setting": {
-    "compileHotReLoad": true
+  "condition": {
+    "miniprogram": {
+      "list": [
+        {
+          "name": "pages/mall/mallRecharge/index",
+          "pathName": "pages/mall/mallRecharge/index",
+          "query": "",
+          "launchMode": "default",
+          "scene": null
+        }
+      ]
+    }
   }
 }

+ 9 - 0
unpackage/dist/dev/mp-weixin/static/style/common.scss

@@ -169,3 +169,12 @@ uni-page-body {
 	-webkit-box-pack: center;//设置高度后只有一行时上下居中
 }
 
+// 底部安全区域
+.safe-area-inset-bottom{
+	padding-bottom: constant(safe-area-inset-bottom) !important;
+	padding-bottom: env(safe-area-inset-bottom) !important;
+}
+.safe-area-issue {
+	margin-bottom: constant(safe-area-inset-bottom) !important;
+	margin-bottom: env(safe-area-inset-bottom) !important;
+}