hmp преди 4 години
родител
ревизия
4dddf0bb4e
променени са 100 файла, в които са добавени 6943 реда и са изтрити 2114 реда
  1. 9 5
      assets/http/api.js
  2. 24 28
      assets/http/service.js
  3. 7 5
      assets/http/setting.js
  4. 1091 0
      components/cu-editor/cu-editor.vue
  5. 119 0
      components/cu-editor/iconfont.wxss
  6. 14 0
      components/cu-editor/util.js
  7. 5 0
      package-lock.json
  8. 1 0
      package.json
  9. 73 51
      pages.json
  10. 1 1
      pages/activity/comps/card.vue
  11. 2 2
      pages/activity/detail.vue
  12. 58 0
      pages/auth/auth.vue
  13. 0 396
      pages/bill/bill.vue
  14. 0 217
      pages/bill/billDetail.vue
  15. 2 2
      pages/card/card.vue
  16. 8 2
      pages/index/index.vue
  17. 0 2
      pages/login/account-login.vue
  18. 0 155
      pages/material-download/comps/mp-swiper -tmp.vue
  19. 1 1
      pages/member/detail.vue
  20. 30 5
      pages/member/member.vue
  21. 1 9
      pages/my-bills/bills-detail.vue
  22. 3 2
      pages/my-bills/comps/balance-bills.vue
  23. 6 6
      pages/my-bills/comps/bills.vue
  24. 3 2
      pages/my-bills/comps/channel-point-bill.vue
  25. 3 2
      pages/my-bills/comps/point-bills.vue
  26. 67 0
      pages/notice/detail.vue
  27. 118 0
      pages/notice/list.vue
  28. 106 0
      pages/notice/notice.vue
  29. 0 71
      pages/order/comps/card.vue
  30. 0 101
      pages/order/comps/item.vue
  31. 0 237
      pages/order/detail.vue
  32. 0 91
      pages/order/order.vue
  33. 48 41
      pages/shop-info/shop-info.vue
  34. 1 1
      pages/statistics/pointBillStatistics.vue
  35. 4 3
      pages/statistics/statistics.vue
  36. 29 612
      pages/test/test.vue
  37. 1 0
      pagesGoods/assert/js/tarbar.js
  38. 4 4
      pagesGoods/pages/menu/menu.vue
  39. 2 2
      pagesGoods/pages/my-shop/my-shop.vue
  40. 168 42
      pagesGoods/pages/order/comps/card.vue
  41. 24 4
      pagesGoods/pages/order/comps/item.vue
  42. 76 12
      pagesGoods/pages/order/order.vue
  43. 0 0
      pagesPoster/comps/modal-checked.vue
  44. 0 0
      pagesPoster/comps/mp-swiper.vue
  45. 235 0
      pagesPoster/comps/u-draw-poster/README.md
  46. 38 0
      pagesPoster/comps/u-draw-poster/dist/draw-poster.d.ts
  47. 190 0
      pagesPoster/comps/u-draw-poster/dist/draw-poster.js
  48. 17 0
      pagesPoster/comps/u-draw-poster/dist/extends/create-from-list/index.d.ts
  49. 140 0
      pagesPoster/comps/u-draw-poster/dist/extends/create-from-list/index.js
  50. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/create-gcanvas/index.d.ts
  51. 9 0
      pagesPoster/comps/u-draw-poster/dist/extends/create-gcanvas/index.js
  52. 12 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image-fit.d.ts
  53. 25 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image-fit.js
  54. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image.d.ts
  55. 42 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image.js
  56. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-round-image.d.ts
  57. 15 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-round-image.js
  58. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-round-rect.d.ts
  59. 7 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-round-rect.js
  60. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-warp-text.d.ts
  61. 76 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-warp-text.js
  62. 7 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/index.d.ts
  63. 15 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/index.js
  64. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/round-rect.d.ts
  65. 41 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/round-rect.js
  66. 4 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/stroke-round-rect.d.ts
  67. 7 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-function/stroke-round-rect.js
  68. 101 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-painter/index.d.ts
  69. 73 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-painter/index.js
  70. 6 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/index.d.ts
  71. 6 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/index.js
  72. 10 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/uQRCode.d.ts
  73. 1355 0
      pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/uQRCode.js
  74. 11 0
      pagesPoster/comps/u-draw-poster/dist/index.d.ts
  75. 22 0
      pagesPoster/comps/u-draw-poster/dist/index.js
  76. 7 0
      pagesPoster/comps/u-draw-poster/dist/utils/global.d.ts
  77. 11 0
      pagesPoster/comps/u-draw-poster/dist/utils/global.js
  78. 175 0
      pagesPoster/comps/u-draw-poster/dist/utils/interface.d.ts
  79. 1 0
      pagesPoster/comps/u-draw-poster/dist/utils/interface.js
  80. 38 0
      pagesPoster/comps/u-draw-poster/dist/utils/object-sizing.d.ts
  81. 78 0
      pagesPoster/comps/u-draw-poster/dist/utils/object-sizing.js
  82. 20 0
      pagesPoster/comps/u-draw-poster/dist/utils/utils.d.ts
  83. 49 0
      pagesPoster/comps/u-draw-poster/dist/utils/utils.js
  84. 3 0
      pagesPoster/comps/u-draw-poster/dist/utils/wx-utils.d.ts
  85. 37 0
      pagesPoster/comps/u-draw-poster/dist/utils/wx-utils.js
  86. 236 0
      pagesPoster/comps/u-draw-poster/lib/draw-poster.ts
  87. 183 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-from-list/index.ts
  88. 241 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/bridge/bridge-weex.js
  89. 18 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/FillStyleLinearGradient.js
  90. 8 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/FillStylePattern.js
  91. 17 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/FillStyleRadialGradient.js
  92. 666 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/RenderingContext.js
  93. 11 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/ActiveInfo.js
  94. 21 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Buffer.js
  95. 21 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Framebuffer.js
  96. 298 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/GLenum.js
  97. 142 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/GLmethod.js
  98. 23 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/GLtype.js
  99. 21 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Program.js
  100. 21 0
      pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Renderbuffer.js

+ 9 - 5
assets/http/api.js

@@ -184,12 +184,13 @@ const goodsProperty={
 
 
 const goodsbills = {
-	list: p => http.get("ldt_bills/goodsbills/list", {
+	list: p => http.get("goodsbills/listShop", {
 		params: p
 	}),
 	detail: p => http.get("goodsbills/detail", {
 		params: p
 	}),
+	submit: p => http.post('ldt_bills/goodsbills/submit', p),
 }
 
 
@@ -206,9 +207,11 @@ const shopConfig={
 	list:p => http.get('ldt_goods/shopconfig/list', {params: p}),
 	submit: p => http.post('ldt_goods/shopconfig/submit', p),
 }
-
-
-
+const notice={
+	submitNotice: p => http.post('shop/submitNotice',p),
+	list:p => http.get('shop/getPublishNoticeList', {params: p}),
+	detail:p => http.get("ldt_notice/noticecontent/detail", {params:p}),
+}
 
 export const api={
 	uploadFile,
@@ -237,5 +240,6 @@ export const api={
 	goodsbills,
 	area,
 	shopTrade,
-	shopConfig
+	shopConfig,
+	notice
 }

+ 24 - 28
assets/http/service.js

@@ -1,11 +1,8 @@
 import Request from 'luch-request'
 import setting from './setting.js'
 import crypto from '@/utils/crypto.js'
-import md5Libs from "uview-ui/libs/function/md5";
-import verify from "@/utils/verify.js";
 
 let baseURL = setting.baseURL
-
 let refreshTokenUrl = baseURL + "blade-auth/oauth/token"
 
 //获取token
@@ -44,19 +41,15 @@ http.interceptors.request.use((config) => {
 	/* 请求之前拦截器。可以使用async await 做异步操作 */
 	config.header = {
 		...config.header,
-		Authorization: "Basic c2FiZXI6c2FiZXJfc2VjcmV0",
+		"Content-Type": "application/json;charset=UTF-8",
+		"Authorization": "Basic c2FiZXI6c2FiZXJfc2VjcmV0",
 		"Blade-Auth": getTokenStorage()
 	}
-	if (setting.enabledCrypto && config.method == 'POST') {
-		let data=config.data || {}
-		//报文加密
-		if (!verify.isEmpty(config.data)) {
-			let encrypt= crypto.encrypt(JSON.stringify(config.data))
-			config.data=encrypt
-		}
-		//签名
-		data.signKey=crypto.SIGN_KEY
-		config.header.sign= md5Libs.md5(crypto.objSort(data))
+	console.log(config,"122222222222");
+	if (setting.enabledCrypto && config.method == 'POST' && config.data) {
+		let encrypt= crypto.encrypt(JSON.stringify(config.data))
+		console.log(crypto.decrypt(encrypt),"/******************");
+		config.data=encrypt
 	}
 	return config
 }, (config) => {
@@ -87,7 +80,23 @@ http.interceptors.response.use(async (response) => {
 			isRefreshing = true
 
 			let tokenInfo = uni.getStorageSync('tokenInfo')
-
+			if (!tokenInfo.tenantId) {
+				uni.showModal({
+					title: "提示",
+					content: "会话已过期,请重新登录",
+					showCancel:false,
+					confirmColor:'#EF9944',
+					success: (res)=>{
+						if (res.confirm) {
+							uni.clearStorageSync()
+							uni.reLaunch({
+								url:"/pages/login/account-login"
+							})
+						} 
+					}
+				});
+				return
+			}
 			let [, res] = await uni.request({
 				url: refreshTokenUrl,
 				method: 'POST',
@@ -108,19 +117,6 @@ http.interceptors.response.use(async (response) => {
 				uni.reLaunch({
 					url:"/pages/login/account-login"
 				})
-				// uni.showModal({
-				// 	title:"提示",
-				// 	content:"登录失败",
-				// 	showCancel:false,
-				// 	success: (res) => {
-				// 		if (res.confirm) {
-				// 			uni.clearStorage()
-				// 			uni.reLaunch({
-				// 				url:"/pages/login/account-login"
-				// 			})
-				// 		}
-				// 	}
-				// })
 				return
 			}
 			

+ 7 - 5
assets/http/setting.js

@@ -2,13 +2,15 @@ let setting = {}
 
 setting.baseURL='https://ldt.guosen-fumao.cn/api/'
 setting.webSocketUrl='wss://ldt.guosen-fumao.cn/websocket/'
-setting.enabledCrypto = false
+setting.enabledCrypto = true
 
-// setting.baseURL='http://192.168.1.168:2366/'
-// setting.webSocketUrl='ws://192.168.1.168:2366/websocket/'
+// setting.baseURL = 'http://192.168.1.168:2366/'
+// setting.webSocketUrl = 'ws://192.168.1.168:2366/websocket/'
 // setting.enabledCrypto = true
 
-
-export default setting
+// setting.baseURL = 'http://139.159.240.119:2366/'
+// setting.webSocketUrl = 'ws://139.159.240.119:2366/websocket/'
+// setting.enabledCrypto = true
 
 
+export default setting

+ 1091 - 0
components/cu-editor/cu-editor.vue

@@ -0,0 +1,1091 @@
+<template>
+	<view class="editor-container">
+		<view id="fixed-top" class="fixed-top" :class="{ 'isFixed': isFixed }">
+			<view style="background-color: #fff;display: flex;justify-content: space-between;">
+				<view class="center" style="width: 80%;justify-content: flex-start;">
+					<u-form style="width: 100%;">
+						<u-form-item label="标题">
+							<u-input style="width: 95%;" v-model="title" placeholder="请输入标题"/>
+						</u-form-item>
+					</u-form>
+				</view>
+				<view class="center">
+					<view @click="save" class="cu-btn radius bg-base">
+						保存
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="fixed-top__place"></view>
+		<scroll-view scroll-y :style="{ height: scrollViewHeight + 'px' }">
+			<editor id="editor" class="cu-editor" :placeholder="placeholder" :read-only="readOnly"
+				:show-img-size="showImgSize" :show-img-toolbar="showImgToolbar" :show-img-resize="showImgResize"
+				@statuschange="onStatusChange" @ready="onEditorReady" @input="onEditorInput" @focus="onEditorFocus"
+				@blur="onEditorBlur"></editor>
+		</scroll-view>
+		<view class="fixed-bottom" :hidden="!toolbarShow" :style="{ bottom: fixedBottom + 'px' }" @touchstart.stop="">
+			<view class="toolbar selector" :style="{height: toolBarHeight + 'rpx'}">
+				<view class="toolbar-item-header" @touchend.stop="changeKeyBoard"><i class="iconfont icon-keyboard"></i>
+				</view>
+				<view v-for="(icon, index) in ['icon-add', 'icon-textformat', 'icon-align-left']" :key="index"
+					class="toolbar-item" @touchend.stop="changeSwiper(index)">
+					<i class="iconfont" :class="[icon, { active: toolBarContentShow && swiperCurrent == index }]"></i>
+				</view>
+
+				<view class="toolbar-item" @touchend.stop="formatformat('check')"><i
+						class="iconfont icon-list-check"></i></view>
+				<view class="toolbar-item" @touchend.stop="formatformat('undo')"><i class="iconfont icon-undo"></i>
+				</view>
+				<view class="toolbar-item" @touchend.stop="formatformat('redo')"><i class="iconfont icon-redo"></i>
+				</view>
+				<view class="toolbar-item-footer" @touchend.stop="hideToolbar"><i class="iconfont icon-check"></i>
+				</view>
+			</view>
+			<swiper :hidden="!toolBarContentShow" class="toolbar-content swiper-box"
+				:style="{height: toolBarContentHeight + 'rpx'}" :current="swiperCurrent" duration="300">
+				<!-- @touchstart.stop="" 禁用手动滑动 -->
+				<swiper-item v-for="(page, i) in formatArray" :key="i" class="swiper-item" @touchstart.stop="">
+					<template v-if="page.type === 'feature'">
+						<view class="feature-items flex">
+							<view v-for="(pitem, pindex) in page.array" :key="pindex" class="feature"
+								@touchend.stop="formatformat(pitem.name)">
+								<view class="icon"><text class="iconfont" :class="'icon-' + pitem.icon"></text></view>
+							</view>
+						</view>
+					</template>
+
+					<template v-else-if="page.type === 'tool'">
+						<view v-for="(pitem, pindex) in page.array" :key="pindex" class="tool-items flex">
+							<view v-for="(item, index) in pitem.items" :key="index" class="tool-item"
+								@touchend.stop="formatformat('format', item, pitem)"
+								:class="{ 'ql-active': isActive(item, pitem), noBgColor: pitem.name == 'color' }">
+								<view v-if="pitem.name == 'color'" class="color-circle"
+									:style="{ 'background-color': item.value }"></view>
+								<i v-else-if="pitem.label == 'icon'" class="iconfont" :class="'icon-' + item.icon"></i>
+								<text v-else class="txt"
+									:style="[{fontSize : pitem.name == 'fontSize' ? item.value : ''}, item.style]">{{ item.title || item.value }}</text>
+							</view>
+						</view>
+					</template>
+				</swiper-item>
+			</swiper>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		handleHtmlImage
+	} from './util'
+
+	export default {
+		name: 'cuEditor',
+		props: {
+			//editor属性,提示信息
+			placeholder: {
+				type: String,
+				default: '请输入内容'
+			},
+			//editor属性,点击图片时显示图片大小控件
+			showImgSize: {
+				type: Boolean,
+				default: true
+			},
+			//editor属性,点击图片时显示工具栏控件
+			showImgToolbar: {
+				type: Boolean,
+				default: true
+			},
+			//editor属性,点击图片时显示修改尺寸控件
+			showImgResize: {
+				type: Boolean,
+				default: true
+			},
+			//编辑器内容,必填
+			content: {
+				type: String,
+				default: ''
+			},
+			//chooseImage参数,最大文件大小,上传文件前校验是否符合规则,单位MB
+			maxSize: {
+				type: Number,
+				default: 5
+			},
+			//chooseImage参数,最多可以选择的图片张数
+			count: {
+				type: Number,
+				default: 5
+			},
+			//chooseImage参数,所选的图片的尺寸
+			sizeType: {
+				type: Array,
+				default () {
+					return ['original', 'compressed'] //['original', 'compressed']
+				}
+			},
+			//chooseImage参数,选择图片的来源
+			sourceType: {
+				type: Array,
+				default () {
+					return ['album', 'camera']
+				}
+			},
+			//不允许上传的图片类型
+			noAllowType: {
+				type: Array,
+				default () {
+					return [] //['gif']
+				}
+			},
+			//uploadFile参数,必填
+			url: {
+				type: String,
+				default: ''
+			},
+			//uploadFile参数
+			header: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			//uploadFile参数
+			formData: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			//uploadFile参数
+			name: {
+				type: String,
+				default: 'file'
+			}
+		},
+		data() {
+			return {
+				//标题
+				title:'',
+				
+				isFixed: true,
+				iphoneXBottomH: 0,
+				scrollHeightDefault: 0,
+				keyboardHeight: 0,
+				readOnly: true,
+				isDefaultFormat: true, // 首次聚集时设置默认格式
+				isIos: false,
+				inputFocus: false,
+				formats: {},
+				formatArray: [{
+						type: 'feature',
+						array: [{
+								name: 'chooseImage',
+								icon: 'image'
+							},
+							{
+								name: 'chooseImagebyCamera',
+								icon: 'photo'
+							},
+							{
+								name: 'insertDivider',
+								icon: 'line'
+							}
+						]
+					},
+					{
+						type: 'tool',
+						array: [{
+								name: 'text',
+								label: 'icon',
+								items: [{
+										name: 'bold',
+										icon: 'bold'
+									},
+									{
+										name: 'italic',
+										icon: 'italic'
+									},
+									{
+										name: 'underline',
+										icon: 'underline'
+									},
+									{
+										name: 'strike',
+										icon: 'strikethrough'
+									},
+									{
+										name: 'backgroundColor',
+										value: 'yellow',
+										icon: 'fontbgcolor'
+									}
+								]
+							},
+							{
+								name: 'defaultFormat',
+								items: [{
+										title: '标题',
+										format: {
+											fontSize: '18px',
+											bold: 'strong'
+										},
+										style: {
+											fontSize: '18px',
+											fontWeight: 'bold'
+										}
+									},
+									{
+										title: '小标题',
+										format: {
+											fontSize: '16px',
+											bold: 'strong'
+										},
+										style: {
+											fontSize: '16px',
+											fontWeight: 'bold'
+										}
+									},
+									{
+										title: '正文',
+										format: {
+											fontSize: '14px'
+										},
+										style: {
+											fontSize: '14px'
+										}
+									},
+									{
+										title: '注释',
+										format: {
+											fontSize: '12px',
+											color: '#888888'
+										},
+										style: {
+											fontSize: '12px',
+											color: '#888888',
+										}
+									}
+								]
+							},
+							{
+								name: 'fontSize',
+								items: [{
+										title: '18',
+										value: '18px'
+									},
+									{
+										title: '16',
+										value: '16px'
+									},
+									{
+										title: '14',
+										value: '14px'
+									},
+									{
+										title: '12',
+										value: '12px'
+									},
+									{
+										title: '11',
+										value: '11px'
+									},
+									{
+										title: '10',
+										value: '10px'
+									}
+								]
+							},
+							{
+								name: 'color',
+								items: [{
+										value: '#000000'
+									},
+									{
+										value: '#888888'
+									},
+									{
+										value: '#ffffff'
+									},
+									{
+										value: '#f6de41'
+									},
+									{
+										value: '#f68c41'
+									},
+									{
+										value: '#fd3136'
+									},
+									{
+										value: '#5ad8a6'
+									}
+								]
+							}
+						]
+					},
+					{
+						type: 'tool',
+						array: [{
+								name: 'align',
+								label: 'icon',
+								items: [{
+										value: 'left',
+										icon: 'align-left'
+									},
+									{
+										value: 'center',
+										icon: 'align-center'
+									},
+									{
+										value: 'right',
+										icon: 'align-right'
+									}
+								]
+							},
+							{
+								name: 'text',
+								label: 'icon',
+								items: [{
+										name: 'list',
+										value: 'ordered',
+										icon: 'orderedlist'
+									},
+									{
+										name: 'list',
+										value: 'bullet',
+										icon: 'unorderedlist'
+									},
+									{
+										name: 'indent',
+										icon: 'outdent',
+										value: '+1'
+									},
+									{
+										name: 'indent',
+										icon: 'indent',
+										value: '-1'
+									}
+								]
+							},
+							{
+								name: 'lineHeight',
+								items: [{
+										value: 1
+									},
+									{
+										value: 1.3
+									},
+									{
+										value: 1.5
+									},
+									{
+										value: 2
+									},
+									{
+										value: 3
+									}
+								]
+							}
+						]
+					}
+				],
+				curLength: 0,
+				swiperCurrent: 0,
+				toolbarShow: false,
+				toolBarContentShow: false,
+				fixedTopHeight: 0, // 顶部工具栏高度
+				toolBarHeight: 100, // 工具栏高度
+				toolBarContentHeight: 530, // 工具栏内容高度
+				progress: true //判断是否监听上传进度变化
+			};
+		},
+		computed: {
+			fullToolBarHeight() {
+				let height = 0
+				this.toolbarShow ? height += this.toolBarHeight : ''
+				this.toolBarContentShow ? height += this.toolBarContentHeight : ''
+				return uni.upx2px(height)
+			},
+			scrollHeight() {
+				return this.scrollHeightDefault - this.fixedTopHeight - this.fullToolBarHeight;
+			},
+			scrollViewHeight() {
+				let scrollViewHeight = this.scrollHeight - this.keyboardHeight;
+				return this.keyboardHeight > 0 ? scrollViewHeight + this.iphoneXBottomH : scrollViewHeight;
+			},
+			fixedBottom() {
+				return this.isIos || this.iphoneXBottomH > 0 ? (this.keyboardHeight > 0 ? this.keyboardHeight :
+					this.iphoneXBottomH) : 0
+			}
+		},
+		watch: {
+			keyboardHeight(newVal, oldVal) {
+				if (newVal > 0) {
+					this.toolBarContentShow = false
+				}
+				// this.updatePosition(newVal)
+			},
+			toolbarShow(val) {
+				if (!val) this.toolBarContentShow = val
+			}
+		},
+		created() {
+			this.index = 0
+			this.createdAt = Date.now()
+			this.getUid = () => `wux-upload--${this.createdAt}-${++this.index}`
+			this.uploadTask = {}
+			this.tempFilePaths = []
+		},
+		mounted() {
+			const query = wx.createSelectorQuery().in(this)
+			query.select('#fixed-top').boundingClientRect(res => {
+				this.fixedTopHeight = res.height
+			}).exec()
+
+			const system = uni.getSystemInfo({
+				success: e => {
+					this.isIos = e.platform == 'ios'
+					let isIphoneX = (e.platform == 'devtools' || this.isIos) && e.safeArea.top == 44
+					this.iphoneXBottomH = isIphoneX ? 34 : 0
+					this.scrollHeightDefault = e.windowHeight - 34
+				}
+			})
+
+			uni.onKeyboardHeightChange(res => {
+				let keyboardHeight = this.keyboardHeight
+				if (res.height === keyboardHeight) return
+
+				this.keyboardHeight = res.height;
+				const duration = res.height > 0 ? res.duration * 1000 : 0
+				keyboardHeight = res.height;
+				setTimeout(() => {
+					uni.pageScrollTo({
+						scrollTop: 0,
+						success: () => {
+							this.updatePosition(keyboardHeight)
+							this.editorCtx.scrollIntoView() //使得编辑器光标处滚动到窗口可视区域内
+						}
+					})
+				}, duration)
+			})
+		},
+		beforeDestroy() {
+			console.log("editor beforeDestroy")
+		},
+		methods: {
+			initTitle(title){
+				this.title=title
+			},
+			isActive(item, pitem) {
+				let {
+					name,
+					value,
+					format
+				} = item
+					!name ? name = pitem.name : ''
+				if (format) {
+					for (let name in format) {
+						if (this.formats[name] !== format[name]) {
+							return false
+						}
+					}
+					return true
+				} else {
+					return value ? this.formats[name] === value : this.formats[name]
+				}
+			},
+
+			hideKeyboard() {
+				// uni.hideKeyboard() //uni-app提供了隐藏软键盘的api,但是没有生效
+				this.editorCtx.blur()
+			},
+			changeSwiper(current) {
+				this.toolBarContentShow = true
+				this.swiperCurrent = current
+				this.hideKeyboard()
+			},
+			updatePosition(keyboardHeight) {
+				this.keyboardHeight = keyboardHeight
+			},
+			onEditorReady() {
+				const that = this
+				uni.createSelectorQuery()
+					.in(this)
+					.select('#editor')
+					.context(function(res) {
+						that.editorCtx = res.context
+						that.setValue(that.content)
+						// //设置默认格式
+						// // that.editorCtx.format('header', '4')
+						// that.editorCtx.format('fontSize', '14px')
+						// that.editorCtx.format('align', 'left')
+						// that.editorCtx.format('lineHeight', '1.3')
+						//setContents设置内容后editor会自动聚焦,解决:先设置read_only为true,赋值后再把read_only属性设置为false
+						that.readOnly = false
+					})
+					.exec()
+			},
+			onEditorInput(e) {
+				let {
+					html,
+					text
+				} = e.detail
+				this.curLength = text.length - 1
+			},
+			onEditorFocus(e) {
+				this.toolbarShow = true
+				this.inputFocus = true
+				if (this.isDefaultFormat) {
+					//设置默认格式
+					this.editorCtx.format('fontSize', '14px')
+					this.editorCtx.format('align', 'left')
+					this.isDefaultFormat = false
+				}
+			},
+			onEditorBlur() {
+				this.editorCtx.blur()
+				this.updatePosition(0)
+				this.inputFocus = false
+			},
+			changeKeyBoard() {
+				this.toolBarContentShow = false
+				this.hideKeyboard()
+			},
+			hideToolbar() {
+				this.hideKeyboard()
+				this.toolbarShow = false
+			},
+			// 修改默认样式
+			formatDefault(format) {
+				for (let name in format) {
+					this.editorCtx.format(name, format[name])
+				}
+				if (format.bold) {
+					this.editorCtx.format('bold', true)
+				} else if (this.formats.bold) {
+					this.editorCtx.format('bold', '')
+				}
+				this.editorCtx.format('lineHeight', '') //选择默认样式时,取消当前行高的选择
+			},
+			formatformat(bind, item = {}, pitem = {}) {
+				item.name = item.name || pitem.name || ''
+				let {
+					name,
+					value
+				} = item
+				switch (bind) {
+					case 'format': //改变文本样式
+						if (!name) return
+						if (name == 'defaultFormat') { //选择标题样式时,取消当前字号的选择
+							this.formatDefault(item.format)
+						} else {
+							this.editorCtx.format(name, value)
+						}
+						break
+					case 'removeFormat': //删除字体样式
+						this.editorCtx.removeFormat()
+						break
+					case 'insertDate': //插入时间
+						var date = new Date()
+						var formatDate = `${date.getFullYear()} 年${date.getMonth() + 1} 月${date.getDate()} 日`;
+						this.editorCtx.insertText({
+							text: formatDate
+						})
+						break
+					case 'check': //设置当前行为待办列表格式
+						this.editorCtx.format('list', 'check')
+						break
+					case 'undo': //撤销操作
+						this.editorCtx.undo()
+						break
+					case 'redo': //恢复操作
+						this.editorCtx.redo()
+						break
+					case 'insertDivider': //添加分割线
+						this.editorCtx.insertDivider()
+						break
+					case 'clear': //清除内容
+						this.editorCtx.clear()
+						break
+					case 'chooseImage': //插入相册图片
+						this.chooseImage()
+						break;
+					case 'chooseImagebyCamera': //拍摄
+						this.chooseImage(true)
+						break
+				}
+			},
+			onStatusChange(e) {
+				this.formats = e.detail
+				console.log(this.formats)
+			},
+			chooseImage(onlyCamera) {
+				const success = res => {
+					this.tempFilePaths = res.tempFiles.map(item => ({
+						url: item.path,
+						size: item.size,
+						type: item.path.substring(item.path.lastIndexOf('.') + 1, item.path.length),
+						uid: this.getUid()
+					}))
+					// 当前插入图片src地址直接使用临时路径,如果对接接口上传,更改为使用【上传文件】代码片段:
+
+					/* 直接插入临时图片地址 start */
+
+					// this.tempFilePaths.forEach(file => {
+					// 	this.insertImage(file.url, file)
+					// })
+
+					/* 直接插入临时图片地址 end */
+
+
+					/* 上传文件 start */
+
+					this.$emit('before', res)
+					this.verifyFile()
+					this.$nextTick(() => {
+						this.uploadFile(this.tempFilePaths.length)
+					})
+
+					/* 上传文件 end */
+
+				}
+
+				const {
+					count,
+					sizeType
+				} = this
+				setTimeout(() => {
+					uni.chooseImage({
+						count,
+						sizeType,
+						sourceType: onlyCamera ? ['camera'] : this.sourceType,
+						success
+					})
+				}, 100)
+			},
+			insertImage(src, file) {
+				var that = this
+				that.editorCtx.insertImage({
+					src,
+					data: {
+						id: file.uid
+					},
+					// extClass:'editor-img',
+					extClass: 'editor--editor-img', //添加到图片 img标签上的类名为editor-img,设置前缀editor--才生效。部分机型点击图片右边的光标时不灵敏,需将样式editor-img宽度调小 max-width:98%;从而在图片右侧中留出部分位置供用户点击聚集。
+					success(e) {
+						//真机会自动插入一行空格
+					}
+				})
+			},
+			/**
+			 * 上传文件,支持多图递归上传
+			 */
+			uploadFile(uploadCount, curIndex) {
+				if (!this.tempFilePaths.length) return
+				const {
+					url,
+					name,
+					header,
+					formData,
+					progress
+				} = this
+				const file = this.tempFilePaths.shift()
+				curIndex ? (file.index = curIndex + 1) : (file.index = 1)
+				let {
+					uid,
+					url: filePath
+				} = file
+				if (!url || !filePath) return
+
+				this.uploadTask[uid] = uni.uploadFile({
+					url,
+					filePath,
+					name,
+					header,
+					formData,
+					success: res => this.onSuccess(file, res),
+					fail: res => this.onFail(file, res),
+					complete: res => {
+						delete this.uploadTask[uid]
+						this.$emit('complete', res)
+						//同时选择多图上传时,只校验第一张图片大小,多图递归上传需逐一校验
+						if (!this.tempFilePaths.length) return
+						this.verifyFile()
+						this.uploadFile(uploadCount, file.index)
+					}
+				})
+				// 判断是否监听上传进度变化
+				if (progress) {
+					this.uploadTask[uid].onProgressUpdate(res => this.onProgress(file, res, uploadCount))
+				}
+			},
+			/**校验图片格式和大小是否符合规则 */
+			verifyFile() {
+				var {
+					size: tempFilesSize,
+					type
+				} = this.tempFilePaths[0] //获取图片的大小,单位B
+				this.noAllowType.map(item => {
+					if (type == item) {
+						uni.showToast({
+							title: `不支持上传${item}图片`,
+							icon: 'none'
+						})
+						this.tempFilePaths.shift()
+					}
+				})
+
+				if (tempFilesSize / 1024 > this.maxSize * 1024) {
+					uni.showToast({
+						title: '上传图片不能大于' + this.bytesToSize(this.maxSize * 1024 * 1024) + '!',
+						icon: 'none'
+					})
+					this.tempFilePaths.shift()
+				}
+			},
+			onSuccess(file, res) {
+				//按照接口自行处理数据,insertImage的src参数为接口返回的图片地址
+				/**
+				 * 示例数据:
+				   res = {
+				   	data: '{"code":0,"msg":"上传成功","data":{"path":"https://xxx.com/images/upload/1.png"}}'
+				   }
+				*/
+				let json = JSON.parse(res.data)
+				if (json.success) {
+					this.insertImage(json.data.link, file)
+				} else {
+					uni.showToast({
+						title: '图片上传失败',
+						icon: 'none'
+					})
+				}
+			},
+			onFail(file, res) {
+				console.log(res);
+				uni.showToast({
+					title: '图片上传失败!',
+					icon: 'none'
+				})
+			},
+			/**
+			 * 监听上传进度变化的回调函数
+			 * @param {Object} file 文件对象
+			 * @param {Object} res 请求响应对象
+			 * @param {Number} uploadCount 选择图片总数量
+			 */
+			onProgress(file, res, uploadCount) {
+				if (res.progress != 100) {
+					uni.showToast({
+						title: `正在上传图片${file.index}/${uploadCount}`,
+						icon: 'none'
+					})
+				}
+				const targetItem = {
+					...file,
+					progress: res.progress,
+					res
+				}
+				const info = {
+					file: targetItem
+				}
+
+				this.$emit('progress', info)
+			},
+			bytesToSize: function(bytes) {
+				if (bytes === 0) return '0 B'
+				var k = 1024,
+					sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
+					i = Math.floor(Math.log(bytes) / Math.log(k))
+
+				return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]
+			},
+			setValue(value) {
+				if (this.editorCtx) {
+					this.editorCtx.setContents({
+						html: value,
+						success: () => {
+							this.getContents(res => {
+								this.onEditorInput({
+									detail: {
+										html: res.html,
+										text: res.text
+									}
+								})
+								this.$emit('update', res)
+							})
+						}
+					})
+				}
+			},
+			getContents(callback) {
+				//由于获取编辑器内容getContents为异步,因此需要使用callback回调
+				this.editorCtx.getContents({
+					success: res => {
+						callback(res)
+					}
+				})
+			},
+			save() {
+				if (!this.title) {
+					uni.showToast({
+						title:"请输入标题",
+						icon:"none"
+					})
+					return
+				}
+				if (this.curLength==0) {
+					uni.showToast({
+						title:"请输入内容",
+						icon:"none"
+					})
+					return
+				}
+				this.editorCtx.getContents({
+					success: res => {
+						console.log(res)
+						res.html = handleHtmlImage(res.html, true)
+						let data={
+							title:this.title,
+							content:res
+						}
+						this.$emit('save', data)
+					},
+					complete: res => {
+						console.log('getContents complete')
+					}
+				})
+			}
+		}
+
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import 'iconfont.wxss';
+
+	$bg-color: #f7f7f7;
+	$bg-color-hover: #eaeaea;
+	
+	.center{
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.fixed-top {
+		position: fixed;
+		top: -88rpx;
+		line-height: 88rpx;
+		padding: 0 30rpx;
+		box-sizing: border-box;
+		transition: all 0.3s ease;
+		background-color: #FFFFFF;
+		z-index: 999;
+
+		&.isFixed {
+			top: 0;
+		}
+
+		.btn {
+			width: 100%;
+			position: relative;
+			border: 0 !important;
+			border-radius: 6rpx;
+			padding-left: 0;
+			padding-right: 0;
+			overflow: visible;
+			float: right;
+			width: 100rpx;
+			height: 60rpx;
+			line-height: 60rpx;
+			font-size: 24rpx;
+			margin: 14rpx 0;
+			text-align: center;
+		}
+
+		.btn-primary {
+			background: $color !important;
+			color: #fff;
+		}
+
+		.btn-primary:hover {
+			opacity: 0.8;
+		}
+	}
+
+	.fixed-top,
+	.fixed-top__place {
+		width: 100%;
+		height: 88rpx;
+	}
+
+	.flex {
+		display: flex;
+	}
+
+	.editor-container {}
+
+	.cu-editor {
+		box-sizing: border-box;
+		width: 100%;
+		height: 100%;
+		font-size: 28rpx;
+		line-height: 1.5;
+		overflow: auto;
+		padding: 40rpx 35rpx;
+		min-height: unset !important;
+	}
+
+	.editor-img {
+		max-width: 98% !important;
+	}
+
+	.ql-active {
+		background-color: $bg-color-hover;
+
+		.color-circle {
+			border: solid 1px;
+		}
+	}
+
+	.noBgColor {
+		background-color: none !important;
+	}
+
+	.fixed-bottom {
+		position: fixed;
+		left: 0;
+		width: 100%;
+		right: 100%;
+		bottom: 0;
+		z-index: 99999;
+	}
+
+	.toolbar {
+		box-sizing: border-box;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		border: 1rpx solid #e5e5e5;
+		border-left: none;
+		border-right: none;
+		background: #fff;
+
+		.iconfont {
+			display: inline-block;
+			cursor: pointer;
+			font-size: 40rpx;
+			text-align: center;
+			position: relative;
+
+			&.active::after {
+				content: '';
+				left: 0;
+				bottom: 0;
+				width: 100%;
+				position: absolute;
+				height: 6rpx;
+				border-bottom: solid 6rpx #000000;
+			}
+		}
+
+		.toolbar-item {
+			height: 100rpx;
+			line-height: 100rpx;
+			flex: 1;
+			text-align: center;
+
+			&:active {
+				opacity: 0.4;
+			}
+		}
+
+		.toolbar-item-header,
+		.toolbar-item-footer {
+			width: 108rpx;
+			text-align: center;
+		}
+
+		.toolbar-item-header {
+			border-right: solid 1rpx $uni-border-color;
+		}
+
+		.toolbar-item-footer {
+			border-left: solid 1rpx $uni-border-color;
+			color: $color;
+			font-weight: bold;
+		}
+	}
+
+	.toolbar-content {
+		background-color: #ffffff;
+	}
+
+	.swiper-item {
+		box-sizing: border-box;
+		padding: 0 30rpx;
+	}
+
+	.tool-items {
+		background-color: $bg-color;
+		color: #323232;
+		height: 80rpx;
+		line-height: 80rpx;
+		margin: 32rpx 0;
+		border-radius: 16rpx;
+		overflow: hidden;
+
+		.tool-item {
+			flex: 1;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+
+			&:active {
+				background-color: $bg-color-hover;
+			}
+
+		}
+
+		.iconfont {
+			display: inline-block;
+			width: 80rpx;
+			height: 80rpx;
+			line-height: 80rpx;
+			cursor: pointer;
+			font-size: 40rpx;
+			text-align: center;
+		}
+
+		.color-circle {
+			width: 40rpx;
+			height: 40rpx;
+			border-radius: 50%;
+		}
+
+		.txt {
+			font-size: 14px;
+		}
+	}
+
+	.feature {
+		margin: 30rpx;
+		text-align: center;
+
+		.icon {
+			background-color: $bg-color;
+			width: 120rpx;
+			height: 120rpx;
+			line-height: 120rpx;
+			color: #323232;
+			margin-bottom: 10rpx;
+
+			&:active {
+				background-color: $bg-color-hover;
+			}
+
+			.iconfont {
+				font-size: 42rpx;
+			}
+		}
+	}
+</style>

+ 119 - 0
components/cu-editor/iconfont.wxss

@@ -0,0 +1,119 @@
+@font-face {
+  font-family: 'iconfont';  /* Project id 2843597 */
+  src: url('//at.alicdn.com/t/font_2843597_kx4g4k3cyrh.woff2?t=1633846789896') format('woff2'),
+       url('//at.alicdn.com/t/font_2843597_kx4g4k3cyrh.woff?t=1633846789896') format('woff'),
+       url('//at.alicdn.com/t/font_2843597_kx4g4k3cyrh.ttf?t=1633846789896') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-list-check:before {
+  content: "\e667";
+}
+
+.icon-add:before {
+  content: "\e664";
+}
+
+.icon-textformat:before {
+  content: "\e8b8";
+}
+
+.icon-image:before {
+  content: "\e65b";
+}
+
+.icon-photo:before {
+  content: "\e65f";
+}
+
+.icon-keyboard:before {
+  content: "\e64c";
+}
+
+.icon-undo:before {
+  content: "\e6f0";
+}
+
+.icon-redo:before {
+  content: "\e6f1";
+}
+
+.icon-bgcolors:before {
+  content: "\eb95";
+}
+
+.icon-fontbgcolor:before {
+  content: "\e68d";
+}
+
+.icon-indent:before {
+  content: "\e7f3";
+}
+
+.icon-outdent:before {
+  content: "\e7f4";
+}
+
+.icon-menu:before {
+  content: "\e7f5";
+}
+
+.icon-unorderedlist:before {
+  content: "\e7f6";
+}
+
+.icon-orderedlist:before {
+  content: "\e7f7";
+}
+
+.icon-align-right:before {
+  content: "\e7f8";
+}
+
+.icon-align-center:before {
+  content: "\e7f9";
+}
+
+.icon-align-left:before {
+  content: "\e7fa";
+}
+
+.icon-bold:before {
+  content: "\e7fb";
+}
+
+.icon-font-size:before {
+  content: "\e7fd";
+}
+
+.icon-line-height:before {
+  content: "\e7fe";
+}
+
+.icon-strikethrough:before {
+  content: "\e7ff";
+}
+
+.icon-underline:before {
+  content: "\e800";
+}
+
+.icon-italic:before {
+  content: "\e801";
+}
+
+.icon-check:before {
+  content: "\e802";
+}
+
+.icon-line:before {
+  content: "\e803";
+}
+

+ 14 - 0
components/cu-editor/util.js

@@ -0,0 +1,14 @@
+/**
+  * 处理html中的图片地址和宽度
+  * resetClass:  是否将class="editor-- 更改为class="
+  * EditorContext.setContents时img标签的class会自带一个前缀editor--,如原class="editor-img",EditorContext.setContents后class="editor--editor-img" */
+export const handleHtmlImage = (html = '', resetClass) => {
+	var newHtml = html.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/ig, function(match, src) {
+		let result = match
+		//返回每个匹配的字符串
+		if(resetClass) result = result.replace(/class=\"(.*)editor--/gi,'class="');
+		result = result.replace(/\<img/gi, '<img style="max-width:100%;height:auto"');
+		return result;
+	});
+	return newHtml;
+}

+ 5 - 0
package-lock.json

@@ -9,6 +9,11 @@
       "resolved": "https://registry.nlark.com/@dcloudio/types/download/@dcloudio/types-2.3.3.tgz?cache=0&sync_timestamp=1626160250541&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40dcloudio%2Ftypes%2Fdownload%2F%40dcloudio%2Ftypes-2.3.3.tgz",
       "integrity": "sha1-DkDCovGSXVbbKXw0xSjqjIz7tOc="
     },
+    "base-64": {
+      "version": "1.0.0",
+      "resolved": "https://registry.nlark.com/base-64/download/base-64-1.0.0.tgz",
+      "integrity": "sha1-CdDyCE4yo/0IwkdblzeI7uauj0o="
+    },
     "crypto-js": {
       "version": "4.1.1",
       "resolved": "https://registry.nlark.com/crypto-js/download/crypto-js-4.1.1.tgz?cache=0&sync_timestamp=1626954954639&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcrypto-js%2Fdownload%2Fcrypto-js-4.1.1.tgz",

+ 1 - 0
package.json

@@ -10,6 +10,7 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
+    "base-64": "^1.0.0",
     "hotp-totp-generator": "^1.1.3",
     "luch-request": "^3.0.6",
     "tki-qrcode": "^0.1.6",

+ 73 - 51
pages.json

@@ -30,20 +30,6 @@
 				"enablePullDownRefresh": false
 			}
 
-		}, {
-			"path": "pages/bill/bill",
-			"style": {
-				"navigationBarTitleText": "我的账单",
-				"enablePullDownRefresh": false
-			}
-
-		}, {
-			"path": "pages/bill/billDetail",
-			"style": {
-				"navigationBarTitleText": "账单详情",
-				"enablePullDownRefresh": false
-			}
-
 		}, {
 			"path": "pages/publish/publish",
 			"style": {
@@ -164,20 +150,6 @@
 				"enablePullDownRefresh": false
 			}
 
-		}, {
-			"path": "pages/material-download/material-download",
-			"style": {
-				"navigationBarTitleText": "选择模板",
-				"enablePullDownRefresh": false
-			}
-
-		}, {
-			"path": "pages/material-download/createPoster",
-			"style": {
-				"navigationBarTitleText": "生成付款码",
-				"enablePullDownRefresh": false
-			}
-
 		}, {
 			"path": "pages/test/test",
 			"style": {
@@ -258,13 +230,6 @@
 				"enablePullDownRefresh": false
 			}
 
-		}, {
-			"path": "pages/material-download/createOrderPoster",
-			"style": {
-				"navigationBarTitleText": "生成点餐码",
-				"enablePullDownRefresh": false
-			}
-
 		}, {
 			"path": "pages/flow/flow",
 			"style": {
@@ -293,20 +258,6 @@
 				"enablePullDownRefresh": false
 			}
 
-		}, {
-			"path": "pages/order/order",
-			"style": {
-				"navigationBarTitleText": "订单中心",
-				"enablePullDownRefresh": false
-			}
-
-		}, {
-			"path": "pages/order/detail",
-			"style": {
-				"navigationBarTitleText": "订单详情",
-				"enablePullDownRefresh": false
-			}
-
 		}, {
 			"path": "pages/test/test1",
 			"style": {
@@ -336,7 +287,43 @@
 			}
 
 		}
-	],
+	    ,{
+            "path" : "pages/notice/notice",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "发布公告",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/notice/list",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "通知公告",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/notice/detail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "公告详情",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/auth/auth",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "微信认证",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+    ],
 	"subPackages": [{
 		"root": "pagesGoods",
 		"pages": [{
@@ -359,6 +346,13 @@
 					"navigationStyle": "custom"
 				}
 
+			},{
+				"path": "pages/order/detail",
+				"style": {
+					"navigationBarTitleText": "订单详情",
+					"enablePullDownRefresh": false
+				}
+
 			}, {
 				"path": "pages/config/config",
 				"style": {
@@ -375,13 +369,41 @@
 					"navigationStyle":"custom"
 				}
 
+			}
+		]
+	},
+	{
+		"root": "pagesPoster",
+		"pages": [
+			{
+				"path": "pages/material-download",
+				"style": {
+					"navigationBarTitleText": "选择模板",
+					"enablePullDownRefresh": false
+				}
+			
+			}, {
+				"path": "pages/createPoster",
+				"style": {
+					"navigationBarTitleText": "生成付款码",
+					"enablePullDownRefresh": false
+				}
+			
+			},
+			{
+				"path": "pages/createOrderPoster",
+				"style": {
+					"navigationBarTitleText": "生成点餐码",
+					"enablePullDownRefresh": false
+				}
+			
 			}
 		]
 	}],
 	"preloadRule": {
 		"pages/index/index": {
 			"network": "all",
-			"packages": ["pagesGoods"]
+			"packages": ["pagesGoods","pagesPoster"]
 		}
 	},
 	"globalStyle": {

+ 1 - 1
pages/activity/comps/card.vue

@@ -13,7 +13,7 @@
 								<u-icon name="coupon" color="#ff7001" size="30"></u-icon>
 							</view>
 							<view class="">
-								<text class="sub-title text-cut-1 margin-left-10">{{item.discount * 10}}折</text>
+								<text class="sub-title text-cut-1 margin-left-10">{{discount(item.discount)}}</text>
 							</view>
 						</view>
 						<view v-else class="flex" style="width: 96%;">

+ 2 - 2
pages/activity/detail.vue

@@ -44,7 +44,7 @@
 			</view>
 			<view class="data" style="margin-top: 30rpx;">
 				<u-icon name="coupon" color="#EF9944"></u-icon>
-				<text class="margin-left-10">活动折扣:{{detail.discount * 10}} 折</text>
+				<text class="margin-left-10">活动折扣:{{discount(detail.discount)}}</text>
 			</view>
 		</view>
 
@@ -60,7 +60,7 @@
 							<image style="border-radius: 50%;" :src="item.joinLogo" mode="aspectFill"></image>
 							<view>
 								<text>{{item.joinName | ellipsis}}</text>
-								<text>{{item.discount * 10}}折</text>
+								<text>{{discount(item.discount)}}</text>
 							</view>
 						</view>
 					</view>

+ 58 - 0
pages/auth/auth.vue

@@ -0,0 +1,58 @@
+<template>
+	<view >
+		<view style="margin-top: 50rpx;" class="center flex-direction">
+			<image
+				@error="error"
+				style="width: 600rpx;height: 600rpx;"
+				:src="src"
+				mode="widthFix"></image>
+				<view class="center margin-top-50">
+					<text class="text-base">*请保存二维码,然后到微信中扫码关注该公众号</text>
+				</view>
+		</view>
+
+		<view class="" style="position: fixed;bottom: 150rpx;width: 100%;">
+			<view class="center">
+				<view @click="saveImg" class="cu-btn  flex radius text-lg"
+					style="padding: 46rpx 0;background-color: #EF9944;color: #FFFFFF;width: 90%;">
+					<u-icon name="download"></u-icon>
+					<text class="margin-left-20">保存到相册</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: '',
+		data() {
+			return {
+				src:''
+			};
+		},
+		onLoad(options) {
+			this.src=options.src
+			if (this.$isEmpty(this.src)) {
+				this.$dialog.showModalAndBack('二维码获取失败')
+				return
+			}
+			if (this.$isNotEmpty(this.src) && this.src.indexOf('https')<0) {
+				this.src=this.src.replace('http','https')
+			}
+		},
+		methods:{
+			error(){
+				this.$dialog.showModalAndBack('二维码加载失败')
+			},
+			async saveImg(){
+				let res=await this.$mpi.downloadFile(this.src)
+				this.$mpi.saveImg(res)
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 0 - 396
pages/bill/bill.vue

@@ -1,396 +0,0 @@
-<template>
-	<view>
-		<u-picker confirm-color="#EF9944" v-model="showTime" mode="time" :params="params"  @confirm="confirmTime">
-		</u-picker>
-		<view class="top">
-			<view class="tixian">
-				<view class="value" style="margin-bottom: 50rpx;">
-					<text>总应收</text>
-					<text class="text-price">{{shopData.charge}}</text>
-				</view>
-				<view class="flex justify-center align-center">
-					<view class="cu-btn btn round" style="padding: 24rpx 50rpx;" hover-class="hoverClass1"
-						@click="$jump('/pages/withdraw/withdraw')">
-						提现
-					</view>
-				</view>
-			</view>
-			<view style="display: flex;justify-content: flex-start;">
-				<view class="value">
-					<text>余额</text>
-					<text class="text-price">{{shopData.balance}}</text>
-				</view>
-			</view>
-
-		</view>
-		<view class="margin-top-20" style="margin-bottom: -10rpx;">
-			<u-tabs active-color="#FC8D38" :active-item-style="activeItemStyle" :list="tabslist" bg-color="#f1f1f1"
-				:current="current" @change="change"></u-tabs>
-		</view>
-		<view class="data">
-			<view class="left">
-				<view @click.stop="showTime = true">
-					<text>{{defaultTime}}</text>
-					<text class="cuIcon-unfold padding-left-10"></text>
-				</view>
-				<!-- <view>
-					<text>支出 ¥ 165.00 收入 ¥ 463.00</text>
-				</view> -->
-			</view>
-			<view class="right" @click="goStatistics">
-				<text>统计</text>
-				<text class="cuIcon-right"></text>
-			</view>
-		</view>
-
-		<view class="card">
-			<view v-if="current==0" style="display: flex;">
-				<view class="area1 area-padding " style="padding-left: 40rpx;">
-					<text>积分来源</text>
-				</view>
-				<view class="area2 area-padding">
-					<text>折扣</text>
-				</view>
-				<view class="area3 area-padding  text-center">
-					<text>价值</text>
-				</view>
-			</view>
-			<view v-if="current==1" style="display: flex;">
-				<view class="area1 area-padding " style="padding-left: 40rpx;">
-					<text>积分来源</text>
-				</view>
-				<view class="area2 area-padding">
-					<text>积分</text>
-				</view>
-				<view class="area3 area-padding  ">
-					<text>价值</text>
-				</view>
-			</view>
-			<mescroll-body :height="height" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
-				:down="downOption" :up="upOption">
-				<view @click="$jump('/pages/bill/billDetail?billDetail='+JSON.stringify(item)+'&current='+current)"
-					class="item" hover-class="hoverClass" v-for="(item,index) in list" :key="index">
-					<block v-if="current==0">
-						<view class="area1">
-							<view class="item-padding">
-								<image style="border-radius: 50%;"
-									:src="item.avatar?item.avatar:'/static/icon/avatar.png'" mode="aspectFit">
-								</image>
-								<view class="margin-left-10">
-									<text>{{item.nickName || '用户支付'}}</text>
-									<text>{{item.createTime}}</text>
-								</view>
-							</view>
-						</view>
-						<view class="area2 text-area" style="width: 15%;">
-							<view class="item-padding">
-								<text>{{item.discount==-1 || item.discount==0?'无折扣':item.discount +'折'}}</text>
-							</view>
-						</view>
-						<view class="area3 text-area u-p-r-20" style="width: 30%;">
-							<view class="item-padding"
-								style="flex:1;text-align: right;font-size: 34rpx;color: #F39248;">
-								+¥{{item.cost || 0}}</view>
-						</view>
-					</block>
-					
-					<block v-if="current==1">
-						<view class="area1">
-							<view class="item-padding">
-								<image :src="item.channelLogo" mode="aspectFit"></image>
-								<view class="">
-									<text>{{item.channelName}}</text>
-									<text>{{item.createTime}}</text>
-								</view>
-							</view>
-						</view>
-						<view class="area2 text-area ">
-							<view class="item-padding">
-								<image style="width: 35rpx;height: 35rpx;margin-bottom: -5rpx;"
-									src="@/static/icon/points-value.png"></image>
-								<text style="font-size: 32rpx;margin-left: 10rpx;color: #F39248;">+{{item.price  || 0}}</text>
-							</view>
-						</view>
-						<view class="area3 text-area ">
-							<view class="item-padding" style="font-size: 34rpx;color: #000;">¥{{item.price  || 0}}</view>
-						</view>
-					</block>
-				</view>
-			</mescroll-body>
-
-
-		</view>
-	</view>
-</template>
-
-<script>
-	import MescrollMixin from "@/components/mescroll-body/mescroll-mixins.js";
-	export default {
-		mixins: [MescrollMixin],
-		data() {
-			return {
-				activeItemStyle: {
-					fontWeight: 800,
-					fontSize: '36rpx'
-				},
-				tabslist: [{
-					name: '余额明细'
-				}, {
-					name: '应收明细'
-				}],
-				current: 0,
-				list: [],
-				downOption: {
-					auto: false
-				},
-				upOption: {
-					empty: {
-						fixed: true,
-						top: "-180rpx"
-					}
-				},
-
-				showTime: false,
-				params: {
-					year: true,
-					month: true,
-				},
-				defaultTime: '',
-				
-				shopData: {},
-				height: '',
-			}
-		},
-		onLoad() {
-			this.defaultTime=this.$dateTime.format(new Date(),'YYYY-mm')
-			this.shopDetail()
-		},
-		onReady() {
-			this.getElInfo()
-		},
-		methods: {
-			async getElInfo() {
-				let rectInfo = await this.$u.getRect('.card');
-				this.height = this.$u.sys().windowHeight - rectInfo.top + 'px'
-			},
-			async shopDetail() {
-				let params = {
-					shopId: this.vuex_shopId
-				}
-				let res = await this.$api.shop.shopBillsInfo(params)
-				this.shopData = res.data
-			},
-			async shop() {
-				let params = {}
-
-				let res = await this.$api.shop.remainDetailPage(params)
-			},
-			confirmTime(e) {
-				this.defaultTime = e.year + '-' + e.month
-				this.downCallback()
-			},
-			upCallback(mescroll) {
-				if (!this.vuex_shopId) {
-					return
-				}
-				let params = {
-					receiveId: this.vuex_shopId,
-					current: mescroll.num,
-					size: mescroll.size,
-					payStatus:this.$global.PAY_STATUS.SUCCESS
-				}
-				if (this.defaultTime) {
-					params.createTime = this.$dateTime.format(new Date(this.defaultTime))
-				} else {
-					params.createTime = this.$dateTime.format(new Date())
-				}
-				try {
-					if (this.current == 0) {
-						this.$api.bills.list(params).then(res => {
-							let data = res.data.records
-							let total = res.data.total
-							mescroll.endBySize(data.length, total);
-							if (mescroll.num == 1) this.list = []; //如果是第一页需手动制空列表
-							this.list = this.list.concat(data); //追加新数据
-						})
-					} else if (this.current == 1) {
-						this.$api.pointBills.list(params).then(res => {
-							let data = res.data.records
-							let total = res.data.total
-							mescroll.endBySize(data.length, total);
-							if (mescroll.num == 1) this.list = []; //如果是第一页需手动制空列表
-							this.list = this.list.concat(data); //追加新数据
-						})
-					}
-
-				} catch (e) {
-					this.mescroll.endErr()
-				}
-			},
-			downCallback() {
-				setTimeout(() => {
-					this.mescroll.resetUpScroll();
-				}, 500)
-			},
-			change(index) {
-				this.current = index;
-				this.mescroll.resetUpScroll();
-			},
-			goStatistics(){
-				let url='/pages/statistics/statistics'
-				if (this.current==1) {
-					url='/pages/statistics/pointBillStatistics'
-				}
-				uni.navigateTo({
-					url
-				})
-			}
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.btn {
-		background-color: #FC8D38;
-		color: #FFFFFF;
-		border-radius: 50rpx;
-		border: 1rpx solid #FFFFFF;
-	}
-
-	.hoverClass1 {
-		box-shadow: 0rpx 0rpx 10rpx #DDDDDD;
-	}
-
-	.top {
-		padding: 36rpx 50rpx;
-		background-image: linear-gradient(to right, #FBA33D, #FF8D32);
-		display: flex;
-		flex-direction: column;
-		justify-content: center;
-
-		.tixian {
-			display: flex;
-			justify-content: space-between;
-		}
-
-		.value {
-			display: flex;
-			flex-direction: column;
-			text-align: center;
-
-			text:first-child {
-				text-align: left;
-				color: #FCD7BD;
-				font-size: 32rpx;
-			}
-
-			text:last-child {
-				padding-top: 10rpx;
-				font-size: 60rpx;
-				color: #FFFFFF;
-			}
-		}
-	}
-
-	.data {
-		padding: 50rpx 0 25rpx 40rpx;
-		display: flex;
-		justify-content: space-between;
-
-		.left {
-			display: flex;
-			flex-direction: column;
-
-			view:first-child {
-				font-size: 34rpx;
-				color: #000;
-				padding-bottom: 10rpx;
-			}
-
-			view:last-child {
-				font-size: 26rpx;
-				color: #666666;
-			}
-		}
-
-		.right {
-			padding-right: 20rpx;
-			color: #666666;
-			display: flex;
-			justify-content: center;
-			align-items: center;
-			text-align: center;
-		}
-	}
-
-	.card {
-		background-color: #FFFFFF;
-
-		.area-padding {
-			padding: 40rpx 0 20rpx;
-		}
-
-		.text-area {
-			display: flex;
-			justify-content: flex-start;
-			align-items: center;
-		}
-
-		.area1 {
-			padding-left: 30rpx;
-			width: 50%;
-
-			view:first-child {
-				display: flex;
-
-				image {
-					width: 80rpx;
-					height: 80rpx
-				}
-
-				view {
-					padding-left: 15rpx;
-					padding-bottom: 5rpx;
-					display: flex;
-					flex-direction: column;
-
-					text:first-child {
-						font-size: 32rpx;
-						padding-bottom: 10rpx;
-						color: #000;
-					}
-
-					text:last-child {
-						font-size: 22rpx;
-						color: #888888;
-					}
-				}
-			}
-		}
-
-		.area2 {
-			width: 30%;
-		}
-
-		.area3 {
-			width: 20%;
-		}
-
-		.item-padding {
-			padding: 20rpx 0;
-		}
-
-		.item {
-			padding: 5rpx;
-			display: flex;
-			border-bottom: 1rpx solid #DDDDDD;
-		}
-
-		.item:last-child {
-			border: none;
-		}
-
-
-
-	}
-</style>

+ 0 - 217
pages/bill/billDetail.vue

@@ -1,217 +0,0 @@
-<template>
-	<view>
-		<block v-if="current==0">
-			<view class="top">
-				<image style="border-radius: 50%;" :src="billDetail.avatar?billDetail.avatar:'/static/icon/avatar.png'" mode="aspectFit"></image>
-				<text class="title">{{billDetail.nickName?billDetail.nickName:'微信用户'}}</text>
-				<view class="data">
-					<view class="mainColor" style="padding: 0;">
-						+{{billDetail.cost}}
-					</view>
-				</view>
-			</view>
-			<view class="card">
-				<view class="item">
-					<text>订单标题</text>
-					<text class="strong">{{billDetail.title}}</text>
-				</view>
-				<view class="item">
-					<text>商品原价</text>
-					<text class="strong">{{billDetail.cost}}</text>
-				</view>
-				<view class="item">
-					<text>现金支付</text>
-					<text class="strong">+{{billDetail.price}}</text>
-				</view>
-				<view class="item">
-					<text>积分余额支付</text>
-					<text class="strong">+{{billDetail.balanceNum}}</text>
-				</view>
-				<view class="item">
-					<text>渠道积分支付</text>
-					<text class="strong">+{{billDetail.pointNum}}</text>
-				</view>
-				<view class="item">
-					<text>积分服务费</text>
-					<text class="strong">{{billDetail.pointFee}}</text>
-				</view>
-<!-- 				<view class="item">
-					<text>积分成本</text>
-					<view class="u-flex">
-						<image style="width: 26rpx;height: 26rpx;" src="@/static/icon/points-value.png" mode="aspectFit"></image>
-						<text class="mainColor margin-left-10">{{billDetail.point?billDetail.point:0}}</text>
-						<text class="strong" style="margin-left: 50rpx;">¥ {{billDetail.pointValue?billDetail.pointValue:0}}</text>
-					</view>
-				</view> -->
-				
-				<view class="item">
-					<text>联营折扣</text>
-					<text style="color: #000;">{{billDetail.discount==-1 || billDetail.discount==0 || billDetail.discount==1?'无折扣': $digital.floatMul(billDetail.discount , 10) +'折'}}</text>
-				</view>
-				<view class="item">
-					<text>交易状态</text>
-					<text>{{billDetail.payStatus}}</text>
-				</view>
-				<view class="item">
-					<text>交易时间</text>
-					<text>{{billDetail.createTime}}</text>
-				</view>
-				<view class="item">
-					<text>支付方式</text>
-					<text v-if="billDetail.payWay=='WECHAT'">微信支付</text>
-					<text v-if="billDetail.payWay=='ALIPAY'">支付宝支付</text>
-					<text v-if="billDetail.payWay=='APPLEPAY'">银联支付</text>
-				</view>
-				<view class="item">
-					<text>交易单号</text>
-					<text>{{billDetail.id}}</text>
-				</view>
-			</view>
-		</block>
-		
-		<block v-if="current==1">
-			<view class="top">
-				<image :src="billDetail.channelLogo?billDetail.channelLogo:'/static/icon/avatar.png'" mode="aspectFit"></image>
-				<text class="title">{{billDetail.channelName}}</text>
-				<view class="data">
-					<image src="@/static/icon/points-value.png" mode="aspectFit"></image>
-					<view>
-						<text>-{{billDetail.point}}</text>
-						<text>(价值 ¥ {{billDetail.pointValue}})</text>
-					</view>
-				</view>
-			</view>
-			<view class="card">
-				<view class="item">
-					<text>交易状态</text>
-					<text>交易成功</text>
-				</view>
-				<view class="item" v-if="billDetail.jsStatus">
-					<text>结算时间</text>
-					<text>{{billDetail.jsStatus}}</text>
-				</view>
-				<view class="item">
-					<text>账期</text>
-					<text>{{billDetail.paymentDays}}</text>
-				</view>
-				<view class="item">
-					<text>产生时间</text>
-					<text>{{billDetail.updateTime}}</text>
-				</view>
-				<view class="item">
-					<text>交易时间</text>
-					<text>{{billDetail.jsTime}}</text>
-				</view>
-				<view class="item">
-					<text>交易单号</text>
-					<text>{{billDetail.billRecordId}}</text>
-				</view>
-				<view class="item">
-					<text>商户单号</text>
-					<text>{{billDetail.billRecordId}}</text>
-				</view>
-			</view>
-		</block>
-		
-		<view class="question">
-			<text>对订单有疑问</text>
-			<text class="cuIcon-right" style="margin-top: 5rpx;"></text>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default{
-		data(){
-			return{
-				billDetail:{},
-				current:0
-			}
-		},
-		onLoad(option) {
-			if(option.billDetail){
-				this.billDetail = JSON.parse(option.billDetail)
-			}
-			if(option.current){
-				this.current = option.current
-			}
-		}
-	}
-</script>
-
-<style scoped lang="scss">
-	.top {
-		padding: 50rpx 0 0;
-		display: flex;
-		justify-content: center;
-		align-items: center;
-		flex-direction: column;
-	
-		image {
-			width: 140rpx;
-			height: 140rpx;
-		}
-	
-		.title {
-			color: #000;
-			padding-top: 15rpx;
-			font-size: 32rpx;
-		}
-	
-		.data {
-			padding-top: 30rpx;
-			display: flex;
-	
-			image {
-				width: 40rpx;
-				height: 40rpx;
-			}
-	
-			view {
-				padding-left: 20rpx;
-	
-				text:first-child {
-					color: #000;
-					font-size: 38rpx;
-				}
-	
-				text:last-child {
-					font-size: 32rpx;
-					padding-left: 20rpx;
-				}
-			}
-		}
-	}
-	
-	.card {
-		margin-top: 50rpx;
-		padding: 20rpx 30rpx;
-		background-color: #FFFFFF;
-		
-		.item{
-			padding: 20rpx 0;
-			font-size: 28rpx;
-			color: #888888;
-			margin: 0 20rpx;
-			display: flex;
-			justify-content: space-between;
-		}
-	}
-	
-	.question{
-		color: #888888;
-		background-color: #FFFFFF;
-		margin-top: 20rpx;
-		padding: 20rpx 50rpx;
-		display: flex;
-		justify-content: space-between;
-	}
-	.mainColor{
-		font-weight: bold;
-		color: $color;
-	}
-	.strong{
-		font-weight: bold;
-		color: #000;
-	}
-</style>

+ 2 - 2
pages/card/card.vue

@@ -41,7 +41,7 @@
 						icon: 'cuIcon-down',
 						name: '物料下载',
 						verify:true,
-						path: '/pages/material-download/material-download'
+						path: '/pagesPoster/pages/material-download'
 					},
 					{
 						icon: 'cuIcon-community',
@@ -82,7 +82,7 @@
 			},
 			jump(item) {
 				if (item.verify && this.vuex_shopStatus != 'PASS') {
-					this.$refs.toast.error('商户资料审核通过后开放')
+					this.$refs.toast.error('商户资料暂未审核通过')
 					return
 				}
 				if (item.name=='物料下载'&&!this.vuex_isOpenMember) {

+ 8 - 2
pages/index/index.vue

@@ -156,7 +156,13 @@
 					{
 						icon: '/static/index/dingdan3.png',
 						name: '订单中心',
-						path: '/pages/order/order',
+						path: '/pagesGoods/pages/order/order',
+						count: 0
+					},
+					{
+						icon: '/static/index/notice2.png',
+						name: '通知公告',
+						path: '/pages/notice/list',
 						count: 0
 					},
 				],
@@ -380,7 +386,7 @@
 							confirmText: '去认证',
 							success: function(res) {
 								if (res.confirm) {
-									_this.$jump('/pages/webView/webView?url=' + _this.taskDetail.variables
+									_this.$jump('/pages/auth/auth?src=' + _this.taskDetail.variables
 										.qrcodeUrl)
 								}
 							}

+ 0 - 2
pages/login/account-login.vue

@@ -82,8 +82,6 @@
 			this.$refs.uForm.setRules(this.rules);
 		},
 		async onLoad(options) {
-			console.log(this.$u.guid(20));
-			
 			this.form.phone=options.phone || ''
 			if (this.$cache.get('phone')) {
 				this.$refs.loading.show("登录中..")

+ 0 - 155
pages/material-download/comps/mp-swiper -tmp.vue

@@ -1,155 +0,0 @@
-<template>
-	<view class="swiper">
-		<view class="swiper-title">
-			<swiper :style="{height:fullHeight}" class="swiper-tall" :indicator-dots="indicatorDots"
-				:autoplay="autoplay" :previous-margin="previousMargin" :next-margin="nextMargin" :circular="circular"
-				@change="change" :current="swiperCurrentIndex">
-				<swiper-item class="swiper-container" v-for="(item,index) in list" :key="index" :item-id="index"
-					:data-year="index">
-					<view :animation="animationData[index]" class="swiper-item" style="position: relative;">
-						<image :src="item.image" mode=""></image>
-						<view class="content">
-							<text class="">{{shopDetail.name}}</text>
-							<tki-qrcode style="margin-top: -100rpx;" cid="1" ref="qrcode-charge" :val="qrcodeText"
-								size="260" :onval="true" :loadMake="true" :usingComponents="true" />
-						</view>
-					</view>
-				</swiper-item>
-			</swiper>
-		</view>
-		<view class="center flex-direction">
-			<text style="margin-bottom: 50rpx;">{{list[swiperCurrentIndex].name}}</text>
-			<view @click="createPoster" class="cu-btn  flex round text-lg"
-				style="padding: 46rpx 0;background-color: #EF9944;color: #FFFFFF;width: 76%;">
-				生成海报
-			</view>
-		</view>
-	</view>
-</template>
-<script>
-	import tkiQrcode from "tki-qrcode"
-	export default {
-		props: {
-			list: Array
-		},
-		components: {
-			tkiQrcode
-		},
-		data() {
-			return {
-				qrcodeText:'',
-				
-				screenHeight: 0,
-				animationData: {
-					0: {},
-					1: {},
-					2: {},
-					3: {}
-				},
-				title: '0',
-				indicatorDots: false,
-				autoplay: false,
-				previousMargin: uni.upx2px(82) + 'px',
-				nextMargin: uni.upx2px(82) + 'px',
-				circular: true,
-				zoomParam: 1.10,
-				swiperCurrentIndex: 0,
-				data: [],
-				max: 0,
-				//商户详情
-
-				shopDetail: {}
-			}
-		},
-		computed: {
-			fullHeight() {
-				const res = uni.getSystemInfoSync();
-				return res.windowHeight - (res.statusBarHeight + 44) + 'px';
-			}
-		},
-		async mounted(option) {
-			let res = await this.$api.shop.detail({
-				id: this.vuex_shopId
-			})
-			this.shopDetail = res.data
-			this.qrcodeText=this.$global.QR_PATH+this.vuex_shopId
-		},
-		created() {
-			this.animation = uni.createAnimation();
-			this.animation.scale(this.zoomParam).step();
-			this.animationData[0] = this.animation.export();
-		},
-		methods: {
-			createPoster() {
-				this.$emit('click', this.list[this.swiperCurrentIndex].image)
-			},
-			change(e) {
-				this.swiperCurrentIndex = e.detail.current;
-				this.title = e.detail.currentItemId;
-				for (let key in this.animationData) {
-					if (e.detail.currentItemId == key) {
-						this.animation.scale(this.zoomParam).step();
-						this.animationData[key] = this.animation.export();
-					} else {
-						this.animation.scale(1.0).step();
-						this.animationData[key] = this.animation.export();
-					}
-				}
-				this.$emit('change', this.list[this.swiperCurrentIndex].image)
-			}
-		}
-	}
-</script>
-
-<style>
-	page {
-		display: flex;
-		flex-wrap: wrap;
-	}
-
-	.content {
-		position: absolute;
-		display: flex;
-		flex-direction: column;
-		justify-content: center;
-		align-items: center;
-		top: 30rpx;
-	}
-
-
-	.save-btn {
-		background-color: #EF9944;
-		color: #FFFFFF;
-	}
-
-	.swiper-container {
-		display: flex;
-		align-items: center;
-	}
-
-	.swiper-item {
-		display: flex;
-		flex-wrap: wrap;
-		justify-content: center;
-		margin-left: auto;
-		margin-right: auto;
-		height: 760upx;
-		width: 544upx;
-		line-height: 300upx;
-		text-align: center;
-		margin-bottom: 50upx;
-	}
-
-
-
-	.swiper-tall {
-		display: flex;
-		align-items: center;
-	}
-
-	.swiper-title {
-		margin-top: -100rpx;
-		width: 760upx;
-		text-align: center;
-	}
-</style>

+ 1 - 1
pages/member/detail.vue

@@ -39,7 +39,7 @@
 					</view>
 					<view class="area2 text-area" style="width: 15%;">
 						<view class="center">
-							<text style="font-size: 26rpx;color: #666;margin-left: -10rpx;">{{item.discount==-1 || item.discount==0?'无折扣':item.discount +'折'}}</text>
+							<text style="font-size: 26rpx;color: #666;margin-left: -10rpx;">{{discount(item.discount)}}</text>
 						</view>
 					</view>
 					<view class="area3 text-area u-p-r-20" style="width: 30%;">

+ 30 - 5
pages/member/member.vue

@@ -2,7 +2,7 @@
 	<view>
 		<u-navbar :custom-back="back" title="会员中心"></u-navbar>
 		
-		<block >
+		<view v-show="!loading">
 			<view class="empty-page" v-if="!isOpenMember">
 				<image src="../../static/icon/huiyuan1.png" mode=""></image>
 				<text style="color: #303030;font-weight: 800;font-size: 32rpx;margin-top: 25rpx;">创建会员中心</text>
@@ -77,7 +77,17 @@
 					</mescroll-body>
 				</view>
 			</block>
-		</block>
+			
+			<view  v-if="isOpenMember&&$isNotEmpty(detail.memberNum)">
+				<view class="" style="height: 40rpx;"></view>
+				<view class="footer-fixed center bg-white padding-top-20" :style="{'paddingBottom':safeAreaBottom}" >
+					<view @click="$jump('/pages/notice/notice')" class="cu-btn bg-btn radius" style="width: 80%;height: 80rpx;">
+						<u-icon name="chat" size="40"></u-icon>
+						<text class="margin-left-10">群发消息</text>
+					</view>
+				</view>
+			</view>
+		</view>
 		
 		<u-popup v-model="showPopup" mode="center" border-radius="20">
 			<view class="u-popup-content">
@@ -94,7 +104,8 @@
 				<u-button size="medium" shape="circle" :custom-style="customStyle2" @click="showPopup=false">取消</u-button>
 			</view>
 		</u-popup>
-		<loading ref="loading" type="3" theme="2"/>
+		<toast ref="toast" ></toast>
+		<loading ref="loading" type="3" />
 	</view>
 </template>
 
@@ -112,7 +123,7 @@
 				
 				height:'300px',
 				downOption: {
-					use: true,
+					use: false,
 					auto: false // 不自动加载
 				},
 				upOption: {
@@ -146,6 +157,7 @@
 			this.getElInfo()
 		},
 		onLoad() {
+			this.$refs.loading.showLoading()
 			this.fetchMemberInfo()
 		},
 		methods: {
@@ -181,6 +193,9 @@
 				if (res.data.isOpenMember == 1) {
 					this.isOpenMember = true
 					this.detail = res.data
+				}else{
+					this.loading=false
+					this.$refs.loading.hide()
 				}
 			},
 			downCallback() {
@@ -192,7 +207,7 @@
 				let params = {
 					shopId: this.vuex_shopId,
 					current: mescroll.num,
-					size: mescroll.size,
+					size: 30,
 					//商店会员
 					type:'SHOP'
 				}
@@ -203,8 +218,12 @@
 						mescroll.endBySize(data.length, total);
 						if (mescroll.num == 1) this.dataList = []; //如果是第一页需手动制空列表
 						this.dataList = this.dataList.concat(data); //追加新数据
+						this.loading=false
+						this.$refs.loading.hide()
 					})
 				} catch (e) {
+					this.loading=false
+					this.$refs.loading.hide()
 					this.mescroll.endErr()
 				}
 			},
@@ -222,6 +241,12 @@
 </script>
 
 <style lang="scss" scoped>
+	
+	.bg-btn{
+		background-color: #F39248;
+		color: #FFFFFF;
+	}
+	
 	.empty-page {
 		height: 600rpx;
 		display: flex;

+ 1 - 9
pages/my-bills/bills-detail.vue

@@ -37,7 +37,7 @@
 				</view>
 				<view class="item">
 					<text>联营折扣</text>
-					<text style="color: #000;">{{billDetail.discount==-1 || billDetail.discount==0|| billDetail.discount==1?'无折扣': $digital.floatMul(billDetail.discount , 10) +'折'}}</text>
+					<text style="color: #000;">{{discount(billDetail.discount)}}</text>
 				</view>
 				<view class="item">
 					<text>现金支付</text>
@@ -51,14 +51,6 @@
 					<text>渠道积分支付</text>
 					<text class="strong price plus">{{billDetail.pointNum || 0.00}}</text>
 				</view>
-				<view class="item">
-					<text>积分手续费</text>
-					<text class="text-base text-bold price reduce">{{billDetail.pointFee || 0.00}}</text>
-				</view>
-				<view class="item">
-					<text>平台手续费</text>
-					<text class="text-base text-bold price reduce">{{billDetail.fee || 0.00}}</text>
-				</view>
 				<view class="item">
 					<text>交易手续费</text>
 					<text class="text-base text-bold price reduce">{{billDetail.merchantFee || 0.00}}</text>

+ 3 - 2
pages/my-bills/comps/balance-bills.vue

@@ -81,7 +81,7 @@
 					</view>
 				</view>
 				<view class="area2">
-					<text>{{item.discount==-1 || item.discount==0 || item.discount==1?'无折扣':item.discount +'折'}}</text>
+					<text>{{discount(item.discount)}}</text>
 				</view>
 				<view class="area3">
 					<text class="text-base price plus">{{item.receiveNumYp || 0}}</text>
@@ -287,6 +287,7 @@
 		width: 54%;
 		display: flex;
 		height: 120rpx;
+		padding-left: 30rpx;
 		justify-content: center;
 		align-items: center;
 
@@ -300,7 +301,7 @@
 		}
 
 		view {
-			width: calc(100% - $img-width);
+			width: 80%;
 			display: flex;
 			flex-direction: column;
 			justify-content: space-between;

+ 6 - 6
pages/my-bills/comps/bills.vue

@@ -56,7 +56,7 @@
 						<image v-else src="@/static/icon/avatar.png"></image>
 					</block>
 					<view>
-						<text v-if="$isNotEmpty(item.nickName)">{{item.nickName}}</text>
+						<text class="text-cut-2" v-if="$isNotEmpty(item.nickName)">{{item.nickName}}</text>
 						<block v-else>
 							<text v-if="item.payWay=='WECHAT'">微信用户</text>
 							<text v-else-if="item.payWay=='ALIPAY'">支付宝用户</text>
@@ -68,11 +68,10 @@
 					</view>
 				</view>
 				<view class="area2">
-					<text>{{item.discount==-1 || item.discount==0 || item.discount==1?'无折扣':item.discount +'折'}}</text>
+					<text>{{discount(item.discount)}}</text>
 				</view>
 				<view class="area3">
-					<text class="text-base price"
-						v-if="$isNotEmpty(item.receiveNumTotal)">{{item.receiveNumTotal}}</text>
+					<text class="text-base price" v-if="$isNotEmpty(item.receiveNumTotal)">{{item.receiveNumTotal}}</text>
 					<text class="text-base price" v-else>{{item.cost || 0}}</text>
 				</view>
 			</navigator>
@@ -195,7 +194,8 @@
 		width: 54%;
 		display: flex;
 		height: 120rpx;
-		justify-content: center;
+		padding-left: 30rpx;
+		justify-content: flex-start;
 		align-items: center;
 
 		image {
@@ -208,7 +208,7 @@
 		}
 
 		view {
-			width: calc(100% - $img-width);
+			width: 80%;
 			display: flex;
 			flex-direction: column;
 			justify-content: space-between;

+ 3 - 2
pages/my-bills/comps/channel-point-bill.vue

@@ -65,7 +65,7 @@
 						</view>
 					</view>
 					<view class="area2">
-						<text>{{item.discount==-1 || item.discount==0?'无折扣':item.discount +'折'}}</text>
+						<text>{{discount(item.discount)}}</text>
 					</view>
 					<view class="area3">
 						<text class="text-base price plus">{{item.pointNum || 0}}</text>
@@ -200,6 +200,7 @@
 		width: 54%;
 		display: flex;
 		height: 120rpx;
+		padding-left: 30rpx;
 		justify-content: center;
 		align-items: center;
 
@@ -213,7 +214,7 @@
 		}
 
 		view {
-			width: calc(100% - $img-width);
+			width: 80%;
 			display: flex;
 			flex-direction: column;
 			justify-content: space-between;

+ 3 - 2
pages/my-bills/comps/point-bills.vue

@@ -66,7 +66,7 @@
 					</view>
 				</view>
 				<view class="area2">
-					<text>{{item.discount==-1 || item.discount==0?'无折扣':item.discount +'折'}}</text>
+					<text>{{discount(item.discount)}}</text>
 				</view>
 				<view class="area3">
 					<text class="text-base price plus">{{item.balanceNum || 0}}</text>
@@ -263,6 +263,7 @@
 		width: 54%;
 		display: flex;
 		height: 120rpx;
+		padding-left: 30rpx;
 		justify-content: center;
 		align-items: center;
 
@@ -276,7 +277,7 @@
 		}
 
 		view {
-			width: calc(100% - $img-width);
+			width: 80%;
 			display: flex;
 			flex-direction: column;
 			justify-content: space-between;

+ 67 - 0
pages/notice/detail.vue

@@ -0,0 +1,67 @@
+<template>
+	<view class="safe-area-inset-bottom">
+		<view class="flex justify-end padding-30">
+			<view @click="edit" class="cu-btn radius sm bg-base">
+				编辑
+			</view>
+		</view>
+		<view class="text-area" v-html="content"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				id: '',
+				content: '',
+				detail: {}
+			}
+		},
+		onLoad(options) {
+			this.id = options.id
+			this.fetchDetail()
+		},
+		onShow() {
+			this.fetchDetail()
+		},
+		methods: {
+			edit(){
+				uni.navigateTo({
+					url:"notice?id="+this.id
+				})
+			},
+		    async fetchDetail() {
+				let params = {
+					id: this.id
+				}
+				let res=await this.$api.notice.detail(params)
+				this.detail = res.data || {}
+				this.content = decodeURIComponent(this.detail.content)
+				if (this.$isNotEmpty(this.detail.title)) {
+					uni.setNavigationBarTitle({
+						title:this.detail.title
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	page {
+		background-color: #FFFFFF;
+	}
+</style>
+
+<style lang="scss" scoped>
+	.text-area {
+		padding: 20rpx;
+	}
+	
+	.title{
+		text-align: center;
+		font-size: 34rpx;
+		font-weight: 800;
+	}
+</style>

+ 118 - 0
pages/notice/list.vue

@@ -0,0 +1,118 @@
+<template>
+	<view class="safe-area-inset-bottom margin-top-10">
+		<mescroll-body :height="height" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
+			:down="downOption" :up="upOption">
+			<view @click="jump(item)" class="cart-view-box" v-for="(item,index) in list" :key="index">
+				<view class="text-gray text-center text-sm">{{item.createTime}}</view>
+				<view class="bg-white margin-top-10 radius card-view">
+					<view class="content-view">
+						<view class="flex">
+							<view class="center">
+								<text class=" text-lg text-cut" style="color: #000000;">{{item.title}}</text>
+							</view>
+						</view>
+						<view class=" text-sm text-cut-2 subtitle">{{item.content | formatHtml}}</view>
+						<view class="flex text-gray justify-between "
+							style=" border-top: 1rpx solid #f2f2f2;box-sizing: border-box;padding-top: 15rpx;">
+							<view class="text-df ">
+								<text>查看详情</text>
+							</view>
+							<view style="padding-top: 8rpx;">
+								<text class="cuIcon-right "></text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</mescroll-body>
+		<toast ref="toast"></toast>
+	</view>
+</template>
+<script>
+	import MescrollMixin from "@/components/mescroll-body/mescroll-mixins.js";
+	export default {
+		mixins: [MescrollMixin],
+		data() {
+			return {
+				list: [],
+				downOption:{
+					auto:false
+				}
+			}
+		},
+		filters: {
+			formatHtml(str) {
+				try{
+					str= decodeURIComponent(str).replace(/<[^>]+>/g, "")
+				}catch(e){
+					console.log(e);
+				}
+				return str
+			}
+		},
+		methods: {
+			jump(item) {
+				uni.navigateTo({
+					url:"./detail?id="+item.id
+				})
+			},
+			downCallback() {
+				setTimeout(() => {
+					this.$refs.toast.info('刷新成功')
+					this.mescroll.resetUpScroll();
+				}, 1000)
+			},
+			upCallback(mescroll) {
+				let params = {
+					senderId: this.vuex_shopId,
+					current: mescroll.num,
+					size: mescroll.size,
+				}
+				try {
+					this.$api.notice.list(params).then(res => {
+						let data = res.data.records
+						let total = res.data.total
+						mescroll.endBySize(data.length, total);
+						if (mescroll.num == 1) this.list = []; //如果是第一页需手动制空列表
+						this.list = this.list.concat(data); //追加新数据
+					})
+				} catch (e) {
+					this.mescroll.endErr()
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F3F3F3;
+		font-size: 28rpx;
+	}
+
+	.subtitle {
+		color: #7e7e7e;
+		font-size: 28rpx;
+		margin: 30rpx 0 10rpx 0;
+		line-height: 52rpx;
+	}
+
+	.cart-view-box {
+		padding: 25rpx 20rpx;
+
+		.card-view {
+			background-color: #FFFFFF;
+			position: relative;
+			border-radius: 10rpx;
+
+			.head-img {
+				width: 100%;
+				height: 236rpx;
+			}
+
+			.content-view {
+				padding: 27rpx 27rpx 15rpx;
+			}
+		}
+	}
+</style>

+ 106 - 0
pages/notice/notice.vue

@@ -0,0 +1,106 @@
+<template>
+	<view>
+		<cu-editor ref="editor" :url="uploadUrl" :header="header" :formData="formData" :content="content"
+			@before="onUploadBefore" @update="onUpdate" @save="onSave"></cu-editor>
+		<toast ref="toast"></toast>
+	</view>
+</template>
+<script>
+	import setting from "@/assets/http/setting.js"
+	import cuEditor from '@/components/cu-editor/cu-editor'
+	import Base64 from 'base-64';
+	import {
+		handleHtmlImage
+	} from '@/components/cu-editor/util'
+
+	export default {
+		components: {
+			cuEditor
+		},
+		data() {
+			return {
+				id:'',
+				successTitlte:"发布成功",
+				content: '',
+				uploadUrl: setting.baseURL + 'blade-resource/oss/endpoint/put-file',
+				header: {},
+				formData: {},
+				form: {
+					title: '',
+					content: '',
+				}
+			}
+		},
+		onLoad(options) {
+			this.id=options.id
+			this.init()
+		},
+		methods: {
+			init(){
+				if (this.$isEmpty(this.id)) {
+					return
+				}
+				this.successTitlte="修改成功"
+				uni.setNavigationBarTitle({
+					title:"编辑公告"
+				})
+				let params={
+					id:this.id
+				}
+				this.$api.notice.detail(params).then(res=>{
+					if (res.data) {
+						let detail=res.data
+						this.content= decodeURIComponent(detail.content)
+						this.$refs.editor.initTitle(detail.title)
+					}
+				})
+			},
+			onUploadBefore: function() {
+				this.formData = {
+					"Authorization": "Basic c2FiZXI6c2FiZXJfc2VjcmV0",
+					"Blade-Auth": uni.getStorageSync('token'),
+					"timestamp": (Date.parse(new Date())) / 1000
+				}
+			},
+			onUpdate(res) {
+				res.html = handleHtmlImage(res.html)
+				this.value = res.html
+			},
+			//保存
+			onSave(e) {
+				let tilte = e.title
+				let content = e.content
+
+				let html = content.html
+				var containsImage = html.search(/<img /i) >= 0 //内容是否包含图片标签
+				let txt = content.text.replace(/(^\s*)|[\r\n]|(\s*$)/g, "") //去掉换行符和两端空格
+
+				this.form = {
+					title: e.title,
+					content: txt == "" && !containsImage ? txt : html
+				}
+				this.submit()
+				uni.$emit('save', this.form)
+			},
+			submit() {
+				let form = this.$u.deepClone(this.form)
+				form.id=this.id
+				form.senderId = this.vuex_shopId
+				form.sender = this.$cache.get('selectedShop').label
+				form.content= encodeURIComponent(form.content)
+				this.$api.notice.submitNotice(form).then(res => {
+					if (res.success) {
+						this.$dialog.showModalAndBack(this.successTitlte)
+					}
+				})
+			},
+
+		}
+	}
+</script>
+
+<style>
+	page {
+		background-color: #FFFFFF;
+	}
+</style>

+ 0 - 71
pages/order/comps/card.vue

@@ -1,71 +0,0 @@
-<template>
-	<view>
-		<view @click="$jump('/pages/order/detail?id='+item.id)" class="card" v-for="(item,index) in list" :key="index">
-			<view class="center">
-				<image
-					src="https://guosen-bucket-ldt.obs.cn-south-1.myhuaweicloud.com:443/b15e8992179b4b30b9bdb943d8ad9c07-uWGk0l5GutNQ3013850822b2cdb5f77a445ce68ab57e.jpeg"
-					mode="aspectFill"></image>
-			</view>
-			<view class="content">
-				<view class="flex justify-between">
-					<text class="text-bold text-lg">杨国福麻辣烫</text>
-					<view class="">
-						<text v-if="item.payStatus=='付款成功'" class="text-base">{{item.orderStatus}}</text>
-						<text v-else class="text-base">{{item.payStatus}}</text>
-					</view>
-				</view>
-				
-				<view style="font-size: 26rpx;color: #888888;">
-					<view class="margin-bottom-10">
-						<text>{{item.id}}</text>
-						<text @click.stop="$util.copy(item.id)" class="margin-left-10 text-black">复制</text>
-					</view>
-					<view class="flex justify-between ">
-						<text class="center">{{item.createTime}}</text>
-						<text class="">消费:{{item.totalPrice / 100}}元</text>
-					</view>
-				</view>
-
-			</view>
-		</view>
-	</view>
-</template>
-
-<script>
-	export default {
-		props:{
-			list:Array
-		},
-		data() {
-			return {
-
-			}
-		},
-		methods: {
-
-		}
-	}
-</script>
-
-<style lang="scss">
-	.card {
-		margin: 10rpx;
-		background-color: #FFFFFF;
-		display: flex;
-		padding: 18rpx;
-
-		image {
-			width: 150rpx;
-			height: 150rpx;
-			border-radius: 8rpx;
-		}
-
-		.content {
-			width: calc(100% - 140rpx - 20rpx - 20rpx);
-			margin-left: 20rpx;
-			display: flex;
-			flex-direction: column;
-			justify-content: space-between;
-		}
-	}
-</style>

+ 0 - 101
pages/order/comps/item.vue

@@ -1,101 +0,0 @@
-<template>
-	<view style="margin-top: 4rpx;">
-		<MeScroll  :up="up" :down="down" @up="upFn" :fixed="false" @down="downFn" @init="initMeScroll">
-			<card :list="list" ></card>
-		</MeScroll>
-	</view>
-	
-</template>
-<script>
-	import MeScroll from '@/components/mescroll-body/mescroll-uni.vue'
-	import card from './card.vue'
-	export default {
-		components:{
-			MeScroll,card
-		},
-		props: {
-			type: Number,
-			i: Number,
-			item:Object
-		},
-		data() {
-			return {
-				isInit: false, // 是否初始化
-				list: [], // 列表数据
-				mescroll: null, // mescroll 对象
-				// 上拉配置参数
-				up: {
-					noMoreSize: 5, 
-					auto: false,
-					page: {
-						page: 0,
-						size: 10
-					}
-				},
-				// 下拉配置参数
-				down: {
-					use: false, 
-					auto: false
-				}
-			}
-		},
-		created() {
-			
-		},
-		watch:{
-			type(val) {
-				if(!this.isInit && val === this.i) {
-					this.mescroll.resetUpScroll()
-				}
-			}
-		},
-		mounted() {
-			if(!this.isInit && this.i === 0) {
-				this.mescroll.resetUpScroll()
-			}
-		},
-		methods: {
-			//初始化组件
-			initMeScroll(mescroll) {
-				this.mescroll = mescroll
-			},
-			//上拉回调
-			upFn(mescroll) {
-				let params={
-					receiveId:this.vuex_shopId,
-					current:mescroll.num,
-					size:mescroll.size
-				}
-				if (this.item.value==0) {
-					params.createTime=this.$dateTime.format()
-				}
-				try{
-					this.$api.goodsbills.list(params).then(res=>{
-						let data=res.data.records
-						let length=data.length
-						let total=res.data.total
-						mescroll.endBySize(length, total);
-						if(mescroll.num == 1) this.list = []; //如果是第一页需手动制空列表
-						this.list=this.list.concat(data); //追加新数据
-					})
-				}catch(e){
-					console.log(e);
-					mescroll.endErr();
-				}
-			},
-			//下拉回调
-			downFn(mescroll) {
-				setTimeout(()=>{
-					this.u.toast('刷新成功')
-					this.mescroll.resetUpScroll()
-				},1500)
-			},
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	view{
-		box-sizing: border-box;
-	}
-</style>

+ 0 - 237
pages/order/detail.vue

@@ -1,237 +0,0 @@
-<template>
-	<view class="page safe-area-inset-bottom">
-
-		<view class="card section" style="flex-direction: column;">
-			<view class="center text-bold margin-50" style="font-size: 66rpx;">
-				<text>{{order.verifyNum}}</text>
-			</view>
-			<view class="cu-steps steps-arrow margin-bottom-50">
-				<view class="cu-item" :class="index>stepIndex?'text-default':'text-base'" v-for="(item,index) in stepList" :key="index">
-					<text style="font-size: 70rpx;margin-bottom: 20rpx;margin-right: 10rpx;" :class="'cuIcon-' + item.icon"></text>
-					<text >{{item.name}}</text>
-				</view>
-			</view>
-			<view class="center padding-30" style="color: #999;">
-				<text>备注:{{order.extraInfo}}</text>
-			</view>
-		</view>
-		<view class="section"></view>
-		
-		<view class="padding-10 bg-white">
-			<u-read-more ref="uReadMore" close-text="展开更多" show-height="300" color="#999">
-				<view v-for="(item,index) in cart" :key="index" class="cart">
-					<view class="flex" style="width: 70%;">
-						<image :src="item.image" mode=""></image>
-						<view class="item-content " >
-							<text class="text-cut-1">{{item.name}}</text>
-							<text class="text-cut-1">{{item.propertyStr ? item.propertyStr : item.name}}</text>
-						</view>
-					</view>
-					<view class="item-data">
-						<view class="">
-							<text class="text-sm">x</text>
-							<text class="text-lg" style="margin-left: 6rpx;">{{item.number}}</text>
-						</view>
-						<text class=" text-lg">{{item.realPrice / 100}}</text>
-					</view>
-				</view>
-			</u-read-more>
-		</view>
-		
-		<!-- 订单金额 -->
-		<view class="">
-			<view class="card text-df" v-if="$isNotEmpty(order.packingPrice)&&order.packingPrice != -1">
-				<text class="text-gray">包装费</text>
-				<text class="text-price">{{order.packingPrice / 100}}</text>
-			</view>
-			<view class="card text-df" v-if="$isNotEmpty(order.sendingPrice)&&order.sendingPrice != -1">
-				<text class="text-gray">配送费</text>
-				<text class="text-price">{{order.sendingPrice / 100}}</text>
-			</view>
-			<view class="card text-df ">
-				<text class="text-gray">金额总计</text>
-				<view class="">
-					<text class="text-price">{{order.totalPrice / 100}}</text>
-				</view>
-			</view>
-		</view>
-		
-		<view class="section"></view>
-		
-		<view class="">
-			<view class="card text-df" >
-				<text class="text-gray">取单号</text>
-				<text class="">{{order.verifyNum}}</text>
-			</view>
-			<view class="card text-df" v-if="$isNotEmpty(order.seatNum) && order.seatNum !=-1">
-				<text class="text-gray">座位号</text>
-				<text class="">{{order.seatNum}}</text>
-			</view>
-			<view class="card text-df" >
-				<text class="text-gray">下单时间</text>
-				<text class="">{{order.createTime}}</text>
-			</view>
-			<view class="card text-df" >
-				<text class="text-gray">下单门店</text>
-				<text class="">{{shop.name}}</text>
-			</view>
-			<view class="card text-df" >
-				<text class="text-gray">付款状态</text>
-				<text class="">{{order.payStatus}}</text>
-			</view>
-			<view class="card text-df" >
-				<text class="text-gray">订单状态</text>
-				<text class="">{{order.orderStatus}}</text>
-			</view>
-			<view class="card text-df" >
-				<text class="text-gray">订单号</text>
-				<text class="">{{order.id}}</text>
-			</view>
-		</view>
-		
-		<view class="">
-			<view class="card text-df" >
-				<text class="text-gray">下单手机号</text>
-				<text class="">{{order.userPhone}}</text>
-			</view>
-			<view class="card text-df" >
-				<text class="text-gray">取餐方式</text>
-				<text class="">{{order.takeType}}</text>
-			</view>
-			<view class="card text-df">
-				<text class="text-gray">取餐时间</text>
-				<text class="">{{order.takeTime || '立即就餐'}}</text>
-			</view>
-		
-		</view>
-		
-		
-		
-	</view>
-</template>
-
-<script>
-export default {
-	name: '',
-	data() {
-		return {
-			id:'',
-			order:{},
-			shop:{},
-			cart:[],
-			//订单流程
-			stepList:[{
-				name:'待付款',
-				icon:'rechargefill'
-			},
-			{
-				name:'已付款',
-				icon:'roundcheckfill'
-			},
-			{
-				name:'制作中',
-				icon:'timefill'
-			},
-			{
-				name:'已完成',
-				icon:'goodsfill'
-			}],
-		};
-	},
-	onLoad(options) {
-		this.id=options.id
-		this.fetchDetail()
-	},
-	computed:{
-		stepIndex:{
-			get(){
-				if (this.order.orderStatus == '待付款') {
-					return 0
-				}else{
-					return 2
-				}
-			}
-		}
-	},
-	methods:{
-		fetchDetail(){
-			let params={
-				id:this.id
-			}
-			this.$api.goodsbills.detail(params).then(res=>{
-				this.order=res.data || {}
-				this.shop=this.order.shop || {}
-				this.cart=JSON.parse(this.order.goodsPreview)
-			})
-		}
-	}
-};
-</script>
-
-<style lang="scss" scoped>
-	.page{
-		margin: 20rpx;
-	}
-	
-	.text-default{
-		color: #ffbf91;
-	}
-	
-	.btn-icon{
-		background-color: rgba(255, 148, 71,.3);
-		color: #FF9447;
-	}
-	
-	
-	.card {
-		padding: 30rpx;
-		background-color: #FFFFFF;
-		border-bottom: 1rpx solid #f1f1f1;
-		display: flex;
-		justify-content: space-between;
-	}
-	
-	.cart {
-		border-bottom: 1rpx solid #f1f1f1;
-		display: flex;
-		background-color: #FFFFFF;
-		padding: 15rpx 0;
-	
-		image {
-			width: 100rpx;
-			height: 100rpx;
-			border-radius: 8rpx;
-		}
-	
-		.item-content {
-			width: calc(100% - 100rpx);
-			margin-left: -40rpx;
-			display: flex;
-			flex-direction: column;
-			justify-content: space-between;
-	
-			text:first-child {
-				font-size: 30rpx;
-			}
-	
-			text:last-child {
-				font-size: 24rpx;
-				color: #999;
-				font-weight: 400;
-			}
-		}
-	
-		.item-data {
-			display: flex;
-			align-items: center;
-			width: 30%;
-			justify-content: space-between;
-			margin-right: 20rpx;
-	
-		}
-	}
-	
-	.cart:last-child {
-		border: none;
-	}
-</style>

+ 0 - 91
pages/order/order.vue

@@ -1,91 +0,0 @@
-<template>
-	<view class="container">
-		<view class="tabs">
-			<scroll-view scroll-x class="bg-white nav">
-				<view class="flex text-center">
-					<view class="cu-item flex-sub" :class="index==current?'text-base cur text-xl text-bold ':'text-lg'"
-						v-for="(item,index) in tabs" :key="index" @tap="tabChange(index)">
-						{{item.name}}
-					</view>
-				</view>
-			</scroll-view>
-		</view>
-		<view style="height: 100%;">
-			<swiper style="height: 100%;" :current="current" @change="swiperChange" @animationfinish="animationfinish">
-				<swiper-item v-for="(item,index) in tabs" :key="index">
-					<scroll-view scroll-y style="height: 100%;">
-						<item :i="index" :item="item" :type="current"></item>
-					</scroll-view>
-				</swiper-item>
-			</swiper>
-		</view>
-	</view>
-</template>
-<script>
-	import item from "./comps/item.vue"
-	export default {
-		components:{
-			item
-		},
-		data() {
-			return {
-				current: 0,
-				swiperCurrent: 0,
-				tabs: [{
-						name: '今日订单',
-						value: 0
-					},
-					{
-						name: '全部订单',
-						value: 1
-					}
-				],
-			}
-		},
-		onLoad() {
-
-		},
-		methods: {
-			tabChange(index) {
-				this.current = index
-			},
-			swiperChange(e) {
-				uni.pageScrollTo({
-					scrollTop: 0,
-					duration: 0
-				});
-				this.current = e.detail.current
-			},
-			animationfinish({
-				detail: {
-					current
-				}
-			}) {
-				this.swiperCurrent = current;
-				this.current = current;
-			},
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
-	.text-xl {
-		font-size: 34rpx;
-	}
-
-	.container {
-		height: calc(100vh);
-		background-color: #F6F6F6;
-		padding: 78rpx 0rpx 0rpx;
-
-		.tabs {
-			position: fixed;
-			top: -10rpx;
-			left: 0;
-			width: 100%;
-			background-color: #FFFFFF;
-			box-sizing: border-box;
-			z-index: 3;
-		}
-	}
-</style>

+ 48 - 41
pages/shop-info/shop-info.vue

@@ -1,7 +1,7 @@
 <template>
 	<view>
 		<u-navbar title="店铺资料" :border-bottom="false"></u-navbar>
-		<block >
+		<view v-show="!loading">
 			<view class="title u-flex u-row-between u-col-center">
 				<text v-if="step==1">请选择商家类型</text>
 				<text v-else>完善商家资料</text>
@@ -12,7 +12,7 @@
 					<u-alert-tips @close="failReason=null" type="error" :close-able="true" :show-icon="true"
 						title="审核意见" :description="failReason"></u-alert-tips>
 				</view>
-				<u-form :model="form" :label-width="labelWidth" ref="uForm">
+				<u-form :model="form" :label-width="labelWidth" ref="uForm" :label-style="labelStyle">
 					<view v-if="step==1" class="steps1" style="padding-bottom: 40rpx;">
 						<view @click="clickType(1)" class="item   u-border-bottom">
 							<view class="flex">
@@ -66,7 +66,8 @@
 						</view>
 						<view class="border">
 							<u-form-item label="商户联系人手机号" prop="personTel" label-width="250">
-								<u-input disabled placeholder="请输入联系方式" v-model="form.personTel" type="number"></u-input>
+								<u-input disabled placeholder="请输入联系方式" v-model="form.personTel" type="number">
+								</u-input>
 							</u-form-item>
 						</view>
 						<view class="border">
@@ -116,7 +117,7 @@
 						</view>
 						<view class="border">
 							<u-form-item label="具体地址" label-position="top" prop="address">
-								<u-input :border="false" placeholder="请详细写到门店编号" v-model="form.address"></u-input>
+								<u-input :border="false" disabled placeholder="请详细写到门店编号" v-model="form.address"></u-input>
 								<view slot="right">
 									<u-button @click="chooseAddress" size="mini">获取地址</u-button>
 								</view>
@@ -124,7 +125,7 @@
 						</view>
 						<view class="border">
 							<view style="padding: 30rpx 0 10rpx;">
-								<text>店铺封面</text>
+								<text :style="{'color':'#6d6d6d'}">店铺封面</text>
 								<text style="font-size: 24rpx;color: #999999;">(请上传店铺封面)</text>
 								<mp-upload-img style="height: 120rpx;" ref="mpUploadCover" @click='uploadShopCover'
 									col="4" :count="1"></mp-upload-img>
@@ -133,7 +134,7 @@
 
 						<view class="border">
 							<view style="padding: 30rpx 0 10rpx;">
-								<text>店铺实况</text>
+								<text :style="{'color':'#6d6d6d'}">店铺实况</text>
 								<text style="font-size: 24rpx;color: #999999;">(请依次上传门头、店内照片)</text>
 								<mp-upload-img ref="mpUploadImg" @click='uploadShopPics' :count="2" col="4">
 								</mp-upload-img>
@@ -183,8 +184,8 @@
 						<view class="photo border">
 							<text>请拿出商户法人有效二代身份证件准备拍摄</text>
 							<view class="box">
-								<ocr-navigator  @onSuccess="idCardSuccess" certificateType="idCard" :opposite="false">
-									<upload-img  :width="520" :height="300" title="上传人像面照片"
+								<ocr-navigator @onSuccess="idCardSuccess" certificateType="idCard" :opposite="false">
+									<upload-img :width="520" :height="300" title="上传人像面照片"
 										:model="auditForm.idCardFront" dataName="idCardFront" :enableImg="true">
 									</upload-img>
 								</ocr-navigator>
@@ -273,7 +274,7 @@
 					提交资料
 				</view>
 			</view>
-		</block>
+		</view>
 
 		<!-- 商场 -->
 		<u-popup border-radius="8" height="60%" mode="bottom" v-model="mallShow">
@@ -312,16 +313,17 @@
 			</scroll-view>
 			<u-empty v-else name="search"></u-empty>
 		</u-popup>
-		<u-select confirm-color="#EF9944" v-model="mallAreaShow" label-name="name" value-name="id" mode="single-column" :list="mallAreaList"
-			@confirm="mallAreaConfirm"></u-select>
+		<u-select confirm-color="#EF9944" v-model="mallAreaShow" label-name="name" value-name="id" mode="single-column"
+			:list="mallAreaList" @confirm="mallAreaConfirm"></u-select>
 		<!-- 地区 -->
 		<!-- <u-picker confirm-color="#EF9944" @confirm="regionConfirm" v-model="regionShow" mode="region"></u-picker> -->
 		<city-select :defaultRegion="defaultRegion" v-model="regionShow" @city-change="regionConfirm"></city-select>
 		<!-- <u-select v-model="bankCodeShow"  :list="bankCodeList" @confirm="bankTypeConfirm"></u-select> -->
-		<u-select confirm-color="#EF9944" v-model="bankAccountTypeShow" :list="bankAccountTypeList" @confirm="bankAccountTypeConfirm">
+		<u-select confirm-color="#EF9944" v-model="bankAccountTypeShow" :list="bankAccountTypeList"
+			@confirm="bankAccountTypeConfirm">
 		</u-select>
 		<toast ref="toast"></toast>
-		<loading ref="loading" type="3"  />
+		<loading ref="loading" type="3" />
 	</view>
 </template>
 
@@ -392,6 +394,8 @@
 		},
 		data() {
 			return {
+				labelStyle:{'color':'#6d6d6d'},
+				
 				loading: true,
 				typeIndex: 1,
 				//银行类型
@@ -745,7 +749,7 @@
 				mallAreaLabel: '',
 				//所在地区
 				regionShow: false,
-				defaultRegion:[],	
+				defaultRegion: [],
 				//门店地址
 				shopAddress: '',
 				step: 1,
@@ -795,6 +799,7 @@
 			uni.hideLoading()
 		},
 		async onLoad(options) {
+			this.$refs.loading.showLoading()
 			this.form.personTel = this.$cache.get('phone')
 			this.auditForm.contactMobile = this.form.personTel
 			//监听从chooseLable页面返回的数据
@@ -822,7 +827,9 @@
 				this.getProcessDefinitionId()
 			}
 			await this.initDict()
-			await this.fetchMallList()
+			await this.fetchMallList(	)
+			this.$refs.loading.hide()
+			this.loading=false
 		},
 		methods: {
 			clickType(index) {
@@ -896,8 +903,8 @@
 			},
 			//所在地区
 			regionConfirm(e) {
-				this.form.location=e.location
-				this.form.locationCode=e.locationCode
+				this.form.location = e.location
+				this.form.locationCode = e.locationCode
 				// this.form.location = e.province.label + "-" + e.city.label + "-" + e.area.label
 				// this.form.locationCode = e.province.value + "0000," + e.city.value + "00," + e.area.value
 			},
@@ -951,7 +958,7 @@
 					})).data.mallName
 				}
 				console.log(this.form.location.split('-'));
-				this.defaultRegion=this.form.location.split('-')
+				this.defaultRegion = this.form.location.split('-')
 				this.imgList = this.$isNotEmpty(this.form.shopPic) ? this.form.shopPic.split(",") : []
 				this.$refs.mpUploadCover.changeImgList([this.form.cover])
 				this.$refs.mpUploadImg.changeImgList(this.imgList)
@@ -1087,30 +1094,30 @@
 					this.auditForm[name] = res.data.link
 				})
 			},
-			idCardSuccess(e){
-				console.log(e,"e********");
-				let data=e.detail
-				console.log(data,"data******");
-				if (data.type==0) {
+			idCardSuccess(e) {
+				console.log(e, "e********");
+				let data = e.detail
+				console.log(data, "data******");
+				if (data.type == 0) {
 					//身份证正面
-					this.auditForm.addr=data.address.text
-					this.auditForm.gender=data.gender.text
-					this.auditForm.idCard=data.id.text
-					this.auditForm.nationality=data.nationality.text
-					this.auditForm.name=data.name.text
+					this.auditForm.addr = data.address.text
+					this.auditForm.gender = data.gender.text
+					this.auditForm.idCard = data.id.text
+					this.auditForm.nationality = data.nationality.text
+					this.auditForm.name = data.name.text
 					this.auditForm.legalPerson = data.name.text
 					this.form.personName = data.name.text
 					this.auditForm.contactLicenceNo = data.id.text
-				}else{
+				} else {
 					this.auditForm.validDate = data.valid_date.text
 				}
-				this.$api.uploadFile(data.image_path).then(res=>{
-					if (data.type==0) {
+				this.$api.uploadFile(data.image_path).then(res => {
+					if (data.type == 0) {
 						//正面
-						this.auditForm.idCardFront=res.data.link
-					}else{
+						this.auditForm.idCardFront = res.data.link
+					} else {
 						//反面
-						this.auditForm.idCardContrary=res.data.link
+						this.auditForm.idCardContrary = res.data.link
 					}
 				})
 			},
@@ -1175,7 +1182,7 @@
 			async fetchMallList() {
 				let params = {
 					name: this.mallKeyWord,
-					auditStatus:'PASS',
+					auditStatus: 'PASS',
 					size: 20
 				}
 				let res = await this.$api.mall.list(params)
@@ -1198,7 +1205,7 @@
 				this.form.mallAreaId = e[0].value
 			},
 			async submit() {
-				let _this=this
+				let _this = this
 
 				if (this.$isEmpty(this.auditForm.idCardFront)) {
 					this.$refs.toast.info('请上传身份证正面照')
@@ -1225,7 +1232,7 @@
 				if (this.$cache.get('promotionCode')) {
 					this.form.agenter = this.$cache.get('promotionCode')
 				}
-				
+
 				this.$refs.loading.showLoading('资料提交中..')
 
 				this.initAuditInfo()
@@ -1237,18 +1244,18 @@
 				}
 				this.$cache.put('shopAuditInfo', params)
 				this.$api.shop.submitAudit(params).then(res => {
-					setTimeout(()=>{
+					setTimeout(() => {
 						if (res.success == true) {
 							_this.$cache.remove('shopAuditInfo')
 							_this.doReSubmit()
 							_this.jump()
 						}
 						_this.$refs.loading.hide()
-					},300)
+					}, 300)
 				}).catch(err => {
-					setTimeout(()=>{
+					setTimeout(() => {
 						_this.$refs.loading.hide()
-					},300)
+					}, 300)
 				})
 			},
 			jump() {

+ 1 - 1
pages/statistics/pointBillStatistics.vue

@@ -40,7 +40,7 @@
 					</view>
 					<view class="area2 text-area" style="width: 15%;">
 						<view class="item-padding">
-							<text>{{item.discount==-1 || item.discount==0?'无折扣':item.discount +'折'}}</text>
+							<text>{{discount(item.discount)}}</text>
 						</view>
 					</view>
 					<view class="area3 text-area u-p-r-20" style="width: 30%;">

+ 4 - 3
pages/statistics/statistics.vue

@@ -52,7 +52,7 @@
 						</view>
 					</view>
 					<view class="area2">
-						<text>{{item.discount==-1 || item.discount==0 || item.discount==1?'无折扣':item.discount +'折'}}</text>
+						<text>{{discount(item.discount)}}</text>
 					</view>
 					<view class="area3">
 						<text class="text-base price" v-if="$isNotEmpty(item.receiveNumTotal)">{{item.receiveNumTotal}}</text>
@@ -105,7 +105,7 @@
 			},
 			async getData() {
 				let params = {
-					queryColumn: 'cost',
+					queryColumn: 'actual_income',
 					queryDate: this.$dateTime.format(new Date(this.defaultTime)),
 					receiveId: this.vuex_shopId
 				}
@@ -229,6 +229,7 @@
 		width: 54%;
 		display: flex;
 		height: 120rpx;
+		padding-left: 30rpx;
 		justify-content: center;
 		align-items: center;
 	
@@ -242,7 +243,7 @@
 		}
 	
 		view {
-			width: calc(100% - $img-width);
+			width: 80%;
 			display: flex;
 			flex-direction: column;
 			justify-content: space-between;

+ 29 - 612
pages/test/test.vue

@@ -1,634 +1,51 @@
 <template>
-	<view class="u-wrap ">
-		<view class="flex bg-white" style="padding: 30rpx 10rpx;">
-			<view class="" style="width: 20%;">
-				<u-button @click="operateCategory(null)" size="mini" type="warning" plain
-					class=" text-sm text-red flex text-bold">
-					<text>添加分类</text>
-					<text class="cuIcon-add u-m-l-4 center"></text>
-				</u-button>
-			</view>
-
-			<view @click="operateGoods(null)" class="center bg-white" style="width: 80%;color: #007AFF;">
-				<text class="cuIcon-roundadd margin-right-10"></text>
-				<text>添加【{{goodsList[current].goodsCategory.name}}】分类下商品</text>
-			</view>
-		</view>
-		<view class="u-menu-wrap">
-			<scroll-view scroll-y scroll-with-animation class="u-tab-view menu-scroll-view" :scroll-top="scrollTop">
-				<view v-for="(item,index) in goodsList" :key="index" class="u-tab-item"
-					:class="[current==index ? 'u-tab-item-active' : '']" :data-current="index"
-					@tap.stop="swichMenu(index)">
-					<view class="">
-						<text class="u-line-1 u-m-r-4" :style="!item.goodsCategory.showStatus?'text-decoration: line-through;color: #bababa':''">{{item.goodsCategory.name}}</text>
-						<u-icon color="#EF9944" @click="operateCategory(item.goodsCategory)" name="edit-pen-fill">
-						</u-icon>
-					</view>
+	<view >
+		<view style="margin-top: 50rpx;" class="center flex-direction">
+			<image
+				style="width: 600rpx;height: 600rpx;"
+				:src="src"
+				mode="widthFix"></image>
+				<view class="center margin-top-50">
+					<text class="text-base">*请保存二维码,然后到微信中扫码关注该公众号</text>
 				</view>
-			</scroll-view>
-			<block v-for="(item,index) in goodsList" :key="index">
-				<scroll-view scroll-y class="right-box" v-if="current==index">
-					<view class="page-view">
-						<view class="class-item">
-							<view class="item-title">
-								<text>{{item.goodsCategory.name}}</text>
-							</view>
-							<view class="item-container">
-								<view class="thumb-box"  v-for="(goods, index1) in item.goods" :key="index1">
-									<image @click="$util.preview(goods.image)" class="item-menu-image"
-										:src="goods.image" mode=""></image>
-									<view class="item-content">
-										<view class="name flex justify-between ">
-											<view class="text-cut-1 " style="width: 75%;">
-												<text>{{goods.name}}</text>
-											</view>
-											<view class="text-red text-sm" @click="operateGoods(goods)">
-												<text>编辑</text>
-												<text class="cuIcon-edit u-m-l-2"></text>
-											</view>
-										</view>
-										<view class="tips">
-											<view class="text-cut-1 " style="width: 75%;">
-												{{ goods.description}}
-											</view>
-											
-											<view class="text-blue text-sm" @click="operateGoods(goods)">
-												<text>规格</text>
-												<text class="cuIcon-goods u-m-l-2"></text>
-											</view>
-										</view>
-										<view class="price_and_action">
-											<text class="price">¥{{ goods.defaultPrice / 100 }}</text>
-											<text v-if="!goods.isSell" class="margin-left-20 text-sm text-red">已下架</text>
-										</view>
-									</view>
-								</view>
-							</view>
-						</view>
-					</view>
-				</scroll-view>
-			</block>
 		</view>
 
-
-		<!-- 分类 -->
-		<u-popup borderRadius="12" v-model="categoryShow" mode="center" width="80%">
-			<view class="center padding-30 flex-direction">
-				<text class="text-center  text-lg" v-text="categoryEdit?'修改分类':'添加分类'"></text>
-				<view class="margin-top-30">
-					<u-form :model="categoryForm" ref="uForm" label-width="140">
-						<u-form-item label="分类名称">
-							<u-input :clearable="false" v-model="categoryForm.name" />
-						</u-form-item>
-						<u-form-item label="显示顺序">
-							<u-number-box v-model="categoryForm.displayOrder" ::min="1" :max="100"></u-number-box>
-						</u-form-item>
-						<u-form-item label="是否显示">
-							<view class="center" style="justify-content: flex-start;">
-								<u-switch active-color="#FF9447" v-model="categoryForm.showStatus" active-value="1"
-									inactive-value="0"></u-switch>
-							</view>
-						</u-form-item>
-					</u-form>
-				</view>
-
-				<view class="center " style="margin-top: 60rpx;width: 100%;justify-content: space-around;">
-					<block v-if="categoryEdit">
-						<view @click="deleteCategory" class="cu-btn  flex  text-lg line-red radius"
-							style="padding: 40rpx 0;width: 46%;">
-							删除
-						</view>
-						<view @click="submitCategory" class="cu-btn  flex  text-lg bg-base radius"
-							style="padding: 40rpx 0;width: 46%;">
-							确认
-						</view>
-					</block>
-					<view v-else @click="submitCategory" class="cu-btn  flex  text-lg bg-base radius"
-						style="padding: 40rpx 0;width: 90%;">
-						确认
-					</view>
-				</view>
-			</view>
-		</u-popup>
-		<!-- 商品 -->
-		<u-popup borderRadius="12" v-model="goodsShow" mode="center" width="90%">
-			<view class="bg-white center  flex-direction" style="padding: 30rpx 20rpx;">
-				<text class="text-center text-bold text-lg" v-text="goodsEdit?'修改商品':'添加商品'"></text>
-				<view class="margin-top-10">
-					<u-form :error-type="['toast']" :model="goodsForm" ref="uGoodsForm" label-width="160">
-						<u-form-item prop="image" :required="true" label="商品图片" label-position="top">
-							<view class="" style="margin-top: -40rpx;margin-bottom: -20rpx;">
-								<mp-upload-img ref="mpUploadImg" @delImg="delGoodsImg" @click='uploadGoodsImg'
-									:count="1" col="3"></mp-upload-img>
-							</view>
-						</u-form-item>
-						<u-form-item :required="true" label="所在分类">
-							<u-input :clearable="false" disabled placeholder-style="color:#d8d8d8"
-								v-model="goodsForm.goodsCategoryName" />
-						</u-form-item>
-						<u-form-item :required="true" label="商品名称" prop="name">
-							<u-input :clearable="false" placeholder-style="color:#d8d8d8" v-model="goodsForm.name" />
-						</u-form-item>
-						<u-form-item  :required="true" label="商品单价">
-							<u-input :clearable="false" placeholder-style="color:#d8d8d8" v-model="price" />
-							<text slot="right">元</text>
-						</u-form-item>
-						<u-form-item label="显示顺序">
-							<u-number-box v-model="goodsForm.displayOrder" ::min="1" :max="100"></u-number-box>
-						</u-form-item>
-						<u-form-item label="是否在卖">
-							<view class="center" style="justify-content: flex-start;">
-								<u-switch active-color="#FF9447" v-model="goodsForm.isSell" active-value="1"
-									inactive-value="0"></u-switch>
-							</view>
-						</u-form-item>
-						<u-form-item label="商品描述">
-							<u-input :clearable="false" placeholder-style="color:#d8d8d8"
-								v-model="goodsForm.description" placeholder="请输入商品描述" />
-						</u-form-item>
-					</u-form>
-				</view>
-
-				<view class="center " style="margin-top: 60rpx;width: 100%;justify-content: space-around;">
-					<block v-if="goodsEdit">
-						<view @click="deleteGoods" class="cu-btn  flex  text-lg line-red radius"
-							style="padding: 40rpx 0;width: 46%;">
-							删除
-						</view>
-						<view @click="submitGoods" class="cu-btn  flex  text-lg bg-base radius"
-							style="padding: 40rpx 0;width: 46%;">
-							确认
-						</view>
-					</block>
-					<view v-else @click="submitGoods" class="cu-btn  flex  text-lg bg-base radius"
-						style="padding: 40rpx 0;width: 90%;">
-						确认
-					</view>
+		<view class="" style="position: fixed;bottom: 150rpx;width: 100%;">
+			<view class="center">
+				<view @click="saveImg" class="cu-btn  flex radius text-lg"
+					style="padding: 46rpx 0;background-color: #EF9944;color: #FFFFFF;width: 90%;">
+					<u-icon name="download"></u-icon>
+					<text class="margin-left-20">保存到相册</text>
 				</view>
 			</view>
-		</u-popup>
-
-		<toast ref="toast"></toast>
+		</view>
 	</view>
 </template>
 
 <script>
-	import mpUploadImg from "@/components/mp-uploadImg/mp-uploadImg.vue"
 	export default {
-		components: {
-			mpUploadImg
-		},
+		name: '',
 		data() {
 			return {
-				goodsList: [],
-
-				//分类
-				operateCategoryItem: {},
-				categoryEdit: false,
-				categoryShow: false,
-				categoryForm: {
-					id: '',
-					shopId: '',
-					name: '',
-					displayOrder: 1,
-					//是否显示
-					showStatus: 1,
-				},
-
-				//商品 begin
-				imgList: [],
-				price: 0,
-				operateGoodsItem: {},
-				goodsEdit: false,
-				goodsShow: false,
-				goodsForm: {
-					id: '',
-					shopId: '',
-					goodsCategoryName: '',
-					name: '',
-					displayOrder: 1,
-					defaultPrice: 0,
-					isSell: 1,
-					image: '',
-					description: null
-				},
-				goodsRules: {
-					image: [{
-						required: true,
-						message: '请上传商品图片',
-						trigger: ['blur', 'change']
-					}],
-					name: [{
-						required: true,
-						message: '请输入商品名称',
-						trigger: ['blur', 'change']
-					}],
-				},
-				//商品 end
-
-				
-				// 菜单
-				scrollTop: 0, //tab标题的滚动条位置
-				current: 0, // 预设当前项的值
-				menuHeight: 0, // 左边菜单的高度
-				menuItemHeight: 0, // 左边菜单item的高度
-			}
+				src:''
+			};
 		},
-		onLoad() {
-			this.getGoodsList()
-		},
-		onReady() {
-			this.$refs.uGoodsForm.setRules(this.goodsRules);
+		onLoad(options) {
+			let src=options.src || 'http://img.yeepay.com/jccpb-wechat-certificate/certificate/qrcode/2021/11/12/16367106615474e8f948b0cec4593842bfc5ce14511e2.png'
+			if (this.$isNotEmpty(src) && src.indexOf('https')<0) {
+				this.src=src.replace('http','https')
+			}
+		
 		},
-		methods: {
-			getGoodsList() {
-				let params = {
-					shopId: this.vuex_shopId
-				}
-				this.$api.goods.list(params).then(res => {
-					this.goodsList = res.data
-				})
-			},
-
-			//分类 begin
-			operateCategory(item) {
-				this.operateCategoryItem = item
-				this.categoryShow = true
-				if (this.$isEmpty(item)) {
-					//添加分类
-					this.reSetCategoryForm()
-					this.categoryEdit = false
-					return
-				}
-				//修改分类
-				this.categoryEdit = true
-				this.$util.objectCopy(this.categoryForm, item)
-			},
-			async submitCategory() {
-				if (this.$isEmpty(this.categoryForm.name)) {
-					this.$u.toast('请输入类目名称!')
-					return
-				}
-				
-				if (!this.categoryEdit) {
-					let flag = this.goodsList.some(item => item.goodsCategory.name == this.categoryForm.name)
-					if (flag) {
-						this.$u.toast('已有该名称的类目!')
-						return
-					}
-				}
-				
-				this.categoryForm.shopId = this.vuex_shopId
-				let res = await this.$api.goodsCategory.submit(this.categoryForm)
-				if (res.success) {
-					this.$u.toast('操作成功')
-					this.getGoodsList()
-					this.categoryShow = false
-				}
-			},
-			deleteCategory() {
-				this.$dialog.showModal('确定删除该分类?').then(() => {
-					this.$api.goodsCategory.remove(this.operateCategoryItem.id).then(res => {
-						if (res.success) {
-							this.$u.toast('删除成功')
-							this.current = 0
-							this.categoryShow = false
-							this.getGoodsList()
-						}
-					})
-				})
-			},
-			reSetCategoryForm(){
-				this.categoryForm={
-					id: '',
-					shopId: '',
-					name: '',
-					displayOrder: 1,
-					//是否显示
-					showStatus: 1,
-				}
-			},
-			//分类 end
-
-			//商品begin
-			uploadGoodsImg(e){
-				this.goodsForm.image=e[0]
-			},
-			operateGoods(item) {
-				this.goodsForm.goodsCategoryName = this.goodsList[this.current].goodsCategory.name
-				this.operateGoodsItem = item
-				this.goodsShow = true
-				if (this.$isEmpty(item)) {
-					//添加商品
-					this.reSetGoodsData()
-					this.goodsEdit = false
-					return
-				}
-				//修改商品
-				this.price = item.defaultPrice / 100
-				this.imgList = [item.image]
-				this.$refs.mpUploadImg.changeImgList(this.imgList)
-				
-				this.goodsEdit = true
-				this.$util.objectCopy(this.goodsForm, item)
-			},
-			delGoodsImg(item) {
-				this.imgList = item[0]
-				this.goodsForm.image=this.imgList
-			},
-			reSetGoodsData(){
-				this.price=0
-				this.imgList=[]
-				this.$refs.mpUploadImg.changeImgList(this.imgList)
-				let goodsCategoryName=this.goodsForm.goodsCategoryName
-				this.goodsForm={
-					id: '',
-					shopId: '',
-					goodsCategoryName,
-					name: '',
-					displayOrder: 1,
-					defaultPrice: 0,
-					isSell: 1,
-					image: '',
-					description: null
-				}
-			},
-			submitGoods() {
-				this.$refs.uGoodsForm.validate(valid => {
-					if (valid) {
-						this.goodsForm.defaultPrice=this.price * 100
-						if (this.$isEmpty(this.goodsForm.defaultPrice)) {
-							this.$u.toast('请输入商品单价')
-							return
-						}
-						this.doSubmitGoods()
-						
-					} else {
-						console.log('验证失败');
-					}
-				});
-			},
-			async doSubmitGoods(){
-				this.goodsForm.shopId = this.vuex_shopId
-				let res = await this.$api.goods.submit(this.goodsForm)
-				if (res.success) {
-					this.$u.toast('操作成功')
-					this.getGoodsList()
-					this.goodsShow = false
-				}
-			},
-			deleteGoods() {
-				this.$dialog.showModal('确定删除该商品?').then(() => {
-					this.$api.goods.remove(this.operateGoodsItem.id).then(res => {
-						if (res.success) {
-							this.$u.toast('删除成功')
-							this.goodsShow = false
-							this.getGoodsList()
-						}
-					})
-				})
-			},
-			//商品end
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-			//菜单 begin
-			// 点击左边的栏目切换
-			async swichMenu(index) {
-				if (index == this.current) return;
-				this.current = index;
-				// 如果为0,意味着尚未初始化
-				if (this.menuHeight == 0 || this.menuItemHeight == 0) {
-					await this.getElRect('menu-scroll-view', 'menuHeight');
-					await this.getElRect('u-tab-item', 'menuItemHeight');
-				}
-				// 将菜单菜单活动item垂直居中
-				this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
-			},
-			// 获取一个目标元素的高度
-			getElRect(elClass, dataVal) {
-				new Promise((resolve, reject) => {
-					const query = uni.createSelectorQuery().in(this);
-					query.select('.' + elClass).fields({
-						size: true
-					}, res => {
-						// 如果节点尚未生成,res值为null,循环调用执行
-						if (!res) {
-							setTimeout(() => {
-								this.getElRect(elClass);
-							}, 10);
-							return;
-						}
-						this[dataVal] = res.height;
-					}).exec();
-				})
+		methods:{
+			async saveImg(){
+				let res=await this.$mpi.downloadFile(this.src)
+				this.$mpi.saveImg(res)
 			}
-			// 菜单end
 		}
-	}
+	};
 </script>
 
 <style lang="scss" scoped>
-	.u-wrap {
-		height: calc(100vh);
-		/* #ifdef H5 */
-		height: calc(100vh - var(--window-top));
-		/* #endif */
-		display: flex;
-		flex-direction: column;
-	}
-
-	.u-menu-wrap {
-		flex: 1;
-		display: flex;
-		overflow: hidden;
-	}
-
-	.u-tab-view {
-		width: 200rpx;
-		height: 100%;
-	}
-
-	.u-tab-item {
-		height: 110rpx;
-		background: #f6f6f6;
-		box-sizing: border-box;
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		font-size: 26rpx;
-		color: #444;
-		font-weight: 400;
-		line-height: 1;
-	}
-
-	.u-tab-item-active {
-		position: relative;
-		color: #000;
-		font-size: 30rpx;
-		font-weight: 600;
-		background: #fff;
-	}
-
-	.u-tab-item-active::before {
-		content: "";
-		position: absolute;
-		border-left: 4px solid $u-type-primary;
-		height: 32rpx;
-		left: 0;
-		top: 39rpx;
-	}
-
-	.u-tab-view {
-		height: 100%;
-	}
-
-	.right-box {
-		background-color: rgb(250, 250, 250);
-	}
-
-	.page-view {
-		padding: 16rpx;
-	}
-
-	.class-item {
-		margin-bottom: 30rpx;
-		background-color: #fff;
-		padding: 16rpx;
-		border-radius: 8rpx;
-	}
-
-	.item-title {
-		font-size: 26rpx;
-		color: $u-main-color;
-		font-weight: bold;
-	}
-
-	.item-container {
-		display: flex;
-		flex-wrap: wrap;
-
-		.thumb-box {
-			width: 100%;
-			display: flex;
-			padding: 20rpx 0;
-			border-bottom: 1rpx solid #EEEEEE;
-
-			.item-menu-image {
-				width: 160rpx;
-				height: 160rpx;
-				margin-right: 20rpx;
-				border-radius: 8rpx;
-			}
-
-			.item-content {
-				width: calc(100% - 180rpx);
-			}
-
-
-			.name {
-				font-size: $font-size-base;
-				margin-bottom: 10rpx;
-			}
-
-			.tips {
-				width: 100%;
-				height: 40rpx;
-				display: flex;
-				justify-content: space-between;
-				line-height: 40rpx;
-				white-space: nowrap;
-				font-size: $font-size-sm;
-				color: $text-color-assist;
-				margin-bottom: 10rpx;
-			}
-
-			.price_and_action {
-				width: 100%;
-				display: flex;
-				align-items: center;
-				margin-top: 30rpx;
-
-				.price {
-					font-size: $font-size-base;
-					font-weight: 600;
-				}
 
-				.btn-group {
-					display: flex;
-					justify-content: space-between;
-					align-items: center;
-					position: relative;
-
-					.btn {
-						background-color: $base-color;
-						padding: 0 20rpx;
-						box-sizing: border-box;
-						font-size: $font-size-sm;
-						height: 44rpx;
-						line-height: 44rpx;
-
-						&.property_btn {
-							border-radius: 24rpx;
-						}
-
-						&.add_btn,
-						&.reduce_btn {
-							color: #FFFFFF;
-							border: $base-color;
-							padding: 0;
-							width: 44rpx;
-							border-radius: 44rpx;
-						}
-					}
-
-					.dot {
-						position: absolute;
-						background-color: #ffffff;
-						border: 1px solid $color-primary;
-						color: $color-primary;
-						font-size: $font-size-sm;
-						width: 36rpx;
-						height: 36rpx;
-						line-height: 36rpx;
-						text-align: center;
-						border-radius: 100%;
-						right: -12rpx;
-						top: -10rpx;
-					}
-
-					.number {
-						width: 44rpx;
-						height: 44rpx;
-						line-height: 44rpx;
-						text-align: center;
-					}
-				}
-			}
-		}
-
-		.thumb-box:last-child {
-			border: none;
-		}
-	}
 </style>

+ 1 - 0
pagesGoods/assert/js/tarbar.js

@@ -4,6 +4,7 @@ export  const tabbar = {
 		bgColor:"#ffffff",
 		midButton:true,
 		iconSize:44,
+		height:108,
 		MinButtonSize:70,
 		borderTop:true,
 		list:[{

+ 4 - 4
pagesGoods/pages/menu/menu.vue

@@ -81,7 +81,7 @@
 
 
 		<!-- 分类 -->
-		<u-popup borderRadius="12" v-model="categoryShow" mode="center" width="80%">
+		<u-popup borderRadius="12" v-model="categoryShow" mode="center" width="80%" :closeable="true">
 			<view class="center padding-30 flex-direction">
 				<text class="text-center  text-lg" v-text="categoryEdit?'修改分类':'添加分类'"></text>
 				<view class="margin-top-30">
@@ -119,7 +119,7 @@
 			</view>
 		</u-popup>
 		<!-- 商品 -->
-		<u-popup borderRadius="12" v-model="goodsShow" mode="center" width="90%">
+		<u-popup borderRadius="12" v-model="goodsShow" mode="center" width="90%" :closeable="true" close-icon-pos="top-left">
 			<view class="bg-white center  flex-direction" style="padding: 30rpx 20rpx;">
 				<text class="text-center text-bold text-lg" v-text="goodsEdit?'修改商品':'添加商品'"></text>
 				<view class="margin-top-10">
@@ -130,7 +130,7 @@
 									:count="1" col="3"></mp-upload-img>
 							</view>
 						</u-form-item>
-						<u-form-item :required="true" label="所分类">
+						<u-form-item :required="true" label="所分类">
 							<u-input :clearable="false" disabled placeholder-style="color:#d8d8d8"
 								v-model="goodsForm.goodsCategoryName" />
 						</u-form-item>
@@ -178,7 +178,7 @@
 
 		<toast ref="toast"></toast>
 
-		<u-tabbar @change="tabChange" v-model="tabbarCurr" :icon-size="tabbar.iconSize"
+		<u-tabbar :height="tabbar.height" @change="tabChange" v-model="tabbarCurr" :icon-size="tabbar.iconSize"
 			:active-color="tabbar.activeColor" :mid-button-size="tabbar.MinButtonSize" :list="tabbar.list">
 		</u-tabbar>
 	</view>

+ 2 - 2
pagesGoods/pages/my-shop/my-shop.vue

@@ -21,7 +21,7 @@
 			</view>
 		</view>
 		
-		<u-tabbar @change="tabChange" v-model="tabbarCurr" :icon-size="tabbar.iconSize"
+		<u-tabbar :height="tabbar.height" @change="tabChange" v-model="tabbarCurr" :icon-size="tabbar.iconSize"
 			:active-color="tabbar.activeColor" :mid-button-size="tabbar.MinButtonSize" :list="tabbar.list">
 		</u-tabbar>
 	</view>
@@ -44,7 +44,7 @@
 					{
 						icon: 'download',
 						name: '点餐码下载',
-						path: '/pages/material-download/material-download?type=order'
+						path: '/pagesPoster/pages/material-download?type=order'
 					},
 					{
 						icon: 'kefu-ermai',

+ 168 - 42
pagesGoods/pages/order/comps/card.vue

@@ -1,31 +1,45 @@
 <template>
-	<view>
-		<view @click="$jump('/pages/order/detail?id='+item.id)" class="card" v-for="(item,index) in list" :key="index">
-			<view class="center">
-				<image
-					src="https://guosen-bucket-ldt.obs.cn-south-1.myhuaweicloud.com:443/b15e8992179b4b30b9bdb943d8ad9c07-uWGk0l5GutNQ3013850822b2cdb5f77a445ce68ab57e.jpeg"
-					mode="aspectFill"></image>
-			</view>
-			<view class="content">
-				<view class="flex justify-between">
-					<text class="text-bold text-lg">杨国福麻辣烫</text>
-					<view class="">
-						<text v-if="item.payStatus=='付款成功'" class="text-base">{{item.orderStatus}}</text>
-						<text v-else class="text-base">{{item.payStatus}}</text>
+	<view class="">
+		<view class="page-box">
+			<view @click="jumpDetail(res)" class="order" v-for="(res, index) in list" :key="res.id">
+				<view class="top center">
+					<view class="left ">
+						<text class="">{{res.takeType}}</text>
+						<text v-if="res.takeType=='店内堂食'" class="text-bold text-lg" style="margin: 0rpx 10rpx;">#{{res.seatNum || 0}}</text>
+						<text v-else class="text-bold text-lg" style="margin: 0rpx 10rpx;">#{{res.verifyNum}}</text>
 					</view>
+					<view class="right">{{res.orderStatus}}</view>
 				</view>
-				
-				<view style="font-size: 26rpx;color: #888888;">
-					<view class="margin-bottom-10">
-						<text>{{item.id}}</text>
-						<text @click.stop="$util.copy(item.id)" class="margin-left-10 text-black">复制</text>
+				<view v-if="index<=1" class="item" style="width: 100%;" v-for="(item, index) in cart(res.goodsPreview)" :key="index">
+					<view style="display: flex;">
+						<view class="left">
+							<image :src="item.image" mode="aspectFill"></image>
+						</view>
+						<view class="content">
+							<view class="title u-line-2">{{ item.name }}</view>
+							<view class="type">{{ item.description }}</view>
+						</view>
 					</view>
-					<view class="flex justify-between ">
-						<text class="center">{{item.createTime}}</text>
-						<text class="">消费:{{item.totalPrice / 100}}元</text>
+					<view class="right flex" >
+						<view class="price center">
+							¥{{item.realPrice / 100}}
+						</view>
+						<view class="number center ">x{{ item.number }}</view>
 					</view>
 				</view>
-
+				<view class="center text-gray" v-if="cart(res.goodsPreview).length>2">
+					<text class="cuIcon-more" style="font-size: 36rpx;"></text>
+				</view>
+				
+				<view class="total">
+					共{{res.goodsTotalNum}}件商品 合计:
+					<text class="total-price">
+						¥{{ res.totalPrice / 100}}
+					</text>
+				</view>
+				<view  class="bottom" v-if="res.orderStatus == '制作中'">
+					<view @click="confirm(res.id)" class="evaluate btn">确认订单</view>
+				</view>
 			</view>
 		</view>
 	</view>
@@ -38,34 +52,146 @@
 		},
 		data() {
 			return {
-
+				
+			};
+		},
+		computed:{
+			cart(){
+				return data=>{
+					return JSON.parse(data)
+				}
 			}
 		},
-		methods: {
-
+		methods:{
+			confirm(id){
+				this.$emit('confirm',id)
+			},
+			jumpDetail(res){
+				uni.navigateTo({
+					url:"/pagesGoods/pages/order/detail?id="+res.id,
+					fail(error) {
+						console.log(error);
+					}
+				})
+				
+			}
 		}
-	}
+	};
 </script>
 
-<style lang="scss">
-	.card {
-		margin: 10rpx;
-		background-color: #FFFFFF;
-		display: flex;
-		padding: 18rpx;
-
-		image {
-			width: 150rpx;
-			height: 150rpx;
-			border-radius: 8rpx;
+<style lang="scss" scoped>
+	.order {
+		width: 720rpx;
+		background-color: #ffffff;
+		margin: 15rpx auto;
+		border-radius: 20rpx;
+		box-sizing: border-box;
+		padding: 20rpx;
+		font-size: 28rpx;
+
+		.top {
+			display: flex;
+			justify-content: space-between;
+
+			.left {
+				display: flex;
+				align-items: center;
+
+				.store {
+					margin: 0 10rpx;
+					font-size: 32rpx;
+					font-weight: bold;
+				}
+			}
+
+			.right {
+				color: $u-type-warning-dark;
+			}
 		}
 
-		.content {
-			width: calc(100% - 140rpx - 20rpx - 20rpx);
-			margin-left: 20rpx;
+		.item {
 			display: flex;
-			flex-direction: column;
 			justify-content: space-between;
+			margin: 20rpx 0 0;
+
+			.left {
+				margin-right: 20rpx;
+
+				image {
+					width: 90rpx;
+					height: 90rpx;
+					border-radius: 10rpx;
+				}
+			}
+
+			.content {
+				.title {
+					font-size: 28rpx;
+					line-height: 50rpx;
+				}
+
+				.type {
+					margin: 10rpx 0;
+					font-size: 24rpx;
+					color: $u-tips-color;
+				}
+
+				.delivery-time {
+					color: #e5d001;
+					font-size: 24rpx;
+				}
+			}
+
+			.right {
+				margin-right: 20rpx;
+				margin-left: 10rpx;
+				padding-top: 20rpx;
+				text-align: right;
+
+				.decimal {
+					font-size: 24rpx;
+					margin-top: 4rpx;
+				}
+
+				.number {
+					color: $u-tips-color;
+					font-size: 24rpx;
+					margin-left: 15rpx;
+				}
+			}
+		}
+
+		.total {
+			margin-top: 20rpx;
+			text-align: right;
+			font-size: 24rpx;
+
+			.total-price {
+				font-size: 32rpx;
+			}
+		}
+
+		.bottom {
+			display: flex;
+			margin-top: 40rpx;
+			justify-content: flex-end;
+			align-items: center;
+
+			.btn {
+				line-height: 48rpx;
+				width: 140rpx;
+				border-radius: 26rpx;
+				border: 2rpx solid $u-border-color;
+				font-size: 24rpx;
+				text-align: center;
+				color: $u-type-info-dark;
+			}
+
+			.evaluate {
+				background-color: $u-type-warning-dark;
+				color: #FFFFFF;
+				border-color: $u-type-warning-dark;
+			}
 		}
 	}
-</style>
+</style>

+ 24 - 4
pagesGoods/pages/order/comps/item.vue

@@ -1,8 +1,9 @@
 <template>
 	<view style="margin-top: 4rpx;">
 		<MeScroll  :up="up" :down="down" @up="upFn" :fixed="false" @down="downFn" @init="initMeScroll">
-			<card :list="list" ></card>
+			<card :list="list" @confirm="confirm"></card>
 		</MeScroll>
+		<toast ref="toast" ></toast>
 	</view>
 	
 </template>
@@ -20,6 +21,8 @@
 		},
 		data() {
 			return {
+				searchParams:{},
+				
 				isInit: false, // 是否初始化
 				list: [], // 列表数据
 				mescroll: null, // mescroll 对象
@@ -55,6 +58,22 @@
 			}
 		},
 		methods: {
+			search(params){
+				this.searchParams=params
+				this.mescroll.resetUpScroll()
+			},
+			confirm(id){
+				let params={
+					id,
+					orderStatus:'已完成'
+				}
+				this.$api.goodsbills.submit(params).then(res=>{
+					if (res.success) {
+						this.$refs.toast.info('操作成功')
+						this.mescroll.resetUpScroll()
+					}
+				})
+			},
 			//初始化组件
 			initMeScroll(mescroll) {
 				this.mescroll = mescroll
@@ -64,10 +83,11 @@
 				let params={
 					receiveId:this.vuex_shopId,
 					current:mescroll.num,
-					size:mescroll.size
+					size:mescroll.size,
+					goodsStatus:this.item.value
 				}
-				if (this.item.value==0) {
-					params.createTime=this.$dateTime.format()
+				if (this.$isNotEmpty(this.searchParams)) {
+					Object.assign(params,this.searchParams)
 				}
 				try{
 					this.$api.goodsbills.list(params).then(res=>{

+ 76 - 12
pagesGoods/pages/order/order.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="container">
+	<view class="container" :style="containerStyle">
 		<view class="tabs">
 			<u-navbar :is-back="false" title="订单中心"></u-navbar>
 			<scroll-view scroll-x class="bg-white nav">
@@ -7,6 +7,7 @@
 					<view class="cu-item flex-sub" :class="index==current?'text-base cur text-xl text-bold ':'text-lg'"
 						v-for="(item,index) in tabs" :key="index" @tap="tabChange(index)">
 						{{item.name}}
+						<text class="cuIcon-filter" v-if="index==current&& !$util.objectKeyIsEmpty (form)"></text>
 					</view>
 				</view>
 			</scroll-view>
@@ -15,16 +16,40 @@
 			<swiper style="height: 100%;" :current="current" @change="swiperChange" @animationfinish="animationfinish">
 				<swiper-item v-for="(item,index) in tabs" :key="index">
 					<scroll-view scroll-y style="height: 100%;">
-						<item :i="index" :item="item" :type="current"></item>
+						<item ref="mescrollItem" :i="index" :item="item" :type="current"></item>
 					</scroll-view>
 				</swiper-item>
 			</swiper>
+			<view class="u-tabbar">
+				<u-tabbar :height="tabbar.height" @change="tabbarChange" v-model="tabbarCurr"
+					:icon-size="tabbar.iconSize" :active-color="tabbar.activeColor"
+					:mid-button-size="tabbar.MinButtonSize" :list="tabbar.list" :mid-button="false">
+				</u-tabbar>
+			</view>
 		</view>
 
-		<u-tabbar @change="tabbarChange" v-model="tabbarCurr" :icon-size="tabbar.iconSize"
-			:active-color="tabbar.activeColor" :mid-button-size="tabbar.MinButtonSize" :list="tabbar.list"
-			:mid-button="true">
-		</u-tabbar>
+		<u-popup v-model="searchShow" mode="bottom" :closeable="true">
+			<view class="padding-30">
+				<u-form :model="form" ref="uForm" label-width="170">
+					<u-form-item label="取货号码">
+						<u-input v-model="form.verifyNum" />
+					</u-form-item>
+					<u-form-item label="下单日期">
+						<u-input disabled type="select" :select-open="timeShow" v-model="form.orderDate"
+							@click="timeShow=true" />
+					</u-form-item>
+				</u-form>
+				<view class="center margin-50" >
+					<view @click="reset" class="cu-btn radius line-gray" style="width: 45%;height: 70rpx;margin-right: 20rpx;">
+						重置
+					</view>
+					<view @click="search" class="cu-btn radius bg-base" style="width: 45%;height: 70rpx;margin-left: 20rpx;">
+						搜索
+					</view>
+				</view>
+			</view>
+		</u-popup>
+		<u-picker mode="time" v-model="timeShow" :params="timeParams" @confirm="confirm" confirm-color="#EF9944"></u-picker>
 	</view>
 </template>
 <script>
@@ -38,6 +63,22 @@
 		},
 		data() {
 			return {
+				containerStyle: '',
+
+				timeParams: {
+					year: true,
+					month: true,
+					day: true,
+					hour: false,
+					minute: false,
+					second: false
+				},
+				timeShow: false,
+				searchShow: false,
+				form:{
+					verifyNum:'',
+					orderDate:''
+				},
 				//tabbar
 				tabbarCurr: 2,
 				tabbar: tabbar,
@@ -45,25 +86,48 @@
 				current: 0,
 				swiperCurrent: 0,
 				tabs: [{
-						name: '今日订单',
-						value: 0
+						name: '待确认',
+						value: '制作中'
 					},
 					{
-						name: '全部订单',
-						value: 1
+						name: '已完成',
+						value: '已完成'
 					}
 				],
 			}
 		},
 		onLoad() {
 
+		},
+		onReady() {
+			this.getElInfo()
 		},
 		methods: {
+			search(){
+				this.$refs.mescrollItem[this.current].search(this.form)
+				this.searchShow=false
+			},
+			confirm(e){
+				this.form.orderDate=e.year+'-'+e.month +'-'+ e.day
+			},
+			reset(){
+				this.form={
+					verifyNum:'',
+					orderDate:''
+				}
+				this.search()
+			},
+			async getElInfo() {
+				let rectInfo = await this.$u.getRect('.u-tabbar');
+				this.containerStyle = `height: calc(100vh - ${rectInfo.height}px)`
+			},
 			tabbarChange(index) {
 				if (index == 0) {
 					uni.redirectTo({
 						url: "/pagesGoods/pages/menu/menu"
 					})
+				} else if (index == 1) {
+					this.searchShow = !this.searchShow
 				} else if (index == 2) {
 					uni.redirectTo({
 						url: "/pagesGoods/pages/my-shop/my-shop"
@@ -98,9 +162,9 @@
 	}
 
 	.container {
-		height: calc(100vh);
+		height: calc(100vh - 180rpx);
 		background-color: #F6F6F6;
-		padding: 78rpx 0rpx 0rpx;
+		padding: 242rpx 0rpx 0rpx;
 
 		.tabs {
 			position: fixed;

+ 0 - 0
pages/material-download/comps/modal-checked.vue → pagesPoster/comps/modal-checked.vue


+ 0 - 0
pages/material-download/comps/mp-swiper.vue → pagesPoster/comps/mp-swiper.vue


+ 235 - 0
pagesPoster/comps/u-draw-poster/README.md

@@ -0,0 +1,235 @@
+# 绘制海报工具简述
+
+- 创建绘制海报`canvas`矩形方法,内置了图片绘制,圆角矩形绘制,换行字体绘制等方法。
+- 接近原生开发体验,上手快,只需考虑业务逻辑,而不用考虑其他问题。
+- 拥有良好的语法架构,不会在绘制`uni/wx`矩形时陷入回调地狱。
+- 支持原生小程序,与`uniapp`多端应用。当是环境为原生小程序时,自动切换为性能更好的`type2d`绘制方式。
+- 将复杂的逻辑组合为简单的方法,扩展性强,可使用 `use|useCtx` 引入扩展。
+- 支持`typescript`,支持`vue3`模板,具体使用参考 [useDrawPoster](https://github.com/TuiMao233/u-draw-poster/tree/master/docs/use.md)。
+- 更加强大的图片绘制与裁剪方法(object-fit)
+- 支持声明式绘制扩展,自定义海报必备 具体使用参考 [draw-painter](http://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poster/07-draw-painter.html)
+
+api文档:[u-draw-poster](http://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poster/01-base-desc.html)
+
+插件市场:[dcloud/u-draw-poster](https://ext.dcloud.net.cn/plugin?id=3237)
+
+**npm 安装插件**
+
+~~~
+npm i --save-dev u-draw-poster
+~~~
+
+## 1. 创建海报绘制工具
+
+~~~html
+<!-- #ifdef MP-WEIXIN -->
+<canvas id="canvas" type="2d" style="width:100px; height:100px" />
+<!-- #endif -->
+<!-- #ifndef MP-WEIXIN -->
+<canvas canvas-id="canvas" id="canvas" style="width:100px; height:100px" />
+<!-- #endif -->
+~~~
+
+~~~js
+// 注意:如果使用HBuilder引入, 需要引入 '@/js_sdk/u-draw-poster'
+import DrawPoster from 'u-draw-poster'
+async onReady() {
+ // 传入选择器, 初始化绘制工具(注意, 不需要传入#符号) 当微信小程序时, 将自动启用type2d绘制
+ const dp = await DrawPoster.build("canvas")   
+}
+~~~
+
+## 2. 设置画布尺寸
+~~~js
+// 设置长高为100px的矩形宽高
+dp.canvas.width = 100
+dp.canvas.height = 100
+~~~
+
+## 3. 绘制任意内容
+~~~js
+// 绘制背景与文字
+dp.draw((ctx) => {
+    ctx.fillStyle = "#F4F4F4";
+    ctx.fillRect(0, 0, dp.canvas.width, dp.canvas.height);
+    ctx.textBaseline = "top";
+    ctx.textAlign = "start";
+    ctx.fillStyle = "white";
+    ctx.font = `bold ${22}px sans-serif`;
+    ctx.fillText('周先生', dp.canvas.width/2, 38.5);
+})
+// 绘制图片内容
+dp.draw(async (ctx) => {
+    //.......
+})
+~~~
+值得注意的是, `draw`方法会自动的执行`ctx.save/ctx.restore`, 不需要人为操纵绘画栈.
+~~~js
+dp.draw((ctx) => {/* ... */})
+// 相当于
+ctx.save()
+/* ... */
+ctx.restore()
+~~~
+
+## 4. 进行绘制
+
+`dp.draw`并不会马上绘制,只是将该任务添加到了任务栈,需要使用`dp.awaitCreate`函数进行绘制,该函数在绘制完毕后将弹出所有任务。
+`dp.awaitCreate`在非`2d`绘画中,执行绘画任务完毕后,将自动执行`ctx.draw`方法,并在draw绘画才算异步结束。
+
+~~~js
+dp.draw((ctx) => {/* ... */})
+dp.draw(async (ctx) => {/* ... */})
+// 由于每个任务都有可能会有异步的绘制任务, 所以得需要使用await等待绘制
+const result = await dp.awaitCreate();
+// 绘制成功将返回每个任务的绘制状况组成的数组
+console.log("draw绘制状况:", result); // draw绘制状况: [true]
+~~~
+
+[^为什么这么做]: 当全部同步绘制时,将会出现绘制时间保持不一致的情况。这样就会导致一个问题,绘制图层覆盖导致显示未达到预期效果,之所以设计为异步等待,也是为了绘制图层能保持一致顺序。
+
+## 5. 生成图片本地地址
+
+如需要保存为图片时,可以使用`dp.createImgUrl` 进行创建图片本地地址,在由`wx`或`uni`的`api`进行保存。
+~~~js
+dp.draw(async (ctx) => {/* ... */})
+const result = await dp.awaitCreate();
+const posterImgUrl = await dp.createImagePath();
+console.log("draw绘制状况:", result); // [true]
+console.log("绘制生成本地地址:", posterImgUrl); // ...tmp...
+~~~
+你也可以不使用`dp.awaitCreate`方法,当调用`dp.createImagePath`时会自动检测任务列表,如果有则执行绘制任务后在创建地址。
+
+~~~js
+dp.draw(async (ctx) => {/* ... */})
+// 跳过drawPoster.awaitCreate直接生成地址
+const posterImgUrl = await dp.createImagePath();
+console.log("绘制生成本地地址:", posterImgUrl);
+~~~
+
+# 绘制扩展 API
+
+DrawPoster 在创建时,会自动的向`ctx(画笔)`添加/覆盖扩展方法,以便构建海报矩形。
+
+目前支持绘制图片、圆角图片、绘制裁剪图片(object-fit)、换行字体、圆角矩形、圆角矩形边框、绘制二维码。
+
+~~~js
+dp.draw(async (ctx) => {
+  // ctx.drawImage | ctx.drawRoundImage | ctx.fillWarpText | ....
+})
+~~~
+
+具体查看API文档:[u-draw-poster](http://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poster/02-draw-extends.html)
+
+
+# 全局实例 API
+
+DrawPoster 的静态与扩展方法,除了最常用的:绘制节点、绘画构建、创建绘制、创建图片,以及还有另外的扩展功能:绘画构建、挂载全局扩展、挂载绘制扩展、全局画笔、等待绘制、停止绘画。
+
+具体查看API文档:[u-draw-poster](http://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poster/03-gbl-example.html)
+
+# 使用建议
+
+## canvas 当做为生成工具
+
+canvas在海报生成中请当做一个生成工具来看待,它的作用仅是绘制出海报。应把生成得到的资源保存并使用,显示用image图片组件,原因是方便操作,例如调整大小,或是H5端长按保存或识别,所以canvas应将它放在看不见的地方。不能用display:none;overflow:hidden;隐藏,否则生成空白。这里推荐canvas的隐藏样式代码,该说明为 [uQRCode](https://github.com/Sansnn/uQRCode) 提供的说明,同样`u-draw-poster`也适用
+
+~~~css
+.canvas-hide {
+	/* 1 */
+	position: fixed;
+	right: 100vw;
+	bottom: 100vh;
+	/* 2 */
+	z-index: -9999;
+	/* 3 */
+	opacity: 0;
+}
+~~~
+
+## 支持重复调用
+需要注意的是,创建绘制工具支持重复调用,当构建第一次的绘制工具后,重复构建将自动获取第一次的实例。不需要存入`this`中,其实`vue3`也不提倡使用`this`这个黑盒,甚至抛弃了使用`this`。
+~~~js
+data: () => ({}),
+// 不存入实例(推荐)
+method: {
+  async draw() {
+    const dp = await DrawPoster.build("canvas")
+    //...
+  }
+},
+onReady() {
+ this.draw()
+ // 重复调用....
+ this.draw()
+}
+~~~
+~~~js
+// 存入实例(不推荐)
+data: () => ({
+  dp: null
+}),
+method: {
+  async draw() {
+    if (!this.dp) {
+      const dp = await DrawPoster.build("canvas")
+      this.dp = dp
+    }
+    //...
+  }
+},
+onReady() {
+ this.draw()
+ // 重复调用....
+ this.draw()
+}
+~~~
+
+# 常见问题
+
+## 微信小程序手机浏览空白
+
+微信小程序绘制如果有图片绘制,手机浏览需要在后台添加`downloadFile`域名,并需要重启开发者工具。
+
+## 微信小程序无法真机调试
+
+https://developers.weixin.qq.com/community/develop/doc/000eece1640d608df21bb19055b000
+
+## 绘制完毕后没有效果
+
+注意`DrawPoster.build`无法检测你所选择`canvasId`的是否正确,所以一定要确保与`canvas-id`和`html`中的`canvas`相同,在小程序端,由于会自动切换为`type2d`,必须得加上动态编译。
+
+~~~html
+<!-- #ifdef MP-WEIXIN -->
+<canvas id="canvas" type="2d" style="width: 300px; height: 300px" />
+<!-- #endif -->
+<!-- #ifndef MP-WEIXIN -->
+<canvas canvas-id="canvas" id="canvas" style="width: 300px; height: 300px" />
+<!-- #endif -->
+~~~
+
+## 绘制多个图片加载慢
+
+如果觉得多个图片绘制`await`加载慢,可以使用`Promise.all`将一部分不需要处理图层覆盖的图片进行同步绘制。
+
+~~~js
+dp.draw(async (ctx) => {
+  // // 用户头像
+  await ctx.drawRoundImage(headImgUrl, 39, 790, 90, 90, 100);
+  await Promise.all([
+    ctx.drawImage('/static/logo1.png', 20, 20, 35, 35),
+    ctx.drawImage('/static/tp.png', 19, 86, 612, 459),
+    ctx.drawImage('/static/bw.png', 188, 559, 274, 50),
+    // // 用户二维码
+    ctx.drawImage(codeImgUrl, 518, 780, 92, 92),
+  ]);
+});
+~~~
+
+需要注意的是:`ctx.drawRoundImage`不可以放在`Promise.all`当中,由于`ctx.drawRoundImage`内部会调用`ctx.clip`方法,在`Promise.all`中会与其他图片绘制产生冲突。从而导致圆角失效。
+
+我的博客:[Mr.Mao'blog](https://tuimao233.gitee.io/mao-blog/)
+
+联系方式(邮箱):951416545@qq.com
+
+海报绘制QQ群:936377537

+ 38 - 0
pagesPoster/comps/u-draw-poster/dist/draw-poster.d.ts

@@ -0,0 +1,38 @@
+import { Canvas, DrawPosterCanvasCtx, CreateImagePathOptions, DrawPosterBuildOpts, DrawPosterUseOpts, drawPosterExtends, DrawPosterUseCtxOpts } from "./utils/interface";
+declare type DrawPosterInstanceType = InstanceType<typeof DrawPoster> & drawPosterExtends;
+declare class DrawPoster {
+    canvas: Canvas;
+    ctx: DrawPosterCanvasCtx;
+    canvasId: string;
+    loading: boolean;
+    debugging: boolean;
+    loadingText: string;
+    createText: string;
+    [key: string]: any;
+    private executeOnions;
+    private stopStatus;
+    private drawType;
+    /** 构建器, 构建返回当前实例, 并挂载多个方法 */
+    constructor(canvas: Canvas, ctx: DrawPosterCanvasCtx, canvasId: string, loading: boolean, debugging: boolean, loadingText: string, createText: string, tips: boolean);
+    /** 提示器, 传入消息与数据 */
+    private debuggingLog;
+    /** 传入挂载配置对象, 添加扩展方法 */
+    static use: (opts: DrawPosterUseOpts) => void;
+    /** 传入挂载配置对象, 添加绘画扩展方法 */
+    static useCtx: (opts: DrawPosterUseCtxOpts) => void;
+    /** 构建绘制海报矩形方法, 传入canvas选择器或配置对象, 返回绘制对象 */
+    static build: (options: string | DrawPosterBuildOpts, tips?: boolean) => Promise<DrawPosterInstanceType>;
+    /** 构建多个绘制海报矩形方法, 传入选择器或配置对象的数组, 返回多个绘制对象 */
+    static buildAll: (optionsAll: (string | DrawPosterBuildOpts)[]) => Promise<{
+        [key: string]: DrawPosterInstanceType;
+    }>;
+    /** 绘制器, 接收执行器函数, 添加到绘制容器中 */
+    draw: (execute: (ctx: DrawPosterCanvasCtx) => Promise<any> | void) => void;
+    /** 等待创建绘画, 成功后清空绘制器容器 */
+    awaitCreate: () => Promise<boolean[]>;
+    /** 创建canvas本地地址 @returns {string} 本地地址 */
+    createImagePath: (baseOptions?: CreateImagePathOptions) => Promise<string>;
+    /** 停止当前绘画, 调用则停止当前绘画堆栈的绘画 */
+    stop: () => void;
+}
+export default DrawPoster;

+ 190 - 0
pagesPoster/comps/u-draw-poster/dist/draw-poster.js

@@ -0,0 +1,190 @@
+import uni from "./utils/global";
+import { handleBuildOpts, extendMount } from "./utils/utils";
+import { getCanvas2dContext } from "./utils/wx-utils";
+// 扩展挂载储存
+let drawPosterExtend = {};
+let drawCtxPosterExtend = {};
+class DrawPoster {
+    /** 构建器, 构建返回当前实例, 并挂载多个方法 */
+    constructor(canvas, ctx, canvasId, loading, debugging, loadingText, createText, tips) {
+        var _a;
+        this.canvas = canvas;
+        this.ctx = ctx;
+        this.canvasId = canvasId;
+        this.loading = loading;
+        this.debugging = debugging;
+        this.loadingText = loadingText;
+        this.createText = createText;
+        this.executeOnions = [];
+        this.stopStatus = false;
+        /** 提示器, 传入消息与数据 */
+        this.debuggingLog = (message, data, color = "#3489fd") => {
+            if (this.debugging) {
+                if (data) {
+                    console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`, data);
+                }
+                else {
+                    console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`);
+                }
+            }
+        };
+        /** 绘制器, 接收执行器函数, 添加到绘制容器中 */
+        this.draw = (execute) => {
+            const length = this.executeOnions.length;
+            this.executeOnions.push(async () => {
+                var _a, _b;
+                try {
+                    this.ctx.save();
+                    await execute(this.ctx);
+                    this.ctx.restore();
+                    return true;
+                }
+                catch (error) {
+                    const isOutError = ((_b = (_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.search) === null || _b === void 0 ? void 0 : _b.call(_a, `'nodeId' of undefined`)) >= 0;
+                    !isOutError && console.error(`${this.canvasId} -> 绘画栈(${length}),绘制错误:`, error);
+                    return false;
+                }
+            });
+        };
+        /** 等待创建绘画, 成功后清空绘制器容器 */
+        this.awaitCreate = async () => {
+            this.debuggingLog('绘制海报中...');
+            this.loading && uni.showLoading({ title: this.loadingText });
+            const tips = [];
+            for (let i = 0; i < this.executeOnions.length; i++) {
+                const execute = this.executeOnions[i];
+                tips.push(await execute());
+            }
+            this.executeOnions = [];
+            this.debuggingLog('绘制状况', tips);
+            // 当前绘制为 type2 绘制
+            if (this.drawType === 'type2d') {
+                this.loading && uni.hideLoading();
+                return tips;
+            }
+            // 当前绘制为 context 绘制
+            return await new Promise((resolve) => {
+                this.ctx.draw(true, () => {
+                    resolve(tips);
+                    this.loading && uni.hideLoading();
+                });
+            });
+        };
+        /** 创建canvas本地地址 @returns {string} 本地地址 */
+        this.createImagePath = async (baseOptions = {}) => {
+            const { canvas, canvasId, executeOnions, awaitCreate } = this;
+            executeOnions.length && await awaitCreate();
+            // 如果当前为停止状态
+            if (this.stopStatus) {
+                this.stopStatus = false;
+                return '---stop createImagePath---';
+            }
+            this.loading && uni.showLoading({ title: this.createText });
+            const options = Object.assign({}, baseOptions);
+            if (this.drawType === 'context')
+                options.canvasId = canvasId;
+            if (this.drawType === 'type2d')
+                options.canvas = canvas;
+            return new Promise((resolve, reject) => {
+                options.success = (res) => {
+                    resolve(res.tempFilePath);
+                    this.loading && uni.hideLoading();
+                    this.debuggingLog('绘制成功 🎉', res, '#19be6b');
+                };
+                options.fail = (err) => {
+                    reject(err);
+                    this.loading && uni.hideLoading();
+                    this.debuggingLog('绘制失败 🌟', err, '#fa3534');
+                };
+                uni.canvasToTempFilePath(options);
+            });
+        };
+        /** 停止当前绘画, 调用则停止当前绘画堆栈的绘画 */
+        this.stop = () => {
+            this.executeOnions = [];
+            this.stopStatus = true;
+        };
+        if (!canvas || !ctx || !canvasId) {
+            throw new Error("DrawPoster Error: Use DrawPoster.build(string | ops) to build drawPoster instance objects");
+        }
+        // 判断当前绘制类型
+        ctx.drawType = this.drawType = (ctx.draw) ? 'context' : 'type2d';
+        // 挂载全局实例, 绘画扩展
+        extendMount(this.ctx, drawCtxPosterExtend, (extend, target) => {
+            var _a;
+            (_a = target === null || target === void 0 ? void 0 : target.init) === null || _a === void 0 ? void 0 : _a.call(target, this.canvas, this.ctx);
+            return (...args) => extend(this.canvas, this.ctx, ...args);
+        });
+        extendMount(this, drawPosterExtend, (extend, target) => {
+            var _a;
+            (_a = target === null || target === void 0 ? void 0 : target.init) === null || _a === void 0 ? void 0 : _a.call(target, this);
+            return (...args) => extend(this, ...args);
+        });
+        // 当离开页面时, 自动调用停止绘画
+        const _this = this;
+        const pages = getCurrentPages();
+        const page = pages[pages.length - 1];
+        // 查询标识, 不存在, 在替换页面卸载回调, 避免产生死循环
+        if (!((_a = page === null || page === void 0 ? void 0 : page.onUnload) === null || _a === void 0 ? void 0 : _a.identification)) {
+            page.oldOnUnload = page.onUnload;
+            page.onUnload = function () {
+                _this === null || _this === void 0 ? void 0 : _this.stop();
+                page.oldOnUnload();
+            };
+            page.onUnload.identification = true;
+        }
+        tips && this.debuggingLog('构建完成', { canvas, ctx, selector: canvasId }, '#19be6b');
+    }
+}
+/** 传入挂载配置对象, 添加扩展方法 */
+DrawPoster.use = (opts) => {
+    if (opts.name)
+        drawPosterExtend[opts.name] = opts;
+};
+/** 传入挂载配置对象, 添加绘画扩展方法 */
+DrawPoster.useCtx = (opts) => {
+    if (opts.name)
+        drawCtxPosterExtend[opts.name] = opts;
+};
+/** 构建绘制海报矩形方法, 传入canvas选择器或配置对象, 返回绘制对象 */
+DrawPoster.build = async (options, tips = true) => {
+    var _a, _b, _c, _d, _e;
+    const config = handleBuildOpts(options);
+    // 初始化监测当前页面绘制对象
+    const pages = getCurrentPages();
+    const page = pages[pages.length - 1];
+    const gcanvas = DrawPoster.prototype['gcanvas'];
+    if (page[config.selector + '__dp']) {
+        return page[config.selector + '__dp'];
+    }
+    if (config.gcanvas) {
+        if (!gcanvas)
+            console.error('--- 当前未引入gcanvas扩展, 将自动切换为普通 canvas ---');
+        else
+            gcanvas.enable((_b = (_a = config.componentThis) === null || _a === void 0 ? void 0 : _a.$refs) === null || _b === void 0 ? void 0 : _b[config.selector], {
+                bridge: gcanvas.WeexBridge
+            });
+    }
+    // 获取canvas实例
+    const canvas = config.gcanvas && gcanvas ?
+        gcanvas.enable((_d = (_c = config.componentThis) === null || _c === void 0 ? void 0 : _c.$refs) === null || _d === void 0 ? void 0 : _d[config.selector], {
+            bridge: gcanvas.WeexBridge
+        }) :
+        await getCanvas2dContext(config.selector, config.componentThis);
+    const ctx = (((_e = canvas.getContext) === null || _e === void 0 ? void 0 : _e.call(canvas, "2d")) || uni.createCanvasContext(config.selector, config.componentThis));
+    const dp = new DrawPoster(canvas, ctx, config.selector, config.loading, config.debugging, config.loadingText, config.createText, tips);
+    // 储存当前绘制对象
+    page[config.selector + '__dp'] = dp;
+    return page[config.selector + '__dp'];
+};
+/** 构建多个绘制海报矩形方法, 传入选择器或配置对象的数组, 返回多个绘制对象 */
+DrawPoster.buildAll = async (optionsAll) => {
+    const dpsArr = await Promise.all(optionsAll.map(async (options) => {
+        return await DrawPoster.build(options, false);
+    }));
+    const dpsObj = {};
+    dpsArr.forEach(dp => dpsObj[dp.canvasId] = dp);
+    console.log("%cdraw-poster 构建完成:", "#E3712A", dpsObj);
+    return dpsObj;
+};
+export default DrawPoster;

+ 17 - 0
pagesPoster/comps/u-draw-poster/dist/extends/create-from-list/index.d.ts

@@ -0,0 +1,17 @@
+import { DrawPosterUseOpts } from '../../utils/interface';
+export interface CreateLayerOpts {
+    background?: string;
+    self?: boolean;
+    line?: boolean;
+    lineHeight?: number;
+}
+export interface DrawRowOpt {
+    text?: string;
+    font?: string;
+    color?: string;
+    center?: boolean;
+    width?: number;
+}
+declare const _default: DrawPosterUseOpts;
+/** 绘制表单扩展方法 */
+export default _default;

+ 140 - 0
pagesPoster/comps/u-draw-poster/dist/extends/create-from-list/index.js

@@ -0,0 +1,140 @@
+/** 绘制表单扩展方法 */
+export default {
+    name: 'createLayer',
+    init: (dp) => {
+        dp.from = {
+            height: 0,
+            padding: 8,
+            margin: 0
+        };
+        dp.setFromOptions = (opts) => {
+            if (typeof opts.height !== 'undefined') {
+                dp.from.height = opts.height;
+            }
+            if (typeof opts.margin !== 'undefined') {
+                dp.from.margin = opts.margin;
+            }
+            if (typeof opts.padding !== 'undefined') {
+                dp.from.padding = opts.padding;
+            }
+        };
+    },
+    handle: (dp, afferOpts, rowList) => {
+        // 当前配置(头部偏移量, 列内边距, 表单外边距)
+        const height = dp.from.height;
+        const margin = dp.from.margin;
+        const padding = dp.from.padding;
+        // 当前层宽度
+        const containerWidth = dp.canvas.width - (margin * 2);
+        // 基本层配置
+        const opts = Object.assign({ background: "#fff", columnY: height || margin, self: true, line: true, lineHeight: 0, border: true }, afferOpts);
+        // 基本列配置
+        const baseRowOpts = {
+            text: "",
+            font: "24px sans-serif",
+            color: "#333",
+            center: false,
+            width: 0,
+        };
+        // 累计最高的列为标准定义为层高度
+        let maxRowHeight = 0;
+        // 累计固定栅格列偏移量
+        let columnOffsetX = margin;
+        // 创建行绘制任务
+        const drawLayerInfos = rowList.map((afferRowOpts = {}, index) => {
+            const rowOpts = Object.assign(Object.assign({}, baseRowOpts), afferRowOpts);
+            let columnX = 0; // 每列的X轴
+            let columnW = 0; // 每列的宽度
+            let fontOffsetX = 0; // 字体偏移X轴
+            let fontMaxWidth = 100; // 字体最大宽度
+            opts.lineHeight = opts.lineHeight || Number(rowOpts.font.replace(/[^0-9.]/g, ""));
+            if (opts.self) {
+                // 自适应栅格格子计算
+                columnX = containerWidth - (containerWidth / (index + 1)) + margin;
+                columnW = containerWidth / rowList.length;
+                if (columnX > 0 && columnX < containerWidth - columnW) {
+                    columnX = (columnW * index) + margin;
+                }
+                fontOffsetX = rowOpts.center ? columnX + (columnW / 2) : columnX + padding;
+                fontMaxWidth = columnW - (padding * 3);
+            }
+            if (!opts.self) {
+                // 固定栅格格子计算
+                columnW = rowOpts.width;
+                columnX = columnOffsetX;
+                fontMaxWidth = columnW - (padding * 3);
+                fontOffsetX = rowOpts.center ? columnOffsetX + (rowOpts.width / 2) : columnOffsetX + padding;
+                columnOffsetX += rowOpts.width;
+            }
+            dp.ctx.font = rowOpts.font;
+            const drawFontInfos = dp.ctx.fillWarpText({
+                text: rowOpts.text,
+                maxWidth: fontMaxWidth,
+                lineHeight: opts.lineHeight,
+                x: fontOffsetX,
+                y: opts.columnY,
+                layer: 10,
+                notFillText: true
+            });
+            // 当前行的高度
+            const rowHeight = (opts.lineHeight * drawFontInfos.length) + (padding * 3);
+            // 若该列高度大于累计高度, 将累计高度替换
+            if (rowHeight > maxRowHeight) {
+                maxRowHeight = rowHeight;
+            }
+            return {
+                font: rowOpts.font,
+                center: rowOpts.center,
+                color: rowOpts.color,
+                border: opts.border,
+                background: opts.background,
+                lineHeight: opts.lineHeight,
+                line: opts.line,
+                drawFontInfos,
+                columnY: opts.columnY,
+                columnX,
+                columnW,
+                columnH: maxRowHeight,
+                margin,
+                padding
+            };
+        });
+        // 将行绘制任务添加至绘制容器中
+        dp.draw((ctx) => drawLayerInfos.forEach((rowOpts, index) => {
+            ctx.font = rowOpts.font;
+            ctx.fillStyle = rowOpts.background;
+            ctx.strokeStyle = "#333";
+            ctx.textBaseline = "middle";
+            ctx.textAlign = 'left';
+            if (rowOpts.center) {
+                ctx.textAlign = "center";
+            }
+            ctx.fillRect(rowOpts.columnX, rowOpts.columnY, rowOpts.columnW, rowOpts.columnH);
+            if (rowOpts.border) {
+                dp.ctx.strokeRect(margin, rowOpts.columnY, dp.canvas.width - margin, maxRowHeight);
+            }
+            if (rowOpts.line && rowOpts.columnX !== margin) {
+                ctx.moveTo(rowOpts.columnX, rowOpts.columnY);
+                ctx.lineTo(rowOpts.columnX, rowOpts.columnY + rowOpts.columnH);
+                ctx.stroke();
+                ctx.beginPath();
+            }
+            ctx.fillStyle = rowOpts.color;
+            rowOpts.drawFontInfos.forEach(fontInfo => {
+                // 计算每行字体绘制y轴长度
+                // y(当前列置顶轴) + (rowOpts.columnH(当前列最高长度) / 2) - (((总列数-1) * 行高) / 2)
+                const textTotal = rowOpts.drawFontInfos.length - 1;
+                const textMiddleY = (textTotal * rowOpts.lineHeight) / 2;
+                let fontOffsetY = fontInfo.y + (rowOpts.columnH / 2);
+                fontOffsetY -= textMiddleY;
+                ctx.fillText(fontInfo.text, fontInfo.x, fontOffsetY);
+            });
+        }));
+        if (opts.columnY === 0 || opts.columnY === margin) {
+            maxRowHeight += margin;
+        }
+        // 叠加高度
+        dp.from.height += maxRowHeight;
+        return maxRowHeight;
+    },
+};

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/create-gcanvas/index.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseOpts } from '../../utils/interface';
+export * from './gcanvas';
+declare const _default: DrawPosterUseOpts;
+export default _default;

+ 9 - 0
pagesPoster/comps/u-draw-poster/dist/extends/create-gcanvas/index.js

@@ -0,0 +1,9 @@
+import { WeexBridge, enable, Image } from './gcanvas';
+export * from './gcanvas';
+import DrawPoster from "../../draw-poster";
+DrawPoster.prototype['gcanvas'] = {
+    WeexBridge,
+    enable,
+    Image
+};
+export default {};

+ 12 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image-fit.d.ts

@@ -0,0 +1,12 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+import { ObjectFit, ObjectPosition, Size } from "../../utils/object-sizing";
+export interface ImageFitOption {
+    radius?: number;
+    objectFit?: ObjectFit;
+    intrinsicSize?: Size;
+    specifiedSize?: Size;
+    intrinsicPosition?: ObjectPosition;
+    specifiedPosition?: [number, number];
+}
+declare const _default: DrawPosterUseCtxOpts;
+export default _default;

+ 25 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image-fit.js

@@ -0,0 +1,25 @@
+import { calculateConcreteRect } from "../../utils/object-sizing";
+import uni from "../../utils/global";
+export default {
+    name: 'drawImageFit',
+    handle: async (canvas, ctx, url, options) => {
+        var _a, _b, _c;
+        const [error, imageInfo] = await uni.getImageInfo({ src: url });
+        // 配置默认值
+        const style = Object.assign({ radius: 0, objectFit: 'cover', intrinsicSize: { width: (_a = imageInfo === null || imageInfo === void 0 ? void 0 : imageInfo.width) !== null && _a !== void 0 ? _a : 100, height: (_b = imageInfo === null || imageInfo === void 0 ? void 0 : imageInfo.height) !== null && _b !== void 0 ? _b : 100 }, specifiedSize: { width: 100, height: 100 }, intrinsicPosition: ['center', 'center'], specifiedPosition: [0, 0] }, options);
+        // 计算图片尺寸
+        const drawImageInfo = calculateConcreteRect(style, style.intrinsicSize, style.specifiedSize);
+        // 如有圆角, 则进行裁剪
+        if (style.radius > 0) {
+            ctx.save();
+            (_c = ctx.setFillStyle) === null || _c === void 0 ? void 0 : _c.call(ctx, 'transparent');
+            ctx.fillStyle = 'transparent';
+            ctx.fillRoundRect(style.specifiedPosition[0], style.specifiedPosition[1], style.specifiedSize.width, style.specifiedSize.height, style.radius);
+            ctx.clip();
+        }
+        const result = await ctx.drawImage(url, ...Object.values(drawImageInfo));
+        if (style.radius > 0)
+            ctx.restore();
+        return result;
+    }
+};

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+declare const _default: DrawPosterUseCtxOpts;
+/** 等待绘制图片原型方法 */
+export default _default;

+ 42 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-image.js

@@ -0,0 +1,42 @@
+import { downloadImgUrl } from '../../utils/wx-utils';
+/** 等待绘制图片原型方法 */
+export default {
+    name: 'drawImage',
+    init: (canvas, ctx) => {
+        ctx.drawImageProto = ctx.drawImage;
+    },
+    handle: async (canvas, ctx, url, sx, sy, sh, sw, dx, dy, dh, dw) => {
+        // 下载路径
+        const path = await downloadImgUrl(url);
+        // 标记当前绘画存在图片绘制
+        let result = false;
+        // 基本绘制方法, 如果是 fit 方式, 则传入所有参数, 不然则只传入四个参数
+        const baseDrawImage = (imageResource) => {
+            const isFit = typeof dx === 'number' && typeof dw === 'number';
+            if (isFit) {
+                ctx.drawImageProto(imageResource, sx, sy, sh, sw, dx, dy, dh, dw);
+            }
+            else {
+                ctx.drawImageProto(imageResource, sx, sy, sh, sw);
+            }
+        };
+        // 如果是 context 绘制方式, 则直接绘制
+        if (ctx.drawType === 'context') {
+            baseDrawImage(path);
+            result = true;
+        }
+        // 如果是 type2d 绘制方式, 则等待图片绘制完毕
+        if (ctx.drawType === 'type2d') {
+            result = await new Promise(resolve => {
+                const image = canvas.createImage();
+                image.src = path;
+                image.onload = () => {
+                    baseDrawImage(image);
+                    resolve(true);
+                };
+                image.onerror = () => resolve(false);
+            });
+        }
+        return result;
+    }
+};

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-round-image.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+declare const _default: DrawPosterUseCtxOpts;
+/** 绘制圆角图片原型方法 */
+export default _default;

+ 15 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/draw-round-image.js

@@ -0,0 +1,15 @@
+/** 绘制圆角图片原型方法 */
+export default {
+    name: 'drawRoundImage',
+    handle: async (canvas, ctx, url, x, y, w, h, r = 15) => {
+        var _a;
+        ctx.save();
+        (_a = ctx.setFillStyle) === null || _a === void 0 ? void 0 : _a.call(ctx, 'transparent');
+        ctx.fillStyle = 'transparent';
+        ctx.fillRoundRect(x, y, w, h, r);
+        ctx.clip();
+        const result = await ctx.drawImage(url, x, y, w, h);
+        ctx.restore();
+        return result;
+    }
+};

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-round-rect.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+declare const _default: DrawPosterUseCtxOpts;
+/** 绘制填充圆角矩形方法 */
+export default _default;

+ 7 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-round-rect.js

@@ -0,0 +1,7 @@
+/** 绘制填充圆角矩形方法 */
+export default {
+    name: 'fillRoundRect',
+    handle: (canvas, ctx, x, y, w, h, r) => {
+        ctx.roundRect(x, y, w, h, r, true);
+    }
+};

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-warp-text.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+declare const _default: DrawPosterUseCtxOpts;
+/** 绘制换行字体原型方法 */
+export default _default;

+ 76 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/fill-warp-text.js

@@ -0,0 +1,76 @@
+/** 绘制换行字体原型方法 */
+export default {
+    name: 'fillWarpText',
+    handle: (canvas, ctx, config) => {
+        const newConfig = config = Object.assign({ maxWidth: 100, layer: 2, lineHeight: Number(ctx.font.replace(/[^0-9.]/g, '')), x: 0, y: Number(ctx.font.replace(/[^0-9.]/g, '')) / 1.2, splitText: '', notFillText: false }, config);
+        const { text, splitText, maxWidth, layer, lineHeight, notFillText, x, y } = newConfig;
+        // 当字符串为空时, 抛出错误
+        if (!text) {
+            throw Error('warpFillText Error: text is empty string');
+        }
+        // 分割所有单个字符串
+        const chr = text.split(splitText);
+        // 存入的每行字体的容器
+        let row = [];
+        // 判断字符串
+        let timp = '';
+        if (splitText) {
+            row = chr;
+        }
+        else {
+            // 遍历所有字符串, 填充行容器
+            for (let i = 0; i < chr.length; i++) {
+                // 当超出行列时, 停止执行遍历, 节省计算时间
+                if (row.length > layer) {
+                    break;
+                }
+                if (ctx.measureText(timp).width < maxWidth) {
+                    // 如果超出长度, 添加进row数组
+                    timp += chr[i];
+                }
+                else {
+                    // 如超出一行长度, 则换行, 并清除容器
+                    i--;
+                    row.push(timp);
+                    timp = '';
+                }
+            }
+            // 如有剩下字体, 则在最后时添加一行
+            if (timp) {
+                row.push(timp);
+            }
+            // 如果数组长度大于指定行数
+            if (row.length > layer) {
+                row = row.slice(0, layer);
+                // 结束的索引
+                const end = layer - 1;
+                for (let i = 0; i < row[end].length; i++) {
+                    const currentWidth = ctx.measureText(`${row[end]}...`).width;
+                    if (currentWidth > maxWidth) {
+                        // 加上... 当前宽度大于最大宽度时, 去除一位字符串
+                        const strEnd = row[end].length - 1;
+                        row[end] = row[end].slice(0, strEnd);
+                    }
+                    else {
+                        row[end] += '...';
+                        break;
+                    }
+                }
+            }
+        }
+        // 储存并返回绘制信息
+        const drawInfos = row.map((item, index) => {
+            const info = {
+                text: item,
+                y: y + index * lineHeight,
+                x: x,
+            };
+            // 默认执行绘制信息
+            if (!notFillText) {
+                ctx.fillText(info.text, info.x, info.y);
+            }
+            return info;
+        });
+        return drawInfos;
+    }
+};

+ 7 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/index.d.ts

@@ -0,0 +1,7 @@
+export { default as drawImage } from "./draw-image";
+export { default as roundRect } from "./round-rect";
+export { default as fillRoundRect } from "./fill-round-rect";
+export { default as strokeRoundRect } from "./stroke-round-rect";
+export { default as fillWarpText } from "./fill-warp-text";
+export { default as drawRoundImage } from "./draw-round-image";
+export { default as drawImageFit } from "./draw-image-fit";

+ 15 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/index.js

@@ -0,0 +1,15 @@
+/*
+ * @Author: Mr.Mao
+ * @LastEditors: Mr.Mao
+ * @Date: 2020-11-11 20:43:33
+ * @LastEditTime: 2021-01-02 00:16:59
+ * @Description:
+ * @任何一个傻子都能写出让电脑能懂的代码,而只有好的程序员可以写出让人能看懂的代码
+ */
+export { default as drawImage } from "./draw-image";
+export { default as roundRect } from "./round-rect";
+export { default as fillRoundRect } from "./fill-round-rect";
+export { default as strokeRoundRect } from "./stroke-round-rect";
+export { default as fillWarpText } from "./fill-warp-text";
+export { default as drawRoundImage } from "./draw-round-image";
+export { default as drawImageFit } from "./draw-image-fit";

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/round-rect.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+declare const _default: DrawPosterUseCtxOpts;
+/** 绘制圆角矩形原型方法 */
+export default _default;

+ 41 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/round-rect.js

@@ -0,0 +1,41 @@
+/** 绘制圆角矩形原型方法 */
+export default {
+    name: 'roundRect',
+    handle: (canvas, ctx, x, y, w, h, r = 15, fill = false, stroke = false) => {
+        if (r === 0) {
+            if (stroke)
+                ctx.strokeRect(x, y, w, h);
+            if (fill)
+                ctx.fillRect(x, y, w, h);
+            return;
+        }
+        if (w < 2 * r) {
+            r = w / 2;
+        }
+        if (h < 2 * r) {
+            r = h / 2;
+        }
+        // 开始绘制
+        ctx.beginPath();
+        ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
+        // 移动复制
+        ctx.moveTo(x + r, y);
+        ctx.lineTo(x + w - r, y);
+        ctx.lineTo(x + w, y + r);
+        // (x,y,z,j,f) x,y圆心z半径,j起始弧度f,终止弧度
+        ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
+        ctx.lineTo(x + w, y + h - r);
+        ctx.lineTo(x + w - r, y + h);
+        ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5);
+        ctx.lineTo(x + r, y + h);
+        ctx.lineTo(x, y + h - r);
+        ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI);
+        ctx.lineTo(x, y + r);
+        ctx.lineTo(x + r, y);
+        if (stroke)
+            ctx.stroke();
+        if (fill)
+            ctx.fill();
+        ctx.closePath();
+    }
+};

+ 4 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/stroke-round-rect.d.ts

@@ -0,0 +1,4 @@
+import { DrawPosterUseCtxOpts } from '../../utils/interface';
+declare const _default: DrawPosterUseCtxOpts;
+/** 绘制填充圆角矩形方法 */
+export default _default;

+ 7 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-function/stroke-round-rect.js

@@ -0,0 +1,7 @@
+/** 绘制填充圆角矩形方法 */
+export default {
+    name: 'strokeRoundRect',
+    handle: (canvas, ctx, x, y, w, h, r) => {
+        ctx.roundRect(x, y, w, h, r, false, true);
+    }
+};

+ 101 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-painter/index.d.ts

@@ -0,0 +1,101 @@
+import { DrawPosterUseOpts } from '../../utils/interface';
+import { ImageFitOption } from '../draw-function/draw-image-fit';
+/** 矩形基本信息 */
+interface PainterItemSize {
+    /** 容器的宽度,固定值 */
+    width: number;
+    /** 容器的高度,固定值 */
+    height: number;
+}
+/** 元素位置信息 */
+interface PainterItemSite {
+    /** 元素锚点距左边的距离; 默认: 0 */
+    left?: number;
+    /** 元素锚点距上边的距离; 默认: 0 */
+    top?: number;
+}
+/** 绘制图片信息 */
+interface PainterImageInfo extends PainterItemSize, PainterItemSite {
+    /** 绘制图片元素 */
+    type: 'image';
+    /** 图片地址 */
+    src: string;
+    /** 图片自适应, 可参考 css 属性 object-fit */
+    objectFit?: ImageFitOption['objectFit'];
+    /** 图片在元素容器中显示的位置,可参考 css 属性 object-position */
+    position?: ImageFitOption['intrinsicPosition'];
+    /** 圆角尺寸; 默认: 0 */
+    radius?: number;
+}
+/** 绘制矩形信息 */
+interface PainterRectInfo extends PainterItemSize, PainterItemSite {
+    /** 绘制矩形元素 */
+    type: "rect";
+    /** 矩形背景颜色; 默认: "#000" */
+    background?: string;
+    /** 圆角尺寸; 默认: 0 */
+    radius?: number;
+}
+/** 绘制单行文字信息 */
+interface PainterTextInfo extends PainterItemSite {
+    /** 绘制文本元素 */
+    type: "text";
+    /** 文本颜色; 默认: "#000" */
+    color?: string;
+    /** 字体; 默认: "serial" */
+    fontFamily?: string;
+    /** 字号(单位rpx); 默认: 30 rpx */
+    fontSize?: number;
+    /** 字重; 默认: "normal" 可选项: "bold" */
+    fontWeight?: string;
+    /** 字型 默认: "normal" 可选项: "italic" */
+    fontStyle?: string;
+    /** 元素的宽度(单位rpx), 水平排布时影响后一个元素的位置,为 null 时根据文字实际占用的宽度计算 */
+    width?: number;
+    /** 文本内容 */
+    content: string;
+}
+/** 绘制多行文字信息 */
+interface PainterLineFeedTextInfo extends PainterItemSite {
+    /** 绘制换行文本元素 */
+    type: "line-feed-text";
+    /** 文本颜色; 默认: "#000" */
+    color?: string;
+    /** 字体; 默认: "serial" */
+    fontFamily?: string;
+    /** 字号(单位rpx); 默认: 30 rpx */
+    fontSize?: number;
+    /** 字重; 默认: "normal" 可选项: "bold" */
+    fontWeight?: string;
+    /** 字型 默认: "normal" 可选项: "italic" */
+    fontStyle?: string;
+    /** 文本块的宽度,不能为空 */
+    width: number;
+    /** 行高; 默认取当前文字行高 */
+    lineHeight?: number;
+    /** 文本最大行数,超出即显示省略号; 默认3行 */
+    lineClamp?: number;
+    /** 文本内容 */
+    content: string;
+}
+/** 绘制二维码信息 */
+interface PainterQrCodeInfo extends PainterItemSite {
+    /** 绘制换行文本元素 */
+    type: "qr-code";
+    /** 二维码尺寸 */
+    size: number;
+    /** 二维码内容 */
+    content: string;
+    /** 边距,二维码实际尺寸会根据所设边距值进行缩放调整(默认:5) */
+    margin?: number;
+    /** 背景色(默认:'#ffffff')*/
+    backgroundColor?: string;
+    /** 前景色(默认:'#000000') */
+    foregroundColor?: string;
+}
+export interface PainterContainerOption extends PainterItemSize {
+    /** 绘制项的数组 */
+    contents: Array<PainterImageInfo | PainterRectInfo | PainterTextInfo | PainterLineFeedTextInfo | PainterQrCodeInfo>;
+}
+declare const _default: DrawPosterUseOpts;
+export default _default;

+ 73 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-painter/index.js

@@ -0,0 +1,73 @@
+export default {
+    name: 'painter',
+    handle: (dp, option) => {
+        dp.canvas.width = option.width;
+        dp.canvas.height = option.height;
+        dp.draw(async (ctx) => {
+            for (let i = 0; i < option.contents.length; i++) {
+                ctx.save();
+                const drawInfo = option.contents[i];
+                const { left = 0, top = 0 } = drawInfo;
+                if (drawInfo.type === 'rect') {
+                    ctx.fillStyle = drawInfo.background || '#000000';
+                    ctx.fillRoundRect(left, top, drawInfo.width, drawInfo.height, drawInfo.radius || 0);
+                }
+                if (drawInfo.type === 'image') {
+                    await ctx.drawImageFit(drawInfo.src, {
+                        objectFit: drawInfo.objectFit || 'cover',
+                        intrinsicPosition: drawInfo.position || ['center', 'center'],
+                        specifiedPosition: [left, top],
+                        specifiedSize: {
+                            width: drawInfo.width,
+                            height: drawInfo.height
+                        },
+                        radius: drawInfo.radius
+                    });
+                }
+                if (drawInfo.type === 'text') {
+                    ctx.fillStyle = drawInfo.color || '#000000';
+                    ctx.font = `\
+          ${drawInfo.fontStyle || 'normal'} \
+          ${drawInfo.fontWeight || 'normal'} \
+          ${drawInfo.fontSize || 30} \
+          ${drawInfo.fontFamily || 'serial'}\
+          `;
+                    ctx.fillText(drawInfo.content, left, top, drawInfo.width);
+                }
+                if (drawInfo.type === 'line-feed-text') {
+                    ctx.fillStyle = drawInfo.color || '#000000';
+                    ctx.font = `\
+          ${drawInfo.fontStyle || 'normal'} \
+          ${drawInfo.fontWeight || 'normal'} \
+          ${drawInfo.fontSize || 30} \
+          ${drawInfo.fontFamily || 'serial'}\
+          `;
+                    ctx.fillWarpText({
+                        x: drawInfo.left,
+                        y: drawInfo.top,
+                        layer: drawInfo.lineClamp,
+                        lineHeight: drawInfo.lineHeight,
+                        maxWidth: drawInfo.width,
+                        text: drawInfo.content
+                    });
+                }
+                if (drawInfo.type === 'qr-code') {
+                    if (typeof ctx.drawQrCode !== 'function') {
+                        console.error('--- 当前未引入qr-code扩展, 将自动省略该二维码绘制 ---');
+                        return false;
+                    }
+                    ctx.drawQrCode({
+                        x: left,
+                        y: top,
+                        size: drawInfo.size,
+                        text: drawInfo.content,
+                        margin: drawInfo.margin || 5,
+                        backgroundColor: drawInfo.backgroundColor || '#ffffff',
+                        foregroundColor: drawInfo.foregroundColor || '#000000',
+                    });
+                }
+                ctx.restore();
+            }
+        });
+    }
+};

+ 6 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/index.d.ts

@@ -0,0 +1,6 @@
+declare const _default: {
+    name: string;
+    handle: any;
+    errorCorrectLevel: any;
+};
+export default _default;

+ 6 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/index.js

@@ -0,0 +1,6 @@
+import uQRCode from "./uQRCode";
+export default {
+    name: "drawQrCode",
+    handle: uQRCode.make.bind(uQRCode),
+    errorCorrectLevel: uQRCode.errorCorrectLevel
+};

+ 10 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/uQRCode.d.ts

@@ -0,0 +1,10 @@
+/*
+ * @Author: Mr.Mao
+ * @LastEditors: Mr.Mao
+ * @Date: 2021-01-02 13:30:58
+ * @LastEditTime: 2021-01-02 13:31:27
+ * @Description: 
+ * @任何一个傻子都能写出让电脑能懂的代码,而只有好的程序员可以写出让人能看懂的代码
+ */
+declare const uQRCode: any
+export default uQRCode

+ 1355 - 0
pagesPoster/comps/u-draw-poster/dist/extends/draw-qr-code/uQRCode.js

@@ -0,0 +1,1355 @@
+/*
+ * @Author: Mr.Mao
+ * @LastEditors: Mr.Mao
+ * @Date: 2021-01-02 13:30:58
+ * @LastEditTime: 2021-01-02 13:30:58
+ * @Description: 
+ * @任何一个傻子都能写出让电脑能懂的代码,而只有好的程序员可以写出让人能看懂的代码
+ */
+//---------------------------------------------------------------------
+// github https://github.com/Sansnn/uQRCode
+//---------------------------------------------------------------------
+
+let uQRCode = {};
+
+(function () {
+  //---------------------------------------------------------------------
+  // QRCode for JavaScript
+  //
+  // Copyright (c) 2009 Kazuhiko Arase
+  //
+  // URL: http://www.d-project.com/
+  //
+  // Licensed under the MIT license:
+  //   http://www.opensource.org/licenses/mit-license.php
+  //
+  // The word "QR Code" is registered trademark of 
+  // DENSO WAVE INCORPORATED
+  //   http://www.denso-wave.com/qrcode/faqpatent-e.html
+  //
+  //---------------------------------------------------------------------
+
+  //---------------------------------------------------------------------
+  // QR8bitByte
+  //---------------------------------------------------------------------
+
+  function QR8bitByte(data) {
+    this.mode = QRMode.MODE_8BIT_BYTE;
+    this.data = data;
+  }
+
+  QR8bitByte.prototype = {
+
+    getLength: function (buffer) {
+      return this.data.length;
+    },
+
+    write: function (buffer) {
+      for (var i = 0; i < this.data.length; i++) {
+        // not JIS ...
+        buffer.put(this.data.charCodeAt(i), 8);
+      }
+    }
+  };
+
+  //---------------------------------------------------------------------
+  // QRCode
+  //---------------------------------------------------------------------
+
+  function QRCode(typeNumber, errorCorrectLevel) {
+    this.typeNumber = typeNumber;
+    this.errorCorrectLevel = errorCorrectLevel;
+    this.modules = null;
+    this.moduleCount = 0;
+    this.dataCache = null;
+    this.dataList = new Array();
+  }
+
+  QRCode.prototype = {
+
+    addData: function (data) {
+      var newData = new QR8bitByte(data);
+      this.dataList.push(newData);
+      this.dataCache = null;
+    },
+
+    isDark: function (row, col) {
+      if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
+        throw new Error(row + "," + col);
+      }
+      return this.modules[row][col];
+    },
+
+    getModuleCount: function () {
+      return this.moduleCount;
+    },
+
+    make: function () {
+      // Calculate automatically typeNumber if provided is < 1
+      if (this.typeNumber < 1) {
+        var typeNumber = 1;
+        for (typeNumber = 1; typeNumber < 40; typeNumber++) {
+          var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel);
+
+          var buffer = new QRBitBuffer();
+          var totalDataCount = 0;
+          for (var i = 0; i < rsBlocks.length; i++) {
+            totalDataCount += rsBlocks[i].dataCount;
+          }
+
+          for (var i = 0; i < this.dataList.length; i++) {
+            var data = this.dataList[i];
+            buffer.put(data.mode, 4);
+            buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
+            data.write(buffer);
+          }
+          if (buffer.getLengthInBits() <= totalDataCount * 8)
+            break;
+        }
+        this.typeNumber = typeNumber;
+      }
+      this.makeImpl(false, this.getBestMaskPattern());
+    },
+
+    makeImpl: function (test, maskPattern) {
+
+      this.moduleCount = this.typeNumber * 4 + 17;
+      this.modules = new Array(this.moduleCount);
+
+      for (var row = 0; row < this.moduleCount; row++) {
+
+        this.modules[row] = new Array(this.moduleCount);
+
+        for (var col = 0; col < this.moduleCount; col++) {
+          this.modules[row][col] = null; //(col + row) % 3;
+        }
+      }
+
+      this.setupPositionProbePattern(0, 0);
+      this.setupPositionProbePattern(this.moduleCount - 7, 0);
+      this.setupPositionProbePattern(0, this.moduleCount - 7);
+      this.setupPositionAdjustPattern();
+      this.setupTimingPattern();
+      this.setupTypeInfo(test, maskPattern);
+
+      if (this.typeNumber >= 7) {
+        this.setupTypeNumber(test);
+      }
+
+      if (this.dataCache == null) {
+        this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
+      }
+
+      this.mapData(this.dataCache, maskPattern);
+    },
+
+    setupPositionProbePattern: function (row, col) {
+
+      for (var r = -1; r <= 7; r++) {
+
+        if (row + r <= -1 || this.moduleCount <= row + r) continue;
+
+        for (var c = -1; c <= 7; c++) {
+
+          if (col + c <= -1 || this.moduleCount <= col + c) continue;
+
+          if ((0 <= r && r <= 6 && (c == 0 || c == 6)) ||
+            (0 <= c && c <= 6 && (r == 0 || r == 6)) ||
+            (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
+            this.modules[row + r][col + c] = true;
+          } else {
+            this.modules[row + r][col + c] = false;
+          }
+        }
+      }
+    },
+
+    getBestMaskPattern: function () {
+
+      var minLostPoint = 0;
+      var pattern = 0;
+
+      for (var i = 0; i < 8; i++) {
+
+        this.makeImpl(true, i);
+
+        var lostPoint = QRUtil.getLostPoint(this);
+
+        if (i == 0 || minLostPoint > lostPoint) {
+          minLostPoint = lostPoint;
+          pattern = i;
+        }
+      }
+
+      return pattern;
+    },
+
+    createMovieClip: function (target_mc, instance_name, depth) {
+
+      var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
+      var cs = 1;
+
+      this.make();
+
+      for (var row = 0; row < this.modules.length; row++) {
+
+        var y = row * cs;
+
+        for (var col = 0; col < this.modules[row].length; col++) {
+
+          var x = col * cs;
+          var dark = this.modules[row][col];
+
+          if (dark) {
+            qr_mc.beginFill(0, 100);
+            qr_mc.moveTo(x, y);
+            qr_mc.lineTo(x + cs, y);
+            qr_mc.lineTo(x + cs, y + cs);
+            qr_mc.lineTo(x, y + cs);
+            qr_mc.endFill();
+          }
+        }
+      }
+
+      return qr_mc;
+    },
+
+    setupTimingPattern: function () {
+
+      for (var r = 8; r < this.moduleCount - 8; r++) {
+        if (this.modules[r][6] != null) {
+          continue;
+        }
+        this.modules[r][6] = (r % 2 == 0);
+      }
+
+      for (var c = 8; c < this.moduleCount - 8; c++) {
+        if (this.modules[6][c] != null) {
+          continue;
+        }
+        this.modules[6][c] = (c % 2 == 0);
+      }
+    },
+
+    setupPositionAdjustPattern: function () {
+
+      var pos = QRUtil.getPatternPosition(this.typeNumber);
+
+      for (var i = 0; i < pos.length; i++) {
+
+        for (var j = 0; j < pos.length; j++) {
+
+          var row = pos[i];
+          var col = pos[j];
+
+          if (this.modules[row][col] != null) {
+            continue;
+          }
+
+          for (var r = -2; r <= 2; r++) {
+
+            for (var c = -2; c <= 2; c++) {
+
+              if (r == -2 || r == 2 || c == -2 || c == 2 ||
+                (r == 0 && c == 0)) {
+                this.modules[row + r][col + c] = true;
+              } else {
+                this.modules[row + r][col + c] = false;
+              }
+            }
+          }
+        }
+      }
+    },
+
+    setupTypeNumber: function (test) {
+
+      var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
+
+      for (var i = 0; i < 18; i++) {
+        var mod = (!test && ((bits >> i) & 1) == 1);
+        this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
+      }
+
+      for (var i = 0; i < 18; i++) {
+        var mod = (!test && ((bits >> i) & 1) == 1);
+        this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
+      }
+    },
+
+    setupTypeInfo: function (test, maskPattern) {
+
+      var data = (this.errorCorrectLevel << 3) | maskPattern;
+      var bits = QRUtil.getBCHTypeInfo(data);
+
+      // vertical		
+      for (var i = 0; i < 15; i++) {
+
+        var mod = (!test && ((bits >> i) & 1) == 1);
+
+        if (i < 6) {
+          this.modules[i][8] = mod;
+        } else if (i < 8) {
+          this.modules[i + 1][8] = mod;
+        } else {
+          this.modules[this.moduleCount - 15 + i][8] = mod;
+        }
+      }
+
+      // horizontal
+      for (var i = 0; i < 15; i++) {
+
+        var mod = (!test && ((bits >> i) & 1) == 1);
+
+        if (i < 8) {
+          this.modules[8][this.moduleCount - i - 1] = mod;
+        } else if (i < 9) {
+          this.modules[8][15 - i - 1 + 1] = mod;
+        } else {
+          this.modules[8][15 - i - 1] = mod;
+        }
+      }
+
+      // fixed module
+      this.modules[this.moduleCount - 8][8] = (!test);
+
+    },
+
+    mapData: function (data, maskPattern) {
+
+      var inc = -1;
+      var row = this.moduleCount - 1;
+      var bitIndex = 7;
+      var byteIndex = 0;
+
+      for (var col = this.moduleCount - 1; col > 0; col -= 2) {
+
+        if (col == 6) col--;
+
+        while (true) {
+
+          for (var c = 0; c < 2; c++) {
+
+            if (this.modules[row][col - c] == null) {
+
+              var dark = false;
+
+              if (byteIndex < data.length) {
+                dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
+              }
+
+              var mask = QRUtil.getMask(maskPattern, row, col - c);
+
+              if (mask) {
+                dark = !dark;
+              }
+
+              this.modules[row][col - c] = dark;
+              bitIndex--;
+
+              if (bitIndex == -1) {
+                byteIndex++;
+                bitIndex = 7;
+              }
+            }
+          }
+
+          row += inc;
+
+          if (row < 0 || this.moduleCount <= row) {
+            row -= inc;
+            inc = -inc;
+            break;
+          }
+        }
+      }
+
+    }
+
+  };
+
+  QRCode.PAD0 = 0xEC;
+  QRCode.PAD1 = 0x11;
+
+  QRCode.createData = function (typeNumber, errorCorrectLevel, dataList) {
+
+    var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
+
+    var buffer = new QRBitBuffer();
+
+    for (var i = 0; i < dataList.length; i++) {
+      var data = dataList[i];
+      buffer.put(data.mode, 4);
+      buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
+      data.write(buffer);
+    }
+
+    // calc num max data.
+    var totalDataCount = 0;
+    for (var i = 0; i < rsBlocks.length; i++) {
+      totalDataCount += rsBlocks[i].dataCount;
+    }
+
+    if (buffer.getLengthInBits() > totalDataCount * 8) {
+      throw new Error("code length overflow. (" +
+        buffer.getLengthInBits() +
+        ">" +
+        totalDataCount * 8 +
+        ")");
+    }
+
+    // end code
+    if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
+      buffer.put(0, 4);
+    }
+
+    // padding
+    while (buffer.getLengthInBits() % 8 != 0) {
+      buffer.putBit(false);
+    }
+
+    // padding
+    while (true) {
+
+      if (buffer.getLengthInBits() >= totalDataCount * 8) {
+        break;
+      }
+      buffer.put(QRCode.PAD0, 8);
+
+      if (buffer.getLengthInBits() >= totalDataCount * 8) {
+        break;
+      }
+      buffer.put(QRCode.PAD1, 8);
+    }
+
+    return QRCode.createBytes(buffer, rsBlocks);
+  }
+
+  QRCode.createBytes = function (buffer, rsBlocks) {
+
+    var offset = 0;
+
+    var maxDcCount = 0;
+    var maxEcCount = 0;
+
+    var dcdata = new Array(rsBlocks.length);
+    var ecdata = new Array(rsBlocks.length);
+
+    for (var r = 0; r < rsBlocks.length; r++) {
+
+      var dcCount = rsBlocks[r].dataCount;
+      var ecCount = rsBlocks[r].totalCount - dcCount;
+
+      maxDcCount = Math.max(maxDcCount, dcCount);
+      maxEcCount = Math.max(maxEcCount, ecCount);
+
+      dcdata[r] = new Array(dcCount);
+
+      for (var i = 0; i < dcdata[r].length; i++) {
+        dcdata[r][i] = 0xff & buffer.buffer[i + offset];
+      }
+      offset += dcCount;
+
+      var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
+      var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
+
+      var modPoly = rawPoly.mod(rsPoly);
+      ecdata[r] = new Array(rsPoly.getLength() - 1);
+      for (var i = 0; i < ecdata[r].length; i++) {
+        var modIndex = i + modPoly.getLength() - ecdata[r].length;
+        ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
+      }
+
+    }
+
+    var totalCodeCount = 0;
+    for (var i = 0; i < rsBlocks.length; i++) {
+      totalCodeCount += rsBlocks[i].totalCount;
+    }
+
+    var data = new Array(totalCodeCount);
+    var index = 0;
+
+    for (var i = 0; i < maxDcCount; i++) {
+      for (var r = 0; r < rsBlocks.length; r++) {
+        if (i < dcdata[r].length) {
+          data[index++] = dcdata[r][i];
+        }
+      }
+    }
+
+    for (var i = 0; i < maxEcCount; i++) {
+      for (var r = 0; r < rsBlocks.length; r++) {
+        if (i < ecdata[r].length) {
+          data[index++] = ecdata[r][i];
+        }
+      }
+    }
+
+    return data;
+
+  }
+
+  //---------------------------------------------------------------------
+  // QRMode
+  //---------------------------------------------------------------------
+
+  var QRMode = {
+    MODE_NUMBER: 1 << 0,
+    MODE_ALPHA_NUM: 1 << 1,
+    MODE_8BIT_BYTE: 1 << 2,
+    MODE_KANJI: 1 << 3
+  };
+
+  //---------------------------------------------------------------------
+  // QRErrorCorrectLevel
+  //---------------------------------------------------------------------
+
+  var QRErrorCorrectLevel = {
+    L: 1,
+    M: 0,
+    Q: 3,
+    H: 2
+  };
+
+  //---------------------------------------------------------------------
+  // QRMaskPattern
+  //---------------------------------------------------------------------
+
+  var QRMaskPattern = {
+    PATTERN000: 0,
+    PATTERN001: 1,
+    PATTERN010: 2,
+    PATTERN011: 3,
+    PATTERN100: 4,
+    PATTERN101: 5,
+    PATTERN110: 6,
+    PATTERN111: 7
+  };
+
+  //---------------------------------------------------------------------
+  // QRUtil
+  //---------------------------------------------------------------------
+
+  var QRUtil = {
+
+    PATTERN_POSITION_TABLE: [
+      [],
+      [6, 18],
+      [6, 22],
+      [6, 26],
+      [6, 30],
+      [6, 34],
+      [6, 22, 38],
+      [6, 24, 42],
+      [6, 26, 46],
+      [6, 28, 50],
+      [6, 30, 54],
+      [6, 32, 58],
+      [6, 34, 62],
+      [6, 26, 46, 66],
+      [6, 26, 48, 70],
+      [6, 26, 50, 74],
+      [6, 30, 54, 78],
+      [6, 30, 56, 82],
+      [6, 30, 58, 86],
+      [6, 34, 62, 90],
+      [6, 28, 50, 72, 94],
+      [6, 26, 50, 74, 98],
+      [6, 30, 54, 78, 102],
+      [6, 28, 54, 80, 106],
+      [6, 32, 58, 84, 110],
+      [6, 30, 58, 86, 114],
+      [6, 34, 62, 90, 118],
+      [6, 26, 50, 74, 98, 122],
+      [6, 30, 54, 78, 102, 126],
+      [6, 26, 52, 78, 104, 130],
+      [6, 30, 56, 82, 108, 134],
+      [6, 34, 60, 86, 112, 138],
+      [6, 30, 58, 86, 114, 142],
+      [6, 34, 62, 90, 118, 146],
+      [6, 30, 54, 78, 102, 126, 150],
+      [6, 24, 50, 76, 102, 128, 154],
+      [6, 28, 54, 80, 106, 132, 158],
+      [6, 32, 58, 84, 110, 136, 162],
+      [6, 26, 54, 82, 110, 138, 166],
+      [6, 30, 58, 86, 114, 142, 170]
+    ],
+
+    G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
+    G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
+    G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
+
+    getBCHTypeInfo: function (data) {
+      var d = data << 10;
+      while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
+        d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
+      }
+      return ((data << 10) | d) ^ QRUtil.G15_MASK;
+    },
+
+    getBCHTypeNumber: function (data) {
+      var d = data << 12;
+      while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
+        d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
+      }
+      return (data << 12) | d;
+    },
+
+    getBCHDigit: function (data) {
+
+      var digit = 0;
+
+      while (data != 0) {
+        digit++;
+        data >>>= 1;
+      }
+
+      return digit;
+    },
+
+    getPatternPosition: function (typeNumber) {
+      return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
+    },
+
+    getMask: function (maskPattern, i, j) {
+
+      switch (maskPattern) {
+
+        case QRMaskPattern.PATTERN000:
+          return (i + j) % 2 == 0;
+        case QRMaskPattern.PATTERN001:
+          return i % 2 == 0;
+        case QRMaskPattern.PATTERN010:
+          return j % 3 == 0;
+        case QRMaskPattern.PATTERN011:
+          return (i + j) % 3 == 0;
+        case QRMaskPattern.PATTERN100:
+          return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
+        case QRMaskPattern.PATTERN101:
+          return (i * j) % 2 + (i * j) % 3 == 0;
+        case QRMaskPattern.PATTERN110:
+          return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
+        case QRMaskPattern.PATTERN111:
+          return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
+
+        default:
+          throw new Error("bad maskPattern:" + maskPattern);
+      }
+    },
+
+    getErrorCorrectPolynomial: function (errorCorrectLength) {
+
+      var a = new QRPolynomial([1], 0);
+
+      for (var i = 0; i < errorCorrectLength; i++) {
+        a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
+      }
+
+      return a;
+    },
+
+    getLengthInBits: function (mode, type) {
+
+      if (1 <= type && type < 10) {
+
+        // 1 - 9
+
+        switch (mode) {
+          case QRMode.MODE_NUMBER:
+            return 10;
+          case QRMode.MODE_ALPHA_NUM:
+            return 9;
+          case QRMode.MODE_8BIT_BYTE:
+            return 8;
+          case QRMode.MODE_KANJI:
+            return 8;
+          default:
+            throw new Error("mode:" + mode);
+        }
+
+      } else if (type < 27) {
+
+        // 10 - 26
+
+        switch (mode) {
+          case QRMode.MODE_NUMBER:
+            return 12;
+          case QRMode.MODE_ALPHA_NUM:
+            return 11;
+          case QRMode.MODE_8BIT_BYTE:
+            return 16;
+          case QRMode.MODE_KANJI:
+            return 10;
+          default:
+            throw new Error("mode:" + mode);
+        }
+
+      } else if (type < 41) {
+
+        // 27 - 40
+
+        switch (mode) {
+          case QRMode.MODE_NUMBER:
+            return 14;
+          case QRMode.MODE_ALPHA_NUM:
+            return 13;
+          case QRMode.MODE_8BIT_BYTE:
+            return 16;
+          case QRMode.MODE_KANJI:
+            return 12;
+          default:
+            throw new Error("mode:" + mode);
+        }
+
+      } else {
+        throw new Error("type:" + type);
+      }
+    },
+
+    getLostPoint: function (qrCode) {
+
+      var moduleCount = qrCode.getModuleCount();
+
+      var lostPoint = 0;
+
+      // LEVEL1
+
+      for (var row = 0; row < moduleCount; row++) {
+
+        for (var col = 0; col < moduleCount; col++) {
+
+          var sameCount = 0;
+          var dark = qrCode.isDark(row, col);
+
+          for (var r = -1; r <= 1; r++) {
+
+            if (row + r < 0 || moduleCount <= row + r) {
+              continue;
+            }
+
+            for (var c = -1; c <= 1; c++) {
+
+              if (col + c < 0 || moduleCount <= col + c) {
+                continue;
+              }
+
+              if (r == 0 && c == 0) {
+                continue;
+              }
+
+              if (dark == qrCode.isDark(row + r, col + c)) {
+                sameCount++;
+              }
+            }
+          }
+
+          if (sameCount > 5) {
+            lostPoint += (3 + sameCount - 5);
+          }
+        }
+      }
+
+      // LEVEL2
+
+      for (var row = 0; row < moduleCount - 1; row++) {
+        for (var col = 0; col < moduleCount - 1; col++) {
+          var count = 0;
+          if (qrCode.isDark(row, col)) count++;
+          if (qrCode.isDark(row + 1, col)) count++;
+          if (qrCode.isDark(row, col + 1)) count++;
+          if (qrCode.isDark(row + 1, col + 1)) count++;
+          if (count == 0 || count == 4) {
+            lostPoint += 3;
+          }
+        }
+      }
+
+      // LEVEL3
+
+      for (var row = 0; row < moduleCount; row++) {
+        for (var col = 0; col < moduleCount - 6; col++) {
+          if (qrCode.isDark(row, col) &&
+            !qrCode.isDark(row, col + 1) &&
+            qrCode.isDark(row, col + 2) &&
+            qrCode.isDark(row, col + 3) &&
+            qrCode.isDark(row, col + 4) &&
+            !qrCode.isDark(row, col + 5) &&
+            qrCode.isDark(row, col + 6)) {
+            lostPoint += 40;
+          }
+        }
+      }
+
+      for (var col = 0; col < moduleCount; col++) {
+        for (var row = 0; row < moduleCount - 6; row++) {
+          if (qrCode.isDark(row, col) &&
+            !qrCode.isDark(row + 1, col) &&
+            qrCode.isDark(row + 2, col) &&
+            qrCode.isDark(row + 3, col) &&
+            qrCode.isDark(row + 4, col) &&
+            !qrCode.isDark(row + 5, col) &&
+            qrCode.isDark(row + 6, col)) {
+            lostPoint += 40;
+          }
+        }
+      }
+
+      // LEVEL4
+
+      var darkCount = 0;
+
+      for (var col = 0; col < moduleCount; col++) {
+        for (var row = 0; row < moduleCount; row++) {
+          if (qrCode.isDark(row, col)) {
+            darkCount++;
+          }
+        }
+      }
+
+      var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
+      lostPoint += ratio * 10;
+
+      return lostPoint;
+    }
+
+  };
+
+
+  //---------------------------------------------------------------------
+  // QRMath
+  //---------------------------------------------------------------------
+
+  var QRMath = {
+
+    glog: function (n) {
+
+      if (n < 1) {
+        throw new Error("glog(" + n + ")");
+      }
+
+      return QRMath.LOG_TABLE[n];
+    },
+
+    gexp: function (n) {
+
+      while (n < 0) {
+        n += 255;
+      }
+
+      while (n >= 256) {
+        n -= 255;
+      }
+
+      return QRMath.EXP_TABLE[n];
+    },
+
+    EXP_TABLE: new Array(256),
+
+    LOG_TABLE: new Array(256)
+
+  };
+
+  for (var i = 0; i < 8; i++) {
+    QRMath.EXP_TABLE[i] = 1 << i;
+  }
+  for (var i = 8; i < 256; i++) {
+    QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^
+      QRMath.EXP_TABLE[i - 5] ^
+      QRMath.EXP_TABLE[i - 6] ^
+      QRMath.EXP_TABLE[i - 8];
+  }
+  for (var i = 0; i < 255; i++) {
+    QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
+  }
+
+  //---------------------------------------------------------------------
+  // QRPolynomial
+  //---------------------------------------------------------------------
+
+  function QRPolynomial(num, shift) {
+
+    if (num.length == undefined) {
+      throw new Error(num.length + "/" + shift);
+    }
+
+    var offset = 0;
+
+    while (offset < num.length && num[offset] == 0) {
+      offset++;
+    }
+
+    this.num = new Array(num.length - offset + shift);
+    for (var i = 0; i < num.length - offset; i++) {
+      this.num[i] = num[i + offset];
+    }
+  }
+
+  QRPolynomial.prototype = {
+
+    get: function (index) {
+      return this.num[index];
+    },
+
+    getLength: function () {
+      return this.num.length;
+    },
+
+    multiply: function (e) {
+
+      var num = new Array(this.getLength() + e.getLength() - 1);
+
+      for (var i = 0; i < this.getLength(); i++) {
+        for (var j = 0; j < e.getLength(); j++) {
+          num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
+        }
+      }
+
+      return new QRPolynomial(num, 0);
+    },
+
+    mod: function (e) {
+
+      if (this.getLength() - e.getLength() < 0) {
+        return this;
+      }
+
+      var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
+
+      var num = new Array(this.getLength());
+
+      for (var i = 0; i < this.getLength(); i++) {
+        num[i] = this.get(i);
+      }
+
+      for (var i = 0; i < e.getLength(); i++) {
+        num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
+      }
+
+      // recursive call
+      return new QRPolynomial(num, 0).mod(e);
+    }
+  };
+
+  //---------------------------------------------------------------------
+  // QRRSBlock
+  //---------------------------------------------------------------------
+
+  function QRRSBlock(totalCount, dataCount) {
+    this.totalCount = totalCount;
+    this.dataCount = dataCount;
+  }
+
+  QRRSBlock.RS_BLOCK_TABLE = [
+
+    // L
+    // M
+    // Q
+    // H
+
+    // 1
+    [1, 26, 19],
+    [1, 26, 16],
+    [1, 26, 13],
+    [1, 26, 9],
+
+    // 2
+    [1, 44, 34],
+    [1, 44, 28],
+    [1, 44, 22],
+    [1, 44, 16],
+
+    // 3
+    [1, 70, 55],
+    [1, 70, 44],
+    [2, 35, 17],
+    [2, 35, 13],
+
+    // 4		
+    [1, 100, 80],
+    [2, 50, 32],
+    [2, 50, 24],
+    [4, 25, 9],
+
+    // 5
+    [1, 134, 108],
+    [2, 67, 43],
+    [2, 33, 15, 2, 34, 16],
+    [2, 33, 11, 2, 34, 12],
+
+    // 6
+    [2, 86, 68],
+    [4, 43, 27],
+    [4, 43, 19],
+    [4, 43, 15],
+
+    // 7		
+    [2, 98, 78],
+    [4, 49, 31],
+    [2, 32, 14, 4, 33, 15],
+    [4, 39, 13, 1, 40, 14],
+
+    // 8
+    [2, 121, 97],
+    [2, 60, 38, 2, 61, 39],
+    [4, 40, 18, 2, 41, 19],
+    [4, 40, 14, 2, 41, 15],
+
+    // 9
+    [2, 146, 116],
+    [3, 58, 36, 2, 59, 37],
+    [4, 36, 16, 4, 37, 17],
+    [4, 36, 12, 4, 37, 13],
+
+    // 10		
+    [2, 86, 68, 2, 87, 69],
+    [4, 69, 43, 1, 70, 44],
+    [6, 43, 19, 2, 44, 20],
+    [6, 43, 15, 2, 44, 16],
+
+    // 11
+    [4, 101, 81],
+    [1, 80, 50, 4, 81, 51],
+    [4, 50, 22, 4, 51, 23],
+    [3, 36, 12, 8, 37, 13],
+
+    // 12
+    [2, 116, 92, 2, 117, 93],
+    [6, 58, 36, 2, 59, 37],
+    [4, 46, 20, 6, 47, 21],
+    [7, 42, 14, 4, 43, 15],
+
+    // 13
+    [4, 133, 107],
+    [8, 59, 37, 1, 60, 38],
+    [8, 44, 20, 4, 45, 21],
+    [12, 33, 11, 4, 34, 12],
+
+    // 14
+    [3, 145, 115, 1, 146, 116],
+    [4, 64, 40, 5, 65, 41],
+    [11, 36, 16, 5, 37, 17],
+    [11, 36, 12, 5, 37, 13],
+
+    // 15
+    [5, 109, 87, 1, 110, 88],
+    [5, 65, 41, 5, 66, 42],
+    [5, 54, 24, 7, 55, 25],
+    [11, 36, 12],
+
+    // 16
+    [5, 122, 98, 1, 123, 99],
+    [7, 73, 45, 3, 74, 46],
+    [15, 43, 19, 2, 44, 20],
+    [3, 45, 15, 13, 46, 16],
+
+    // 17
+    [1, 135, 107, 5, 136, 108],
+    [10, 74, 46, 1, 75, 47],
+    [1, 50, 22, 15, 51, 23],
+    [2, 42, 14, 17, 43, 15],
+
+    // 18
+    [5, 150, 120, 1, 151, 121],
+    [9, 69, 43, 4, 70, 44],
+    [17, 50, 22, 1, 51, 23],
+    [2, 42, 14, 19, 43, 15],
+
+    // 19
+    [3, 141, 113, 4, 142, 114],
+    [3, 70, 44, 11, 71, 45],
+    [17, 47, 21, 4, 48, 22],
+    [9, 39, 13, 16, 40, 14],
+
+    // 20
+    [3, 135, 107, 5, 136, 108],
+    [3, 67, 41, 13, 68, 42],
+    [15, 54, 24, 5, 55, 25],
+    [15, 43, 15, 10, 44, 16],
+
+    // 21
+    [4, 144, 116, 4, 145, 117],
+    [17, 68, 42],
+    [17, 50, 22, 6, 51, 23],
+    [19, 46, 16, 6, 47, 17],
+
+    // 22
+    [2, 139, 111, 7, 140, 112],
+    [17, 74, 46],
+    [7, 54, 24, 16, 55, 25],
+    [34, 37, 13],
+
+    // 23
+    [4, 151, 121, 5, 152, 122],
+    [4, 75, 47, 14, 76, 48],
+    [11, 54, 24, 14, 55, 25],
+    [16, 45, 15, 14, 46, 16],
+
+    // 24
+    [6, 147, 117, 4, 148, 118],
+    [6, 73, 45, 14, 74, 46],
+    [11, 54, 24, 16, 55, 25],
+    [30, 46, 16, 2, 47, 17],
+
+    // 25
+    [8, 132, 106, 4, 133, 107],
+    [8, 75, 47, 13, 76, 48],
+    [7, 54, 24, 22, 55, 25],
+    [22, 45, 15, 13, 46, 16],
+
+    // 26
+    [10, 142, 114, 2, 143, 115],
+    [19, 74, 46, 4, 75, 47],
+    [28, 50, 22, 6, 51, 23],
+    [33, 46, 16, 4, 47, 17],
+
+    // 27
+    [8, 152, 122, 4, 153, 123],
+    [22, 73, 45, 3, 74, 46],
+    [8, 53, 23, 26, 54, 24],
+    [12, 45, 15, 28, 46, 16],
+
+    // 28
+    [3, 147, 117, 10, 148, 118],
+    [3, 73, 45, 23, 74, 46],
+    [4, 54, 24, 31, 55, 25],
+    [11, 45, 15, 31, 46, 16],
+
+    // 29
+    [7, 146, 116, 7, 147, 117],
+    [21, 73, 45, 7, 74, 46],
+    [1, 53, 23, 37, 54, 24],
+    [19, 45, 15, 26, 46, 16],
+
+    // 30
+    [5, 145, 115, 10, 146, 116],
+    [19, 75, 47, 10, 76, 48],
+    [15, 54, 24, 25, 55, 25],
+    [23, 45, 15, 25, 46, 16],
+
+    // 31
+    [13, 145, 115, 3, 146, 116],
+    [2, 74, 46, 29, 75, 47],
+    [42, 54, 24, 1, 55, 25],
+    [23, 45, 15, 28, 46, 16],
+
+    // 32
+    [17, 145, 115],
+    [10, 74, 46, 23, 75, 47],
+    [10, 54, 24, 35, 55, 25],
+    [19, 45, 15, 35, 46, 16],
+
+    // 33
+    [17, 145, 115, 1, 146, 116],
+    [14, 74, 46, 21, 75, 47],
+    [29, 54, 24, 19, 55, 25],
+    [11, 45, 15, 46, 46, 16],
+
+    // 34
+    [13, 145, 115, 6, 146, 116],
+    [14, 74, 46, 23, 75, 47],
+    [44, 54, 24, 7, 55, 25],
+    [59, 46, 16, 1, 47, 17],
+
+    // 35
+    [12, 151, 121, 7, 152, 122],
+    [12, 75, 47, 26, 76, 48],
+    [39, 54, 24, 14, 55, 25],
+    [22, 45, 15, 41, 46, 16],
+
+    // 36
+    [6, 151, 121, 14, 152, 122],
+    [6, 75, 47, 34, 76, 48],
+    [46, 54, 24, 10, 55, 25],
+    [2, 45, 15, 64, 46, 16],
+
+    // 37
+    [17, 152, 122, 4, 153, 123],
+    [29, 74, 46, 14, 75, 47],
+    [49, 54, 24, 10, 55, 25],
+    [24, 45, 15, 46, 46, 16],
+
+    // 38
+    [4, 152, 122, 18, 153, 123],
+    [13, 74, 46, 32, 75, 47],
+    [48, 54, 24, 14, 55, 25],
+    [42, 45, 15, 32, 46, 16],
+
+    // 39
+    [20, 147, 117, 4, 148, 118],
+    [40, 75, 47, 7, 76, 48],
+    [43, 54, 24, 22, 55, 25],
+    [10, 45, 15, 67, 46, 16],
+
+    // 40
+    [19, 148, 118, 6, 149, 119],
+    [18, 75, 47, 31, 76, 48],
+    [34, 54, 24, 34, 55, 25],
+    [20, 45, 15, 61, 46, 16]
+  ];
+
+  QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
+
+    var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
+
+    if (rsBlock == undefined) {
+      throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
+    }
+
+    var length = rsBlock.length / 3;
+
+    var list = new Array();
+
+    for (var i = 0; i < length; i++) {
+
+      var count = rsBlock[i * 3 + 0];
+      var totalCount = rsBlock[i * 3 + 1];
+      var dataCount = rsBlock[i * 3 + 2];
+
+      for (var j = 0; j < count; j++) {
+        list.push(new QRRSBlock(totalCount, dataCount));
+      }
+    }
+
+    return list;
+  }
+
+  QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) {
+
+    switch (errorCorrectLevel) {
+      case QRErrorCorrectLevel.L:
+        return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
+      case QRErrorCorrectLevel.M:
+        return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
+      case QRErrorCorrectLevel.Q:
+        return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
+      case QRErrorCorrectLevel.H:
+        return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
+      default:
+        return undefined;
+    }
+  }
+
+  //---------------------------------------------------------------------
+  // QRBitBuffer
+  //---------------------------------------------------------------------
+
+  function QRBitBuffer() {
+    this.buffer = new Array();
+    this.length = 0;
+  }
+
+  QRBitBuffer.prototype = {
+
+    get: function (index) {
+      var bufIndex = Math.floor(index / 8);
+      return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
+    },
+
+    put: function (num, length) {
+      for (var i = 0; i < length; i++) {
+        this.putBit(((num >>> (length - i - 1)) & 1) == 1);
+      }
+    },
+
+    getLengthInBits: function () {
+      return this.length;
+    },
+
+    putBit: function (bit) {
+
+      var bufIndex = Math.floor(this.length / 8);
+      if (this.buffer.length <= bufIndex) {
+        this.buffer.push(0);
+      }
+
+      if (bit) {
+        this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
+      }
+
+      this.length++;
+    }
+  };
+
+  //---------------------------------------------------------------------
+  // Support Chinese
+  //---------------------------------------------------------------------
+  function utf16To8(text) {
+    var result = '';
+    var c;
+    for (var i = 0; i < text.length; i++) {
+      c = text.charCodeAt(i);
+      if (c >= 0x0001 && c <= 0x007F) {
+        result += text.charAt(i);
+      } else if (c > 0x07FF) {
+        result += String.fromCharCode(0xE0 | c >> 12 & 0x0F);
+        result += String.fromCharCode(0x80 | c >> 6 & 0x3F);
+        result += String.fromCharCode(0x80 | c >> 0 & 0x3F);
+      } else {
+        result += String.fromCharCode(0xC0 | c >> 6 & 0x1F);
+        result += String.fromCharCode(0x80 | c >> 0 & 0x3F);
+      }
+    }
+    return result;
+  }
+
+  uQRCode = {
+
+    errorCorrectLevel: QRErrorCorrectLevel,
+
+    defaults: {
+      size: 354,
+      margin: 0,
+      backgroundColor: '#ffffff',
+      foregroundColor: '#000000',
+      errorCorrectLevel: QRErrorCorrectLevel.H,
+      typeNumber: -1
+    },
+
+    make: function (canvas, ctx, options) {
+      var defaultOptions = {
+        x: 0,
+        y: 0,
+        text: options.text,
+        size: this.defaults.size,
+        margin: this.defaults.margin,
+        backgroundColor: this.defaults.backgroundColor,
+        foregroundColor: this.defaults.foregroundColor,
+        errorCorrectLevel: this.defaults.errorCorrectLevel,
+        typeNumber: this.defaults.typeNumber
+      };
+      if (options) {
+        for (var i in options) {
+          defaultOptions[i] = options[i];
+        }
+      }
+      options = defaultOptions;
+
+      var qrcode = new QRCode(options.typeNumber, options.errorCorrectLevel);
+      qrcode.addData(utf16To8(options.text));
+      qrcode.make();
+
+      ctx.fill
+      ctx.fillStyle = options.backgroundColor;
+      ctx.fillRect(options.x, options.y, options.size, options.size);
+
+      var tileW = (options.size - options.margin * 2) / qrcode.getModuleCount();
+      var tileH = tileW;
+
+      for (var row = 0; row < qrcode.getModuleCount(); row++) {
+        for (var col = 0; col < qrcode.getModuleCount(); col++) {
+          var style = qrcode.isDark(row, col) ? options.foregroundColor : options.backgroundColor;
+          ctx.fillStyle = style
+          var x = Math.round(col * tileW) + options.margin;
+          var y = Math.round(row * tileH) + options.margin;
+          var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW);
+          var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW);
+          ctx.fillRect(options.x + x, options.y + y, w, h);
+        }
+      }
+    }
+  }
+
+})()
+
+export default uQRCode

+ 11 - 0
pagesPoster/comps/u-draw-poster/dist/index.d.ts

@@ -0,0 +1,11 @@
+import { DrawPosterBuildOpts } from "./utils/interface";
+import DrawPoster from "./draw-poster";
+import drawQrCode from "./extends/draw-qr-code/index";
+import createFromList from './extends/create-from-list/index';
+import drawPainter from './extends/draw-painter/index';
+declare const useDrawPoster: (options: string | DrawPosterBuildOpts) => Promise<DrawPoster & import("./utils/interface").drawPosterExtends>;
+declare const useDrawPosters: (optionsAll: (string | DrawPosterBuildOpts)[]) => Promise<{
+    [key: string]: DrawPoster & import("./utils/interface").drawPosterExtends;
+}>;
+export { DrawPoster, useDrawPoster, useDrawPosters, drawQrCode, drawPainter, createFromList };
+export default DrawPoster;

+ 22 - 0
pagesPoster/comps/u-draw-poster/dist/index.js

@@ -0,0 +1,22 @@
+import * as dfucs from "./extends/draw-function/index";
+import DrawPoster from "./draw-poster";
+import drawQrCode from "./extends/draw-qr-code/index";
+import createFromList from './extends/create-from-list/index';
+import drawPainter from './extends/draw-painter/index';
+DrawPoster.useCtx(dfucs.drawImage);
+DrawPoster.useCtx(dfucs.fillWarpText);
+DrawPoster.useCtx(dfucs.roundRect);
+DrawPoster.useCtx(dfucs.fillRoundRect);
+DrawPoster.useCtx(dfucs.strokeRoundRect);
+DrawPoster.useCtx(dfucs.drawRoundImage);
+DrawPoster.useCtx(dfucs.drawImageFit);
+const useDrawPoster = async (options) => {
+    const dp = await DrawPoster.build(options);
+    return dp;
+};
+const useDrawPosters = async (optionsAll) => {
+    const dps = await DrawPoster.buildAll(optionsAll);
+    return dps;
+};
+export { DrawPoster, useDrawPoster, useDrawPosters, drawQrCode, drawPainter, createFromList };
+export default DrawPoster;

+ 7 - 0
pagesPoster/comps/u-draw-poster/dist/utils/global.d.ts

@@ -0,0 +1,7 @@
+/// <reference types="@dcloudio/types" />
+/** 当前环境类型 */
+export declare type UniPlatforms = 'app-plus' | 'app-plus-nvue' | 'h5' | 'mp-weixin' | 'mp-alipay' | 'mp-baidu' | 'mp-toutiao' | 'mp-qq' | 'mp-360' | 'mp' | 'quickapp-webview' | 'quickapp-webview-union' | 'quickapp-webview-huawei' | undefined;
+export declare const PLATFORM: UniPlatforms;
+/** 全局对象 */
+declare const _uni: UniApp.Uni;
+export default _uni;

+ 11 - 0
pagesPoster/comps/u-draw-poster/dist/utils/global.js

@@ -0,0 +1,11 @@
+var _a;
+export const PLATFORM = typeof process !== 'undefined' ? (_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.VUE_APP_PLATFORM : undefined;
+/** 全局对象 */
+const _uni = (function () {
+    if (typeof uni != "undefined")
+        return uni;
+    if (typeof wx != "undefined")
+        return wx;
+    return uni;
+})();
+export default _uni;

+ 175 - 0
pagesPoster/comps/u-draw-poster/dist/utils/interface.d.ts

@@ -0,0 +1,175 @@
+/// <reference types="@dcloudio/types" />
+import DrawPoster from "../draw-poster";
+import { ImageFitOption } from '../extends/draw-function/draw-image-fit';
+import { CreateLayerOpts, DrawRowOpt } from "../extends/create-from-list";
+import { PainterContainerOption } from "../extends/draw-painter";
+/** 绘制容器 */
+export declare type Execute = Array<() => Promise<boolean>>;
+export interface drawPosterExtends {
+    from: {
+        height: number;
+        padding: number;
+        margin: number;
+    };
+    createLayer: (afferOpts: CreateLayerOpts, rowList: DrawRowOpt[]) => number;
+    setFromOptions: (opts: Partial<{
+        height: number;
+        padding: number;
+        margin: number;
+    }>) => void;
+    gcanvas: {
+        WeexBridge: any;
+        Image: any;
+        enable: (el: any, options: {
+            bridge?: any;
+            debug?: boolean;
+            disableAutoSwap?: any;
+            disableComboCommands?: any;
+        }) => Canvas;
+    };
+    painter: (option: PainterContainerOption) => void;
+}
+/** 构建器配置 */
+export interface DrawPosterBuildOpts {
+    /** 查询选择器; 注意不需要加# */
+    selector: string;
+    /** 选取组件范围 */
+    componentThis?: any;
+    /** 绘制类型为2d绘制, 默认开启, 在微信小程序的时候动态加载 */
+    type2d?: boolean;
+    /** 是否在绘制时进行加载提示 */
+    loading?: boolean;
+    /** 当存在绘制图片时, 等待绘画完毕的时间(秒)仅App中生效
+     *
+     *  具体查看文档说明:https://github.com/TuiMao233/uni-draw-poster
+     */
+    drawImageTime?: number;
+    /** 是否开启调试模式 */
+    debugging?: boolean;
+    /** 加载提示文字 */
+    loadingText?: string;
+    /** 创建图片提示文字 */
+    createText?: string;
+    /** 是否启动gcanvas(nvue) */
+    gcanvas?: boolean;
+}
+/** 绘制换行配置 */
+export interface FillWarpTextOpts {
+    text: string;
+    maxWidth?: number;
+    lineHeight?: number;
+    layer?: number;
+    x?: number;
+    y?: number;
+    splitText?: string;
+    notFillText?: boolean;
+}
+/** 绘制二维码配置 */
+export interface DrawQrCodeOpts {
+    text: string;
+    x?: number;
+    y?: number;
+    size?: number;
+    margin?: number;
+    backgroundColor?: string;
+    foregroundColor?: string;
+}
+/** 绘制换行, 单行信息 */
+export interface FillWarpTextItemInfo {
+    text: string;
+    y: number;
+    x: number;
+}
+/** 绘制画笔 */
+export interface DrawPosterCanvasCtx extends UniApp.CanvasContext {
+    [key: string]: any;
+    createImageData: () => ImageData;
+    textAlign: CanvasTextDrawingStyles["textAlign"];
+    textBaseline: CanvasTextDrawingStyles["textBaseline"];
+    transform: CanvasTransform["transform"];
+    /** 绘制图片原型 */
+    drawImageProto: UniApp.CanvasContext['drawImage'];
+    /** 当前绘制类型 */
+    drawType: 'context' | 'type2d';
+    /** 等待绘制图片
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    drawImage(url: string, dx?: number | undefined, dy?: number | undefined, dWidth?: number | undefined, dHeigt?: number | undefined, sx?: number | undefined, sy?: number | undefined, sWidth?: number | undefined, sHeight?: number | undefined): Promise<boolean>;
+    /** 绘制圆角图片
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    drawRoundImage(url: string, x: number, y: number, w: number, h: number, r?: number): Promise<boolean>;
+    /** 绘制 Object-Fit 模式图片
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    drawImageFit(url: string, opts?: ImageFitOption): Promise<boolean>;
+    /** 绘制换行字体
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    fillWarpText(options: FillWarpTextOpts): Array<FillWarpTextItemInfo>;
+    /** 绘制圆角矩形(原型)
+     *
+     */
+    roundRect(x: number, y: number, w: number, h: number, r: number, fill?: boolean, stroke?: boolean): void;
+    /** 绘制圆角矩形(填充)
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    fillRoundRect(x: number, y: number, w: number, h: number, r: number): void;
+    /** 绘制圆角矩形(边框)
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    strokeRoundRect(x: number, y: number, w: number, h: number, r: number): void;
+    /** 绘制二维码
+     *
+     * 说明文档: https://tuimao233.gitee.io/mao-blog/my-extends/u-draw-poste
+     */
+    drawQrCode(options: DrawQrCodeOpts): void;
+}
+/** Canvas2d实例 */
+export interface Canvas {
+    width: number;
+    height: number;
+    getContext(contextType: "2d" | "webgl"): DrawPosterCanvasCtx | WebGLRenderingContext;
+    createImage(): {
+        src: string;
+        width: number;
+        height: number;
+        onload: () => void;
+        onerror: () => void;
+    };
+    requestAnimationFrame(callback: Function): number;
+    cancelAnimationFrame(requestID: number): void;
+    createImageData(): ImageData;
+    createPath2D(path: Path2D): Path2D;
+    toDataURL(type: string, encoderOptions: number): string;
+}
+/** 创建图片路径配置项 */
+export interface CreateImagePathOptions {
+    x?: number;
+    y?: number;
+    width?: number;
+    height?: number;
+    destWidth?: number;
+    destHeight?: number;
+}
+/** 绘制实例扩展配置 */
+export interface DrawPosterUseOpts {
+    name: string;
+    init?: (dp: InstanceType<typeof DrawPoster>) => void;
+    handle: (dp: InstanceType<typeof DrawPoster>, ...args: any[]) => any;
+    createImage?: (dp: InstanceType<typeof DrawPoster>) => void;
+    [key: string]: any;
+}
+/** 绘制画笔实例扩展配置 */
+export interface DrawPosterUseCtxOpts {
+    name: string;
+    init?: (canvas: Canvas, ctx: DrawPosterCanvasCtx) => void;
+    handle: (canvas: Canvas, ctx: DrawPosterCanvasCtx, ...args: any[]) => any;
+    [key: string]: any;
+}

+ 1 - 0
pagesPoster/comps/u-draw-poster/dist/utils/interface.js

@@ -0,0 +1 @@
+export {};

+ 38 - 0
pagesPoster/comps/u-draw-poster/dist/utils/object-sizing.d.ts

@@ -0,0 +1,38 @@
+export declare type ObjectFit = "contain" | "cover";
+export declare type ObjectPosition = ["left" | "center" | "right", "top" | "center" | "bottom"];
+export interface Size {
+    width: number;
+    height: number;
+}
+/**
+ * 用于计算图片的宽高比例
+ * @see https://drafts.csswg.org/css-images-3/#sizing-terms
+ *
+ * ## 名词解释
+ * ### intrinsic dimensions
+ * 图片本身的尺寸
+ *
+ * ### specified size
+ * 用户指定的元素尺寸
+ *
+ * ### concrete object size
+ * 应用了 `objectFit` 之后图片的显示尺寸
+ *
+ * ### default object size
+ */
+export declare function calculateConcreteRect(style: {
+    /** @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fit */
+    objectFit?: ObjectFit;
+    /** @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-position */
+    intrinsicPosition?: ObjectPosition;
+    specifiedPosition?: [number, number];
+}, intrinsicSize: Size, specifiedSize: Size): {
+    sx: number;
+    sy: number;
+    sw: number;
+    sh: number;
+    dx: number;
+    dy: number;
+    dw: number;
+    dh: number;
+};

+ 78 - 0
pagesPoster/comps/u-draw-poster/dist/utils/object-sizing.js

@@ -0,0 +1,78 @@
+/**
+ * 用于计算图片的宽高比例
+ * @see https://drafts.csswg.org/css-images-3/#sizing-terms
+ *
+ * ## 名词解释
+ * ### intrinsic dimensions
+ * 图片本身的尺寸
+ *
+ * ### specified size
+ * 用户指定的元素尺寸
+ *
+ * ### concrete object size
+ * 应用了 `objectFit` 之后图片的显示尺寸
+ *
+ * ### default object size
+ */
+export function calculateConcreteRect(style, intrinsicSize, specifiedSize) {
+    var _a, _b;
+    const isContain = style.objectFit === 'contain';
+    const specifiedPosition = style.specifiedPosition || [0, 0];
+    // ratio 越大表示矩形越"扁"
+    let intrinsicRatio = intrinsicSize.width / intrinsicSize.height;
+    let specifiedRatio = specifiedSize.width / specifiedSize.height;
+    /** 图片原始尺寸与最终尺寸之比 */
+    let concreteScale = 1;
+    if (intrinsicRatio > specifiedRatio && style.objectFit == "contain" ||
+        intrinsicRatio <= specifiedRatio && style.objectFit == "cover")
+        // 图片较"胖"时完整显示图片,图片较"瘦"时完全覆盖容器
+        // 这两种情况下有 concreteRect.width = specifiedSize.width
+        // 因为 concreteRect.width = intrinsicSize.width * concreteScale
+        // 所以:
+        concreteScale = specifiedSize.width / intrinsicSize.width;
+    else if (intrinsicRatio > specifiedRatio && style.objectFit == "cover" ||
+        intrinsicRatio <= specifiedRatio && style.objectFit == "contain")
+        // 图片较"瘦"时完整显示图片,图片较"胖"时完全覆盖容器
+        // 这两种情况下有 concreteRect.height = specifiedSize.height
+        // 因为 concreteRect.height = intrinsicSize.height * concreteScale
+        // 所以:
+        concreteScale = specifiedSize.height / intrinsicSize.height;
+    else
+        throw new Error("Unkonwn concreteScale");
+    let concreteRectWidth = intrinsicSize.width * concreteScale;
+    let concreteRectHeight = intrinsicSize.height * concreteScale;
+    // 这里可以把 left top 的计算想象成投影
+    let xRelativeOrigin = { left: 0, center: .5, right: 1 }[((_a = style.intrinsicPosition) === null || _a === void 0 ? void 0 : _a[0]) || "center"];
+    let yRelativeOrigin = { top: 0, center: .5, bottom: 1 }[((_b = style.intrinsicPosition) === null || _b === void 0 ? void 0 : _b[1]) || "center"];
+    let concreteRectLeft = (specifiedSize.width - concreteRectWidth) * xRelativeOrigin;
+    let concreteRectTop = (specifiedSize.height - concreteRectHeight) * yRelativeOrigin;
+    if (isContain) {
+        concreteRectLeft += specifiedPosition[0];
+        concreteRectTop += specifiedPosition[1];
+    }
+    // 这里有两个坐标系,一个是 specified (dist) 的坐标系,一个是 intrinsic (src) 的坐标系
+    // 这里将两个坐标系的点位置进行变换
+    // 例: 带入 x=0, y=0, 得到的结果就是 specifiedRect 的左上角在 intrinsic 坐标系下的坐标位置
+    // 在 specified 坐标系下, intrinsic 的零点在 (concreteRectLeft, concreteRectTop), 缩放为 concreteScale
+    // 所以有 x_dist = x_src * concreteScale + concreteRectLeft
+    //        y_dist = y_src * concreteScale + concreteRectTop
+    let dist2src = (distX, distY) => [
+        /* srcX = */ (distX - concreteRectLeft) / concreteScale,
+        /* srcY = */ (distY - concreteRectTop) / concreteScale
+    ];
+    let [srcLeft, srcTop] = dist2src(0, 0);
+    // srcRight =  图片 specified 框右边在 src 坐标系下的 x 坐标
+    // srcBottom = 图片 specified 框下边在 src 坐标系下的 y 坐标
+    let [srcRight, srcBottom] = dist2src(specifiedSize.width, specifiedSize.height);
+    // 这里要对 src 和 disc 两个框进行约束
+    return {
+        sx: Math.max(srcLeft, 0),
+        sy: Math.max(srcTop, 0),
+        sw: Math.min(srcRight - srcLeft, intrinsicSize.width),
+        sh: Math.min(srcBottom - srcTop, intrinsicSize.height),
+        dx: isContain ? Math.max(concreteRectLeft, 0) : specifiedPosition[0],
+        dy: isContain ? Math.max(concreteRectTop, 0) : specifiedPosition[1],
+        dw: Math.min(concreteRectWidth, specifiedSize.width),
+        dh: Math.min(concreteRectHeight, specifiedSize.height)
+    };
+}

+ 20 - 0
pagesPoster/comps/u-draw-poster/dist/utils/utils.d.ts

@@ -0,0 +1,20 @@
+import { DrawPosterBuildOpts } from "./interface";
+/** 是否是base64本地地址 */
+export declare const isBaseUrl: (str: string) => boolean;
+/** 是否是小程序本地地址 */
+export declare const isTmpUrl: (str: string) => boolean;
+/** 是否是网络地址 */
+export declare const isNetworkUrl: (str: string) => boolean;
+/** 对象target挂载到对象current */
+export declare const extendMount: (current: Record<any, any>, target: Record<any, any>, handle?: (extend: Function, target?: Record<any, any> | undefined) => any) => void;
+/** 处理构建配置 */
+export declare const handleBuildOpts: (options: string | DrawPosterBuildOpts) => {
+    selector: string;
+    componentThis: any;
+    type2d: boolean;
+    loading: boolean;
+    debugging: boolean;
+    loadingText: string;
+    createText: string;
+    gcanvas: boolean;
+};

+ 49 - 0
pagesPoster/comps/u-draw-poster/dist/utils/utils.js

@@ -0,0 +1,49 @@
+import { PLATFORM } from "./global";
+/** 是否是base64本地地址 */
+export const isBaseUrl = (str) => {
+    return /^\s*data:(?:[a-z]+\/[a-z0-9-+.]+(?:;[a-z-]+=[a-z0-9-]+)?)?(?:;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i.test(str);
+};
+/** 是否是小程序本地地址 */
+export const isTmpUrl = (str) => {
+    return /http:\/\/temp\/wx/.test(str);
+};
+/** 是否是网络地址 */
+export const isNetworkUrl = (str) => {
+    return /^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?$/.test(str);
+};
+/** 对象target挂载到对象current */
+export const extendMount = (current, target, handle = (extend, target) => undefined) => {
+    for (const key in target) {
+        current[key] = handle(target[key].handle, target[key]) || target[key].handle;
+    }
+};
+/** 处理构建配置 */
+export const handleBuildOpts = (options) => {
+    let defaultOpts = {
+        selector: '',
+        componentThis: undefined,
+        type2d: true,
+        loading: false,
+        debugging: false,
+        loadingText: '绘制海报中...',
+        createText: '生成图片中...',
+        gcanvas: false
+    };
+    if (typeof options === "string") {
+        defaultOpts.selector = options;
+    }
+    else {
+        defaultOpts = Object.assign(Object.assign({}, defaultOpts), options);
+    }
+    const oldSelector = defaultOpts.selector;
+    if (PLATFORM === 'mp-weixin' && defaultOpts.type2d) {
+        defaultOpts.selector = '#' + defaultOpts.selector;
+    }
+    if (!PLATFORM) {
+        console.error('注意! draw-poster未开启uni条件编译! 当环境是微信小程序将不会动态切换为type2d模式');
+        console.error(`请在vue.config.js中的transpileDependencies中添加'uni-draw-poster'`);
+        console.error(`或者可以在选择器字符串前缀中添加#来切换为type2d绘制`);
+        defaultOpts.selector = oldSelector;
+    }
+    return defaultOpts;
+};

+ 3 - 0
pagesPoster/comps/u-draw-poster/dist/utils/wx-utils.d.ts

@@ -0,0 +1,3 @@
+import { Canvas } from "./interface";
+export declare const downloadImgUrl: (url: string) => Promise<string>;
+export declare const getCanvas2dContext: (selector: string, componentThis?: any) => Promise<Canvas | {}>;

+ 37 - 0
pagesPoster/comps/u-draw-poster/dist/utils/wx-utils.js

@@ -0,0 +1,37 @@
+/*
+ * @Author: Mr.Mao
+ * @LastEditors: Mr.Mao
+ * @Date: 2020-10-12 08:49:27
+ * @LastEditTime: 2020-12-09 13:54:10
+ * @Description:
+ * @任何一个傻子都能写出让电脑能懂的代码,而只有好的程序员可以写出让人能看懂的代码
+ */
+import uni from "./global";
+import { isBaseUrl, isNetworkUrl, isTmpUrl } from './utils';
+// 下载指定地址图片, 如果不符合下载图片, 则直接返回
+export const downloadImgUrl = (url) => {
+    const isLocalFile = isBaseUrl(url) || isTmpUrl(url) || !isNetworkUrl(url);
+    return new Promise((resolve, reject) => {
+        if (isLocalFile) {
+            return resolve(url);
+        }
+        uni.downloadFile({
+            url,
+            success: (res) => resolve(res.tempFilePath),
+            fail: reject
+        });
+    });
+};
+// 获取当前指定 node 节点
+export const getCanvas2dContext = (selector, componentThis) => {
+    return new Promise(resolve => {
+        const query = (componentThis ?
+            uni.createSelectorQuery().in(componentThis) :
+            uni.createSelectorQuery());
+        query.select(selector)
+            .fields({ node: true }, res => {
+            const node = res === null || res === void 0 ? void 0 : res.node;
+            resolve(node || {});
+        }).exec();
+    });
+};

+ 236 - 0
pagesPoster/comps/u-draw-poster/lib/draw-poster.ts

@@ -0,0 +1,236 @@
+import uni from "./utils/global"
+import {
+  Canvas, Execute,
+  DrawPosterCanvasCtx,
+  CreateImagePathOptions,
+  DrawPosterBuildOpts,
+  DrawPosterUseOpts,
+  drawPosterExtends,
+  DrawPosterUseCtxOpts
+} from "./utils/interface"
+import { handleBuildOpts, extendMount } from "./utils/utils"
+import { getCanvas2dContext } from "./utils/wx-utils"
+
+// 实例类型添加上扩展类型
+type DrawPosterInstanceType = InstanceType<typeof DrawPoster> & drawPosterExtends
+
+// 扩展挂载储存
+let drawPosterExtend: Record<any, any> = {}
+let drawCtxPosterExtend: Record<any, any> = {}
+
+class DrawPoster {
+  [key: string]: any
+  private executeOnions = [] as Execute
+  private stopStatus = false
+  private drawType: 'type2d' | 'context'
+
+  /** 构建器, 构建返回当前实例, 并挂载多个方法 */
+  constructor(
+    public canvas: Canvas,
+    public ctx: DrawPosterCanvasCtx,
+    public canvasId: string,
+    public loading: boolean,
+    public debugging: boolean,
+    public loadingText: string,
+    public createText: string,
+    tips: boolean,
+  ) {
+    if (!canvas || !ctx || !canvasId) {
+      throw new Error("DrawPoster Error: Use DrawPoster.build(string | ops) to build drawPoster instance objects")
+    }
+
+    // 判断当前绘制类型
+    ctx.drawType = this.drawType = (ctx.draw) ? 'context' : 'type2d'
+
+    // 挂载全局实例, 绘画扩展
+    extendMount(this.ctx, drawCtxPosterExtend, (extend, target) => {
+      target?.init?.(this.canvas, this.ctx)
+      return (...args: any[]) => extend(this.canvas, this.ctx, ...args)
+    })
+    extendMount(this, drawPosterExtend, (extend, target) => {
+      target?.init?.(this)
+      return (...args: any[]) => extend(this, ...args)
+    })
+
+    // 当离开页面时, 自动调用停止绘画
+    const _this = this
+    const pages = getCurrentPages()
+    const page = pages[pages.length - 1] as Record<any, any>
+    // 查询标识, 不存在, 在替换页面卸载回调, 避免产生死循环
+    if (!page?.onUnload?.identification) {
+      page.oldOnUnload = page.onUnload
+      page.onUnload = function () {
+        _this?.stop()
+        page.oldOnUnload()
+      }
+      page.onUnload.identification = true
+    }
+    tips && this.debuggingLog('构建完成', {canvas, ctx, selector: canvasId}, '#19be6b')
+  }
+  /** 提示器, 传入消息与数据 */
+  private debuggingLog = (message: string, data?: any, color = "#3489fd") => {
+    if (this.debugging) {
+      if (data) {
+        console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`, data)
+      } else {
+        console.log(`%c${this.canvasId} -> ${message}`, `color: ${color}`)
+      }
+    }
+  }
+
+  /** 传入挂载配置对象, 添加扩展方法 */
+  static use = (opts: DrawPosterUseOpts) => {
+    if (opts.name) drawPosterExtend[opts.name] = opts
+  }
+
+  /** 传入挂载配置对象, 添加绘画扩展方法 */
+  static useCtx = (opts: DrawPosterUseCtxOpts) => {
+    if (opts.name) drawCtxPosterExtend[opts.name] = opts
+  }
+
+  /** 构建绘制海报矩形方法, 传入canvas选择器或配置对象, 返回绘制对象 */
+  static build = async (options: string | DrawPosterBuildOpts, tips = true) => {
+    const config = handleBuildOpts(options)
+
+    // 初始化监测当前页面绘制对象
+    const pages = getCurrentPages()
+    const page = pages[pages.length - 1] as Record<string, DrawPosterInstanceType>
+    const gcanvas: drawPosterExtends['gcanvas'] = DrawPoster.prototype['gcanvas']
+    if (page[config.selector + '__dp']) {
+      return page[config.selector + '__dp']
+    }
+
+    if (config.gcanvas) {
+      if (!gcanvas)
+        console.error('--- 当前未引入gcanvas扩展, 将自动切换为普通 canvas ---')
+      else
+        gcanvas.enable(config.componentThis?.$refs?.[config.selector], {
+          bridge: gcanvas.WeexBridge
+        })
+    }
+    // 获取canvas实例
+    const canvas = config.gcanvas && gcanvas ?
+      gcanvas.enable(config.componentThis?.$refs?.[config.selector], {
+        bridge: gcanvas.WeexBridge
+      }) :
+      await getCanvas2dContext(config.selector, config.componentThis) as Canvas
+
+    const ctx = (
+      canvas.getContext?.("2d") || uni.createCanvasContext(config.selector, config.componentThis)
+    ) as DrawPosterCanvasCtx
+
+
+    const dp = new DrawPoster(
+      canvas, ctx,
+      config.selector,
+      config.loading,
+      config.debugging,
+      config.loadingText,
+      config.createText,
+      tips
+    )
+    // 储存当前绘制对象
+    page[config.selector + '__dp'] = dp as DrawPosterInstanceType;
+    return page[config.selector + '__dp']
+  }
+
+  /** 构建多个绘制海报矩形方法, 传入选择器或配置对象的数组, 返回多个绘制对象 */
+  static buildAll = async (optionsAll: (string | DrawPosterBuildOpts)[]) => {
+    const dpsArr = await Promise.all(optionsAll.map(async options => {
+      return await DrawPoster.build(options, false)
+    }))
+    const dpsObj = {} as { [key: string]: typeof dpsArr[0] }
+    dpsArr.forEach(dp => dpsObj[dp.canvasId] = dp)
+    console.log("%cdraw-poster 构建完成:", "#E3712A", dpsObj)
+    return dpsObj
+  }
+
+  /** 绘制器, 接收执行器函数, 添加到绘制容器中 */
+  public draw = (execute: (ctx: DrawPosterCanvasCtx) => Promise<any> | void) => {
+    const length = this.executeOnions.length
+    this.executeOnions.push(async () => {
+      try {
+        this.ctx.save()
+        await execute(this.ctx)
+        this.ctx.restore()
+        return true
+      } catch (error) {
+        const isOutError = error?.message?.search?.(`'nodeId' of undefined`) >= 0
+        !isOutError && console.error(`${this.canvasId} -> 绘画栈(${length}),绘制错误:`, error)
+        return false
+      }
+    })
+  }
+
+  /** 等待创建绘画, 成功后清空绘制器容器 */
+  public awaitCreate = async (): Promise<boolean[]> => {
+    this.debuggingLog('绘制海报中...')
+    this.loading && uni.showLoading({ title: this.loadingText })
+
+    const tips: Array<boolean> = []
+    for (let i = 0; i < this.executeOnions.length; i++) {
+      const execute = this.executeOnions[i]
+      tips.push(await execute())
+    }
+    this.executeOnions = []
+    this.debuggingLog('绘制状况', tips)
+
+    // 当前绘制为 type2 绘制
+    if (this.drawType === 'type2d') {
+      this.loading && uni.hideLoading()
+      return tips
+    }
+    // 当前绘制为 context 绘制
+    return await new Promise((resolve) => {
+      this.ctx.draw(true, () => {
+        resolve(tips)
+        this.loading && uni.hideLoading()
+      })
+    })
+  }
+
+  /** 创建canvas本地地址 @returns {string} 本地地址 */
+  public createImagePath = async (baseOptions: CreateImagePathOptions = {}): Promise<string> => {
+    const { canvas, canvasId, executeOnions, awaitCreate } = this
+    executeOnions.length && await awaitCreate()
+    // 如果当前为停止状态
+    if (this.stopStatus) {
+      this.stopStatus = false
+      return '---stop createImagePath---'
+    }
+    this.loading && uni.showLoading({ title: this.createText })
+    const options: WechatMiniprogram.CanvasToTempFilePathOption = {
+      // x: 0, y: 0,
+      // width: canvas.width,
+      // height: canvas.height,
+      // destWidth: canvas.width * 2,
+      // destHeight: canvas.height * 2,
+      ...baseOptions
+    };
+    if (this.drawType === 'context')
+      options.canvasId = canvasId
+    if (this.drawType === 'type2d')
+      options.canvas = canvas
+    return new Promise((resolve, reject) => {
+      options.success = (res) => {
+        resolve(res.tempFilePath)
+        this.loading && uni.hideLoading();
+        this.debuggingLog('绘制成功 🎉', res, '#19be6b')
+      }
+      options.fail = (err) => {
+        reject(err)
+        this.loading && uni.hideLoading();
+        this.debuggingLog('绘制失败 🌟', err, '#fa3534')
+      }
+      uni.canvasToTempFilePath(options as any)
+    })
+  }
+
+  /** 停止当前绘画, 调用则停止当前绘画堆栈的绘画 */
+  public stop = () => {
+    this.executeOnions = []
+    this.stopStatus = true
+  }
+}
+
+export default DrawPoster;

+ 183 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-from-list/index.ts

@@ -0,0 +1,183 @@
+import { DrawPosterUseOpts } from '../../utils/interface'
+
+export interface CreateLayerOpts {
+  background?: string
+  self?: boolean
+  line?: boolean
+  lineHeight?: number
+}
+export interface DrawRowOpt {
+  text?: string
+  font?: string
+  color?: string
+  center?: boolean
+  width?: number
+}
+
+/** 绘制表单扩展方法 */
+export default {
+  name: 'createLayer',
+  init: (dp) => {
+    dp.from = {
+      height: 0,
+      padding: 8,
+      margin: 0
+    }
+    dp.setFromOptions = (opts: Record<any, any>) => {
+      if (typeof opts.height !== 'undefined') {
+        dp.from.height = opts.height
+      }
+      if (typeof opts.margin !== 'undefined') {
+        dp.from.margin = opts.margin
+      }
+      if (typeof opts.padding !== 'undefined') {
+        dp.from.padding = opts.padding
+      }
+    }
+  },
+  handle: (dp, afferOpts: CreateLayerOpts, rowList: DrawRowOpt[]) => {
+    // 当前配置(头部偏移量, 列内边距, 表单外边距)
+    const height = dp.from.height as number
+    const margin = dp.from.margin as number
+    const padding = dp.from.padding as number
+    // 当前层宽度
+    const containerWidth = dp.canvas.width - (margin * 2)
+    // 基本层配置
+    const opts = {
+      background: "#fff",
+      columnY: height || margin,
+      self: true,
+      line: true,
+      lineHeight: 0,
+      border: true,
+      ...afferOpts
+    }
+    // 基本列配置
+    const baseRowOpts = {
+      text: "",
+      font: "24px sans-serif",
+      color: "#333",
+      center: false,
+      width: 0,
+    }
+    // 累计最高的列为标准定义为层高度
+    let maxRowHeight = 0
+    // 累计固定栅格列偏移量
+    let columnOffsetX = margin
+    // 创建行绘制任务
+    const drawLayerInfos = rowList.map((afferRowOpts = {}, index) => {
+      const rowOpts = {
+        ...baseRowOpts,
+        ...afferRowOpts
+      }
+      let columnX = 0 // 每列的X轴
+      let columnW = 0 // 每列的宽度
+      let fontOffsetX = 0 // 字体偏移X轴
+      let fontMaxWidth = 100 // 字体最大宽度
+      opts.lineHeight = opts.lineHeight || Number(rowOpts.font.replace(/[^0-9.]/g, ""))
+      if (opts.self) {
+        // 自适应栅格格子计算
+        columnX = containerWidth - (containerWidth / (index + 1)) + margin
+        columnW = containerWidth / rowList.length
+        if (columnX > 0 && columnX < containerWidth - columnW) {
+          columnX = (columnW * index) + margin
+        }
+        fontOffsetX = rowOpts.center ? columnX + (columnW / 2) : columnX + padding
+        fontMaxWidth = columnW - (padding * 3)
+      }
+      if (!opts.self) {
+        // 固定栅格格子计算
+        columnW = rowOpts.width
+        columnX = columnOffsetX
+        fontMaxWidth = columnW - (padding * 3)
+        fontOffsetX = rowOpts.center ? columnOffsetX + (rowOpts.width / 2) : columnOffsetX + padding
+        columnOffsetX += rowOpts.width
+      }
+      dp.ctx.font = rowOpts.font
+      const drawFontInfos = dp.ctx.fillWarpText({
+        text: rowOpts.text,
+        maxWidth: fontMaxWidth,
+        lineHeight: opts.lineHeight,
+        x: fontOffsetX,
+        y: opts.columnY,
+        layer: 10,
+        notFillText: true
+      })
+      // 当前行的高度
+      const rowHeight = (opts.lineHeight * drawFontInfos.length) + (padding * 3)
+      // 若该列高度大于累计高度, 将累计高度替换
+      if (rowHeight > maxRowHeight) {
+        maxRowHeight = rowHeight
+      }
+      return {
+        font: rowOpts.font,
+        center: rowOpts.center,
+        color: rowOpts.color,
+        border: opts.border,
+        background: opts.background,
+        lineHeight: opts.lineHeight,
+        line: opts.line,
+        drawFontInfos,
+        columnY: opts.columnY,
+        columnX,
+        columnW,
+        columnH: maxRowHeight,
+        margin,
+        padding
+      }
+    })
+
+    // 将行绘制任务添加至绘制容器中
+    dp.draw((ctx) => drawLayerInfos.forEach((rowOpts, index) => {
+      ctx.font = rowOpts.font
+      ctx.fillStyle = rowOpts.background
+      ctx.strokeStyle = "#333"
+      ctx.textBaseline = "middle"
+      ctx.textAlign = 'left'
+      if (rowOpts.center) {
+        ctx.textAlign = "center"
+      }
+      ctx.fillRect(
+        rowOpts.columnX,
+        rowOpts.columnY,
+        rowOpts.columnW,
+        rowOpts.columnH
+      )
+      if (rowOpts.border) {
+        dp.ctx.strokeRect(
+          margin,
+          rowOpts.columnY,
+          dp.canvas.width - margin,
+          maxRowHeight
+        )
+      }
+      if (rowOpts.line && rowOpts.columnX !== margin) {
+        ctx.moveTo(rowOpts.columnX, rowOpts.columnY)
+        ctx.lineTo(rowOpts.columnX, rowOpts.columnY + rowOpts.columnH)
+        ctx.stroke()
+        ctx.beginPath()
+      }
+      ctx.fillStyle = rowOpts.color
+      rowOpts.drawFontInfos.forEach(fontInfo => {
+        // 计算每行字体绘制y轴长度
+        // y(当前列置顶轴) + (rowOpts.columnH(当前列最高长度) / 2) - (((总列数-1) * 行高) / 2)
+        const textTotal = rowOpts.drawFontInfos.length - 1
+        const textMiddleY = (textTotal * rowOpts.lineHeight) / 2
+        let fontOffsetY = fontInfo.y + (rowOpts.columnH / 2)
+        fontOffsetY -= textMiddleY
+        ctx.fillText(
+          fontInfo.text,
+          fontInfo.x,
+          fontOffsetY
+        )
+      })
+    }))
+    if (opts.columnY === 0 || opts.columnY === margin) {
+      maxRowHeight += margin
+    }
+
+    // 叠加高度
+    dp.from.height += maxRowHeight
+    return maxRowHeight
+  },
+} as DrawPosterUseOpts

+ 241 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/bridge/bridge-weex.js

@@ -0,0 +1,241 @@
+const isWeex = typeof WXEnvironment !== 'undefined';
+const isWeexIOS = isWeex && /ios/i.test(WXEnvironment.platform);
+const isWeexAndroid = isWeex && !isWeexIOS;
+
+import GLmethod from '../context-webgl/GLmethod';
+
+const GCanvasModule =
+    (typeof weex !== 'undefined' && weex.requireModule) ? (weex.requireModule('gcanvas')) :
+        (typeof __weex_require__ !== 'undefined') ? (__weex_require__('@weex-module/gcanvas')) : {};
+
+let isDebugging = false;
+
+let isComboDisabled = false;
+
+const logCommand = (function () {
+    const methodQuery = [];
+    Object.keys(GLmethod).forEach(key => {
+        methodQuery[GLmethod[key]] = key;
+    })
+    const queryMethod = (id) => {
+        return methodQuery[parseInt(id)] || 'NotFoundMethod';
+    }
+    const logCommand = (id, cmds) => {
+        const mId = cmds.split(',')[0];
+        const mName = queryMethod(mId);
+        console.log(`=== callNative - componentId:${id}; method: ${mName}; cmds: ${cmds}`);
+    }
+    return logCommand;
+})();
+
+function joinArray(arr, sep) {
+    let res = '';
+    for (let i = 0; i < arr.length; i++) {
+        if (i !== 0) {
+            res += sep;
+        }
+        res += arr[i];
+    }
+    return res;
+}
+
+const commandsCache = {}
+
+const GBridge = {
+
+    callEnable: (ref, configArray) => {
+
+        commandsCache[ref] = [];
+
+        return GCanvasModule.enable({
+            componentId: ref,
+            config: configArray
+        });
+    },
+
+    callEnableDebug: () => {
+        isDebugging = true;
+    },
+
+    callEnableDisableCombo: () => {
+        isComboDisabled = true;
+    },
+
+    callSetContextType: function (componentId, context_type) {
+        GCanvasModule.setContextType(context_type, componentId);
+    },
+
+    callReset: function(id){
+        GCanvasModule.resetComponent && canvasModule.resetComponent(componentId);
+    },
+
+    render: isWeexIOS ? function (componentId) {
+        return GCanvasModule.extendCallNative({
+            contextId: componentId,
+            type: 0x60000001
+        });
+    } : function (componentId) {
+        return callGCanvasLinkNative(componentId, 0x60000001, 'render');
+    },
+
+    render2d: isWeexIOS ? function (componentId, commands, callback) {
+
+        if (isDebugging) {
+            console.log('>>> >>> render2d ===');
+            console.log('>>> commands: ' + commands);
+        }
+		
+        GCanvasModule.render([commands, callback?true:false], componentId, callback);
+
+    } : function (componentId, commands,callback) {
+
+        if (isDebugging) {
+            console.log('>>> >>> render2d ===');
+            console.log('>>> commands: ' + commands);
+        }
+
+        callGCanvasLinkNative(componentId, 0x20000001, commands);
+		if(callback){
+		callback();
+		}
+    },
+
+    callExtendCallNative: isWeexIOS ? function (componentId, cmdArgs) {
+
+        throw 'should not be here anymore ' + cmdArgs;
+
+    } : function (componentId, cmdArgs) {
+
+        throw 'should not be here anymore ' + cmdArgs;
+
+    },
+
+
+    flushNative: isWeexIOS ? function (componentId) {
+
+        const cmdArgs = joinArray(commandsCache[componentId], ';');
+        commandsCache[componentId] = [];
+
+        if (isDebugging) {
+            console.log('>>> >>> flush native ===');
+            console.log('>>> commands: ' + cmdArgs);
+        }
+
+        const result = GCanvasModule.extendCallNative({
+            "contextId": componentId,
+            "type": 0x60000000,
+            "args": cmdArgs
+        });
+
+        const res = result && result.result;
+
+        if (isDebugging) {
+            console.log('>>> result: ' + res);
+        }
+
+        return res;
+
+    } : function (componentId) {
+
+        const cmdArgs = joinArray(commandsCache[componentId], ';');
+        commandsCache[componentId] = [];
+
+        if (isDebugging) {
+            console.log('>>> >>> flush native ===');
+            console.log('>>> commands: ' + cmdArgs);
+        }
+
+        const result = callGCanvasLinkNative(componentId, 0x60000000, cmdArgs);
+
+        if (isDebugging) {
+            console.log('>>> result: ' + result);
+        }
+
+        return result;
+    },
+
+    callNative: function (componentId, cmdArgs, cache) {
+
+        if (isDebugging) {
+            logCommand(componentId, cmdArgs);
+        }
+
+        commandsCache[componentId].push(cmdArgs);
+
+        if (!cache || isComboDisabled) {
+            return GBridge.flushNative(componentId);
+        } else {
+            return undefined;
+        }
+    },
+
+    texImage2D(componentId, ...args) {
+        if (isWeexIOS) {
+            if (args.length === 6) {
+                const [target, level, internalformat, format, type, image] = args;
+                GBridge.callNative(
+                    componentId,
+                    GLmethod.texImage2D + ',' + 6 + ',' + target + ',' + level + ',' + internalformat + ',' + format + ',' + type + ',' + image.src
+                )
+            } else if (args.length === 9) {
+                const [target, level, internalformat, width, height, border, format, type, image] = args;
+                GBridge.callNative(
+                    componentId,
+                    GLmethod.texImage2D + ',' + 9 + ',' + target + ',' + level + ',' + internalformat + ',' + width + ',' + height + ',' + border + ',' +
+                    + format + ',' + type + ',' + (image ? image.src : 0)
+                )
+            }
+        } else if (isWeexAndroid) {
+            if (args.length === 6) {
+                const [target, level, internalformat, format, type, image] = args;
+                GCanvasModule.texImage2D(componentId, target, level, internalformat, format, type, image.src);
+            } else if (args.length === 9) {
+                const [target, level, internalformat, width, height, border, format, type, image] = args;
+                GCanvasModule.texImage2D(componentId, target, level, internalformat, width, height, border, format, type, (image ? image.src : 0));
+            }
+        }
+    },
+
+    texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image) {
+        if (isWeexIOS) {
+            if (arguments.length === 8) {
+                GBridge.callNative(
+                    componentId,
+                    GLmethod.texSubImage2D + ',' + 6 + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset, + ',' + format + ',' + type + ',' + image.src
+                )
+            }
+        } else if (isWeexAndroid) {
+            GCanvasModule.texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image.src);
+        }
+    },
+
+    bindImageTexture(componentId, src, imageId) {
+        GCanvasModule.bindImageTexture([src, imageId], componentId);
+    },
+
+    perloadImage([url, id], callback) {
+        GCanvasModule.preLoadImage([url, id], function (image) {
+            image.url = url;
+            image.id = id;
+            callback(image);
+        });
+    },
+	
+	measureText(text, fontStyle, componentId) {
+	    return GCanvasModule.measureText([text, fontStyle], componentId);
+	},
+	
+	getImageData (componentId, x, y, w, h, callback) {
+		GCanvasModule.getImageData([x, y,w,h],componentId,callback);
+	},
+	
+	putImageData (componentId, data, x, y, w, h, callback) {
+		GCanvasModule.putImageData([x, y,w,h,data],componentId,callback);
+	},
+	
+	toTempFilePath(componentId, x, y, width, height, destWidth, destHeight, fileType, quality, callback){ 
+		GCanvasModule.toTempFilePath([x, y, width,height, destWidth, destHeight, fileType, quality], componentId, callback);
+	}
+}
+
+export default GBridge;

+ 18 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/FillStyleLinearGradient.js

@@ -0,0 +1,18 @@
+class FillStyleLinearGradient {
+
+    constructor(x0, y0, x1, y1) {
+        this._start_pos = { _x: x0, _y: y0 };
+        this._end_pos = { _x: x1, _y: y1 };
+        this._stop_count = 0;
+        this._stops = [0, 0, 0, 0, 0];
+    }
+
+    addColorStop = function (pos, color) {
+        if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
+            this._stops[this._stop_count] = { _pos: pos, _color: color };
+            this._stop_count++;
+        }
+    }
+}
+
+export default FillStyleLinearGradient;

+ 8 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/FillStylePattern.js

@@ -0,0 +1,8 @@
+class FillStylePattern {
+    constructor(img, pattern) {
+        this._style = pattern;
+        this._img = img;
+    }
+}
+
+export default FillStylePattern;

+ 17 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/FillStyleRadialGradient.js

@@ -0,0 +1,17 @@
+class FillStyleRadialGradient {
+    constructor(x0, y0, r0, x1, y1, r1) {
+        this._start_pos = { _x: x0, _y: y0, _r: r0 };
+        this._end_pos = { _x: x1, _y: y1, _r: r1 };
+        this._stop_count = 0;
+        this._stops = [0, 0, 0, 0, 0];
+    }
+
+    addColorStop(pos, color) {
+        if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
+            this._stops[this._stop_count] = { _pos: pos, _color: color };
+            this._stop_count++;
+        }
+    }
+}
+
+export default FillStyleRadialGradient;

+ 666 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-2d/RenderingContext.js

@@ -0,0 +1,666 @@
+import FillStylePattern from './FillStylePattern';
+import FillStyleLinearGradient from './FillStyleLinearGradient';
+import FillStyleRadialGradient from './FillStyleRadialGradient';
+import GImage from '../env/image.js';
+import {
+	ArrayBufferToBase64,
+	Base64ToUint8ClampedArray
+} from '../env/tool.js';
+
+export default class CanvasRenderingContext2D {
+
+	_drawCommands = '';
+
+	_globalAlpha = 1.0;
+
+	_fillStyle = 'rgb(0,0,0)';
+	_strokeStyle = 'rgb(0,0,0)';
+
+	_lineWidth = 1;
+	_lineCap = 'butt';
+	_lineJoin = 'miter';
+
+	_miterLimit = 10;
+
+	_globalCompositeOperation = 'source-over';
+
+	_textAlign = 'start';
+	_textBaseline = 'alphabetic';
+
+	_font = '10px sans-serif';
+
+	_savedGlobalAlpha = [];
+
+	timer = null;
+	componentId = null;
+
+	_notCommitDrawImageCache = [];
+	_needRedrawImageCache = [];
+	_redrawCommands = '';
+	_autoSaveContext = true;
+	// _imageMap = new GHashMap();
+	// _textureMap = new GHashMap();
+
+	constructor() {
+		this.className = 'CanvasRenderingContext2D';
+		//this.save()
+	}
+
+	setFillStyle(value) {
+		this.fillStyle = value;
+	}
+
+	set fillStyle(value) {
+		this._fillStyle = value;
+
+		if (typeof(value) == 'string') {
+			this._drawCommands = this._drawCommands.concat("F" + value + ";");
+		} else if (value instanceof FillStylePattern) {
+			const image = value._img;
+			if (!image.complete) {
+				image.onload = () => {
+					var index = this._needRedrawImageCache.indexOf(image);
+					if (index > -1) {
+						this._needRedrawImageCache.splice(index, 1);
+						CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
+						this._redrawflush(true);
+					}
+				}
+				this._notCommitDrawImageCache.push(image);
+			} else {
+				CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
+			}
+
+			//CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
+			this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
+		} else if (value instanceof FillStyleLinearGradient) {
+			var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
+				value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
+				value._stop_count;
+			for (var i = 0; i < value._stop_count; ++i) {
+				command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
+			}
+			this._drawCommands = this._drawCommands.concat(command + ";");
+		} else if (value instanceof FillStyleRadialGradient) {
+			var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
+				.toFixed(2) + "," +
+				value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + value._end_pos._r.toFixed(2) + "," +
+				value._stop_count;
+			for (var i = 0; i < value._stop_count; ++i) {
+				command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
+			}
+			this._drawCommands = this._drawCommands.concat(command + ";");
+		}
+	}
+
+	get fillStyle() {
+		return this._fillStyle;
+	}
+
+	get globalAlpha() {
+		return this._globalAlpha;
+	}
+
+	setGlobalAlpha(value) {
+		this.globalAlpha = value;
+	}
+
+	set globalAlpha(value) {
+		this._globalAlpha = value;
+		this._drawCommands = this._drawCommands.concat("a" + value.toFixed(2) + ";");
+	}
+
+
+	get strokeStyle() {
+		return this._strokeStyle;
+	}
+
+	setStrokeStyle(value) {
+		this.strokeStyle = value;
+	}
+
+	set strokeStyle(value) {
+
+		this._strokeStyle = value;
+
+		if (typeof(value) == 'string') {
+			this._drawCommands = this._drawCommands.concat("S" + value + ";");
+		} else if (value instanceof FillStylePattern) {
+			CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
+			this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
+		} else if (value instanceof FillStyleLinearGradient) {
+			var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
+				value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
+				value._stop_count;
+
+			for (var i = 0; i < value._stop_count; ++i) {
+				command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
+			}
+			this._drawCommands = this._drawCommands.concat(command + ";");
+		} else if (value instanceof FillStyleRadialGradient) {
+			var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
+				.toFixed(2) + "," +
+				value._end_pos._x.toFixed(2) + "," + value._end_pos._y + ",".toFixed(2) + value._end_pos._r.toFixed(2) + "," +
+				value._stop_count;
+
+			for (var i = 0; i < value._stop_count; ++i) {
+				command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
+			}
+			this._drawCommands = this._drawCommands.concat(command + ";");
+		}
+	}
+
+	get lineWidth() {
+		return this._lineWidth;
+	}
+
+	setLineWidth(value) {
+		this.lineWidth = value;
+	}
+
+	set lineWidth(value) {
+		this._lineWidth = value;
+		this._drawCommands = this._drawCommands.concat("W" + value + ";");
+	}
+
+	get lineCap() {
+		return this._lineCap;
+	}
+
+	setLineCap(value) {
+		this.lineCap = value;
+	}
+
+	set lineCap(value) {
+		this._lineCap = value;
+		this._drawCommands = this._drawCommands.concat("C" + value + ";");
+	}
+
+	get lineJoin() {
+		return this._lineJoin;
+	}
+
+	setLineJoin(value) {
+		this.lineJoin = value
+	}
+
+	set lineJoin(value) {
+		this._lineJoin = value;
+		this._drawCommands = this._drawCommands.concat("J" + value + ";");
+	}
+
+	get miterLimit() {
+		return this._miterLimit;
+	}
+
+	setMiterLimit(value) {
+		this.miterLimit = value
+	}
+
+	set miterLimit(value) {
+		this._miterLimit = value;
+		this._drawCommands = this._drawCommands.concat("M" + value + ";");
+	}
+
+	get globalCompositeOperation() {
+		return this._globalCompositeOperation;
+	}
+
+	set globalCompositeOperation(value) {
+
+		this._globalCompositeOperation = value;
+		let mode = 0;
+		switch (value) {
+			case "source-over":
+				mode = 0;
+				break;
+			case "source-atop":
+				mode = 5;
+				break;
+			case "source-in":
+				mode = 0;
+				break;
+			case "source-out":
+				mode = 2;
+				break;
+			case "destination-over":
+				mode = 4;
+				break;
+			case "destination-atop":
+				mode = 4;
+				break;
+			case "destination-in":
+				mode = 4;
+				break;
+			case "destination-out":
+				mode = 3;
+				break;
+			case "lighter":
+				mode = 1;
+				break;
+			case "copy":
+				mode = 2;
+				break;
+			case "xor":
+				mode = 6;
+				break;
+			default:
+				mode = 0;
+		}
+
+		this._drawCommands = this._drawCommands.concat("B" + mode + ";");
+	}
+
+	get textAlign() {
+		return this._textAlign;
+	}
+
+	setTextAlign(value) {
+		this.textAlign = value
+	}
+
+	set textAlign(value) {
+
+		this._textAlign = value;
+		let Align = 0;
+		switch (value) {
+			case "start":
+				Align = 0;
+				break;
+			case "end":
+				Align = 1;
+				break;
+			case "left":
+				Align = 2;
+				break;
+			case "center":
+				Align = 3;
+				break;
+			case "right":
+				Align = 4;
+				break;
+			default:
+				Align = 0;
+		}
+
+		this._drawCommands = this._drawCommands.concat("A" + Align + ";");
+	}
+
+	get textBaseline() {
+		return this._textBaseline;
+	}
+
+	setTextBaseline(value) {
+		this.textBaseline = value
+	}
+
+	set textBaseline(value) {
+		this._textBaseline = value;
+		let baseline = 0;
+		switch (value) {
+			case "alphabetic":
+				baseline = 0;
+				break;
+			case "middle":
+				baseline = 1;
+				break;
+			case "top":
+				baseline = 2;
+				break;
+			case "hanging":
+				baseline = 3;
+				break;
+			case "bottom":
+				baseline = 4;
+				break;
+			case "ideographic":
+				baseline = 5;
+				break;
+			default:
+				baseline = 0;
+				break;
+		}
+
+		this._drawCommands = this._drawCommands.concat("E" + baseline + ";");
+	}
+
+	get font() {
+		return this._font;
+	}
+
+	setFontSize(size) {
+		var str = this._font;
+		var strs = str.trim().split(/\s+/);
+		for (var i = 0; i < strs.length; i++) {
+			var values = ["normal", "italic", "oblique", "normal", "small-caps", "normal", "bold",
+				"bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900",
+				"normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
+				"semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
+			];
+
+			if (-1 == values.indexOf(strs[i].trim())) {
+				if (typeof size === 'string') {
+					strs[i] = size;
+				} else if (typeof size === 'number') {
+					strs[i] = String(size) + 'px';
+				}
+				break;
+			}
+		}
+		this.font = strs.join(" ");
+	}
+
+	set font(value) {
+		this._font = value;
+		this._drawCommands = this._drawCommands.concat("j" + value + ";");
+	}
+
+	setTransform(a, b, c, d, tx, ty) {
+		this._drawCommands = this._drawCommands.concat("t" +
+			(a === 1 ? "1" : a.toFixed(2)) + "," +
+			(b === 0 ? "0" : b.toFixed(2)) + "," +
+			(c === 0 ? "0" : c.toFixed(2)) + "," +
+			(d === 1 ? "1" : d.toFixed(2)) + "," + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
+	}
+
+	transform(a, b, c, d, tx, ty) {
+		this._drawCommands = this._drawCommands.concat("f" +
+			(a === 1 ? "1" : a.toFixed(2)) + "," +
+			(b === 0 ? "0" : b.toFixed(2)) + "," +
+			(c === 0 ? "0" : c.toFixed(2)) + "," +
+			(d === 1 ? "1" : d.toFixed(2)) + "," + tx + "," + ty + ";");
+	}
+
+	resetTransform() {
+		this._drawCommands = this._drawCommands.concat("m;");
+	}
+
+	scale(a, d) {
+		this._drawCommands = this._drawCommands.concat("k" + a.toFixed(2) + "," +
+			d.toFixed(2) + ";");
+	}
+
+	rotate(angle) {
+		this._drawCommands = this._drawCommands
+			.concat("r" + angle.toFixed(6) + ";");
+	}
+
+	translate(tx, ty) {
+		this._drawCommands = this._drawCommands.concat("l" + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
+	}
+
+	save() {
+		this._savedGlobalAlpha.push(this._globalAlpha);
+		this._drawCommands = this._drawCommands.concat("v;");
+	}
+
+	restore() {
+		this._drawCommands = this._drawCommands.concat("e;");
+		this._globalAlpha = this._savedGlobalAlpha.pop();
+	}
+
+	createPattern(img, pattern) {
+		if (typeof img === 'string') {
+			var imgObj = new GImage();
+			imgObj.src = img;
+			img = imgObj;
+		}
+		return new FillStylePattern(img, pattern);
+	}
+
+	createLinearGradient(x0, y0, x1, y1) {
+		return new FillStyleLinearGradient(x0, y0, x1, y1);
+	}
+
+	createRadialGradient = function(x0, y0, r0, x1, y1, r1) {
+		return new FillStyleRadialGradient(x0, y0, r0, x1, y1, r1);
+	};
+
+	createCircularGradient = function(x0, y0, r0) {
+		return new FillStyleRadialGradient(x0, y0, 0, x0, y0, r0);
+	};
+
+	strokeRect(x, y, w, h) {
+		this._drawCommands = this._drawCommands.concat("s" + x + "," + y + "," + w + "," + h + ";");
+	}
+
+
+	clearRect(x, y, w, h) {
+		this._drawCommands = this._drawCommands.concat("c" + x + "," + y + "," + w +
+			"," + h + ";");
+	}
+
+	clip() {
+		this._drawCommands = this._drawCommands.concat("p;");
+	}
+
+	resetClip() {
+		this._drawCommands = this._drawCommands.concat("q;");
+	}
+
+	closePath() {
+		this._drawCommands = this._drawCommands.concat("o;");
+	}
+
+	moveTo(x, y) {
+		this._drawCommands = this._drawCommands.concat("g" + x.toFixed(2) + "," + y.toFixed(2) + ";");
+	}
+
+	lineTo(x, y) {
+		this._drawCommands = this._drawCommands.concat("i" + x.toFixed(2) + "," + y.toFixed(2) + ";");
+	}
+
+	quadraticCurveTo = function(cpx, cpy, x, y) {
+		this._drawCommands = this._drawCommands.concat("u" + cpx + "," + cpy + "," + x + "," + y + ";");
+	}
+
+	bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, ) {
+		this._drawCommands = this._drawCommands.concat(
+			"z" + cp1x.toFixed(2) + "," + cp1y.toFixed(2) + "," + cp2x.toFixed(2) + "," + cp2y.toFixed(2) + "," +
+			x.toFixed(2) + "," + y.toFixed(2) + ";");
+	}
+
+	arcTo(x1, y1, x2, y2, radius) {
+		this._drawCommands = this._drawCommands.concat("h" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + radius + ";");
+	}
+
+	beginPath() {
+		this._drawCommands = this._drawCommands.concat("b;");
+	}
+
+
+	fillRect(x, y, w, h) {
+		this._drawCommands = this._drawCommands.concat("n" + x + "," + y + "," + w +
+			"," + h + ";");
+	}
+
+	rect(x, y, w, h) {
+		this._drawCommands = this._drawCommands.concat("w" + x + "," + y + "," + w + "," + h + ";");
+	}
+
+	fill() {
+		this._drawCommands = this._drawCommands.concat("L;");
+	}
+
+	stroke(path) {
+		this._drawCommands = this._drawCommands.concat("x;");
+	}
+
+	arc(x, y, radius, startAngle, endAngle, anticlockwise) {
+
+		let ianticlockwise = 0;
+		if (anticlockwise) {
+			ianticlockwise = 1;
+		}
+
+		this._drawCommands = this._drawCommands.concat(
+			"y" + x.toFixed(2) + "," + y.toFixed(2) + "," +
+			radius.toFixed(2) + "," + startAngle + "," + endAngle + "," + ianticlockwise +
+			";"
+		);
+	}
+
+	fillText(text, x, y) {
+		let tmptext = text.replace(/!/g, "!!");
+		tmptext = tmptext.replace(/,/g, "!,");
+		tmptext = tmptext.replace(/;/g, "!;");
+		this._drawCommands = this._drawCommands.concat("T" + tmptext + "," + x + "," + y + ",0.0;");
+	}
+
+	strokeText = function(text, x, y) {
+		let tmptext = text.replace(/!/g, "!!");
+		tmptext = tmptext.replace(/,/g, "!,");
+		tmptext = tmptext.replace(/;/g, "!;");
+		this._drawCommands = this._drawCommands.concat("U" + tmptext + "," + x + "," + y + ",0.0;");
+	}
+
+	measureText(text) {
+		return CanvasRenderingContext2D.GBridge.measureText(text, this.font, this.componentId);
+	}
+
+	isPointInPath = function(x, y) {
+		throw new Error('GCanvas not supported yet');
+	}
+
+	drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
+		if (typeof image === 'string') {
+			var imgObj = new GImage();
+			imgObj.src = image;
+			image = imgObj;
+		}
+		if (image instanceof GImage) {
+			if (!image.complete) {
+				imgObj.onload = () => {
+					var index = this._needRedrawImageCache.indexOf(image);
+					if (index > -1) {
+						this._needRedrawImageCache.splice(index, 1);
+						CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
+						this._redrawflush(true);
+					}
+				}
+				this._notCommitDrawImageCache.push(image);
+			} else {
+				CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
+			}
+			var srcArgs = [image, sx, sy, sw, sh, dx, dy, dw, dh];
+			var args = [];
+			for (var arg in srcArgs) {
+				if (typeof(srcArgs[arg]) != 'undefined') {
+					args.push(srcArgs[arg]);
+				}
+			}
+			this.__drawImage.apply(this, args);
+			//this.__drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
+		}
+	}
+
+	__drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
+		const numArgs = arguments.length;
+
+		function drawImageCommands() {
+
+			if (numArgs === 3) {
+				const x = parseFloat(sx) || 0.0;
+				const y = parseFloat(sy) || 0.0;
+
+				return ("d" + image._id + ",0,0," +
+					image.width + "," + image.height + "," +
+					x + "," + y + "," + image.width + "," + image.height + ";");
+			} else if (numArgs === 5) {
+				const x = parseFloat(sx) || 0.0;
+				const y = parseFloat(sy) || 0.0;
+				const width = parseInt(sw) || image.width;
+				const height = parseInt(sh) || image.height;
+
+				return ("d" + image._id + ",0,0," +
+					image.width + "," + image.height + "," +
+					x + "," + y + "," + width + "," + height + ";");
+			} else if (numArgs === 9) {
+				sx = parseFloat(sx) || 0.0;
+				sy = parseFloat(sy) || 0.0;
+				sw = parseInt(sw) || image.width;
+				sh = parseInt(sh) || image.height;
+				dx = parseFloat(dx) || 0.0;
+				dy = parseFloat(dy) || 0.0;
+				dw = parseInt(dw) || image.width;
+				dh = parseInt(dh) || image.height;
+
+				return ("d" + image._id + "," +
+					sx + "," + sy + "," + sw + "," + sh + "," +
+					dx + "," + dy + "," + dw + "," + dh + ";");
+			}
+		}
+		this._drawCommands += drawImageCommands();
+	}
+
+	_flush(reserve, callback) {
+		const commands = this._drawCommands;
+		this._drawCommands = '';
+		CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
+		this._needRender = false;
+	}
+
+	_redrawflush(reserve, callback) {
+		const commands = this._redrawCommands;
+		CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
+		if (this._needRedrawImageCache.length == 0) {
+			this._redrawCommands = '';
+		}
+	}
+
+	draw(reserve, callback) {
+		if (!reserve) {
+			this._globalAlpha = this._savedGlobalAlpha.pop();
+			this._savedGlobalAlpha.push(this._globalAlpha);
+			this._redrawCommands = this._drawCommands;
+			this._needRedrawImageCache = this._notCommitDrawImageCache;
+			if (this._autoSaveContext) {
+				this._drawCommands = ("v;" + this._drawCommands);
+				this._autoSaveContext = false;
+			} else {
+				this._drawCommands = ("e;X;v;" + this._drawCommands);
+			}
+		} else {
+			this._needRedrawImageCache = this._needRedrawImageCache.concat(this._notCommitDrawImageCache);
+			this._redrawCommands += this._drawCommands;
+			if (this._autoSaveContext) {
+				this._drawCommands = ("v;" + this._drawCommands);
+				this._autoSaveContext = false;
+			}
+		}
+		this._notCommitDrawImageCache = [];
+		if (this._flush) {
+			this._flush(reserve, callback);
+		}
+	}
+
+	getImageData(x, y, w, h, callback) {
+		CanvasRenderingContext2D.GBridge.getImageData(this.componentId, x, y, w, h, function(res) {
+			res.data = Base64ToUint8ClampedArray(res.data);
+			if (typeof(callback) == 'function') {
+				callback(res);
+			}
+		});
+	}
+
+	putImageData(data, x, y, w, h, callback) {
+		if (data instanceof Uint8ClampedArray) {
+			data = ArrayBufferToBase64(data);
+			CanvasRenderingContext2D.GBridge.putImageData(this.componentId, data, x, y, w, h, function(res) {
+				if (typeof(callback) == 'function') {
+					callback(res);
+				}
+			});
+		}
+	}
+
+	toTempFilePath(x, y, width, height, destWidth, destHeight, fileType, quality, callback) {
+		CanvasRenderingContext2D.GBridge.toTempFilePath(this.componentId, x, y, width, height, destWidth, destHeight,
+			fileType, quality,
+			function(res) {
+				if (typeof(callback) == 'function') {
+					callback(res);
+				}
+			});
+	}
+}

+ 11 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/ActiveInfo.js

@@ -0,0 +1,11 @@
+export default class WebGLActiveInfo {
+    className = 'WebGLActiveInfo';
+
+    constructor({
+        type, name, size
+    }) {
+        this.type = type;
+        this.name = name;
+        this.size = size;
+    }
+}

+ 21 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Buffer.js

@@ -0,0 +1,21 @@
+import {getTransferedObjectUUID} from './classUtils';
+
+const name = 'WebGLBuffer';
+
+function uuid(id) {
+    return getTransferedObjectUUID(name, id);
+}
+
+export default class WebGLBuffer {
+    className = name;
+
+    constructor(id) {
+        this.id = id;
+    }
+
+    static uuid = uuid;
+
+    uuid() {
+        return uuid(this.id);
+    }
+}

+ 21 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Framebuffer.js

@@ -0,0 +1,21 @@
+import {getTransferedObjectUUID} from './classUtils';
+
+const name = 'WebGLFrameBuffer';
+
+function uuid(id) {
+    return getTransferedObjectUUID(name, id);
+}
+
+export default class WebGLFramebuffer {
+    className = name;
+
+    constructor(id) {
+        this.id = id;
+    }
+
+    static uuid = uuid;
+
+    uuid() {
+        return uuid(this.id);
+    }
+}

+ 298 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/GLenum.js

@@ -0,0 +1,298 @@
+export default {
+    "DEPTH_BUFFER_BIT": 256,
+    "STENCIL_BUFFER_BIT": 1024,
+    "COLOR_BUFFER_BIT": 16384,
+    "POINTS": 0,
+    "LINES": 1,
+    "LINE_LOOP": 2,
+    "LINE_STRIP": 3,
+    "TRIANGLES": 4,
+    "TRIANGLE_STRIP": 5,
+    "TRIANGLE_FAN": 6,
+    "ZERO": 0,
+    "ONE": 1,
+    "SRC_COLOR": 768,
+    "ONE_MINUS_SRC_COLOR": 769,
+    "SRC_ALPHA": 770,
+    "ONE_MINUS_SRC_ALPHA": 771,
+    "DST_ALPHA": 772,
+    "ONE_MINUS_DST_ALPHA": 773,
+    "DST_COLOR": 774,
+    "ONE_MINUS_DST_COLOR": 775,
+    "SRC_ALPHA_SATURATE": 776,
+    "FUNC_ADD": 32774,
+    "BLEND_EQUATION": 32777,
+    "BLEND_EQUATION_RGB": 32777,
+    "BLEND_EQUATION_ALPHA": 34877,
+    "FUNC_SUBTRACT": 32778,
+    "FUNC_REVERSE_SUBTRACT": 32779,
+    "BLEND_DST_RGB": 32968,
+    "BLEND_SRC_RGB": 32969,
+    "BLEND_DST_ALPHA": 32970,
+    "BLEND_SRC_ALPHA": 32971,
+    "CONSTANT_COLOR": 32769,
+    "ONE_MINUS_CONSTANT_COLOR": 32770,
+    "CONSTANT_ALPHA": 32771,
+    "ONE_MINUS_CONSTANT_ALPHA": 32772,
+    "BLEND_COLOR": 32773,
+    "ARRAY_BUFFER": 34962,
+    "ELEMENT_ARRAY_BUFFER": 34963,
+    "ARRAY_BUFFER_BINDING": 34964,
+    "ELEMENT_ARRAY_BUFFER_BINDING": 34965,
+    "STREAM_DRAW": 35040,
+    "STATIC_DRAW": 35044,
+    "DYNAMIC_DRAW": 35048,
+    "BUFFER_SIZE": 34660,
+    "BUFFER_USAGE": 34661,
+    "CURRENT_VERTEX_ATTRIB": 34342,
+    "FRONT": 1028,
+    "BACK": 1029,
+    "FRONT_AND_BACK": 1032,
+    "TEXTURE_2D": 3553,
+    "CULL_FACE": 2884,
+    "BLEND": 3042,
+    "DITHER": 3024,
+    "STENCIL_TEST": 2960,
+    "DEPTH_TEST": 2929,
+    "SCISSOR_TEST": 3089,
+    "POLYGON_OFFSET_FILL": 32823,
+    "SAMPLE_ALPHA_TO_COVERAGE": 32926,
+    "SAMPLE_COVERAGE": 32928,
+    "NO_ERROR": 0,
+    "INVALID_ENUM": 1280,
+    "INVALID_VALUE": 1281,
+    "INVALID_OPERATION": 1282,
+    "OUT_OF_MEMORY": 1285,
+    "CW": 2304,
+    "CCW": 2305,
+    "LINE_WIDTH": 2849,
+    "ALIASED_POINT_SIZE_RANGE": 33901,
+    "ALIASED_LINE_WIDTH_RANGE": 33902,
+    "CULL_FACE_MODE": 2885,
+    "FRONT_FACE": 2886,
+    "DEPTH_RANGE": 2928,
+    "DEPTH_WRITEMASK": 2930,
+    "DEPTH_CLEAR_VALUE": 2931,
+    "DEPTH_FUNC": 2932,
+    "STENCIL_CLEAR_VALUE": 2961,
+    "STENCIL_FUNC": 2962,
+    "STENCIL_FAIL": 2964,
+    "STENCIL_PASS_DEPTH_FAIL": 2965,
+    "STENCIL_PASS_DEPTH_PASS": 2966,
+    "STENCIL_REF": 2967,
+    "STENCIL_VALUE_MASK": 2963,
+    "STENCIL_WRITEMASK": 2968,
+    "STENCIL_BACK_FUNC": 34816,
+    "STENCIL_BACK_FAIL": 34817,
+    "STENCIL_BACK_PASS_DEPTH_FAIL": 34818,
+    "STENCIL_BACK_PASS_DEPTH_PASS": 34819,
+    "STENCIL_BACK_REF": 36003,
+    "STENCIL_BACK_VALUE_MASK": 36004,
+    "STENCIL_BACK_WRITEMASK": 36005,
+    "VIEWPORT": 2978,
+    "SCISSOR_BOX": 3088,
+    "COLOR_CLEAR_VALUE": 3106,
+    "COLOR_WRITEMASK": 3107,
+    "UNPACK_ALIGNMENT": 3317,
+    "PACK_ALIGNMENT": 3333,
+    "MAX_TEXTURE_SIZE": 3379,
+    "MAX_VIEWPORT_DIMS": 3386,
+    "SUBPIXEL_BITS": 3408,
+    "RED_BITS": 3410,
+    "GREEN_BITS": 3411,
+    "BLUE_BITS": 3412,
+    "ALPHA_BITS": 3413,
+    "DEPTH_BITS": 3414,
+    "STENCIL_BITS": 3415,
+    "POLYGON_OFFSET_UNITS": 10752,
+    "POLYGON_OFFSET_FACTOR": 32824,
+    "TEXTURE_BINDING_2D": 32873,
+    "SAMPLE_BUFFERS": 32936,
+    "SAMPLES": 32937,
+    "SAMPLE_COVERAGE_VALUE": 32938,
+    "SAMPLE_COVERAGE_INVERT": 32939,
+    "COMPRESSED_TEXTURE_FORMATS": 34467,
+    "DONT_CARE": 4352,
+    "FASTEST": 4353,
+    "NICEST": 4354,
+    "GENERATE_MIPMAP_HINT": 33170,
+    "BYTE": 5120,
+    "UNSIGNED_BYTE": 5121,
+    "SHORT": 5122,
+    "UNSIGNED_SHORT": 5123,
+    "INT": 5124,
+    "UNSIGNED_INT": 5125,
+    "FLOAT": 5126,
+    "DEPTH_COMPONENT": 6402,
+    "ALPHA": 6406,
+    "RGB": 6407,
+    "RGBA": 6408,
+    "LUMINANCE": 6409,
+    "LUMINANCE_ALPHA": 6410,
+    "UNSIGNED_SHORT_4_4_4_4": 32819,
+    "UNSIGNED_SHORT_5_5_5_1": 32820,
+    "UNSIGNED_SHORT_5_6_5": 33635,
+    "FRAGMENT_SHADER": 35632,
+    "VERTEX_SHADER": 35633,
+    "MAX_VERTEX_ATTRIBS": 34921,
+    "MAX_VERTEX_UNIFORM_VECTORS": 36347,
+    "MAX_VARYING_VECTORS": 36348,
+    "MAX_COMBINED_TEXTURE_IMAGE_UNITS": 35661,
+    "MAX_VERTEX_TEXTURE_IMAGE_UNITS": 35660,
+    "MAX_TEXTURE_IMAGE_UNITS": 34930,
+    "MAX_FRAGMENT_UNIFORM_VECTORS": 36349,
+    "SHADER_TYPE": 35663,
+    "DELETE_STATUS": 35712,
+    "LINK_STATUS": 35714,
+    "VALIDATE_STATUS": 35715,
+    "ATTACHED_SHADERS": 35717,
+    "ACTIVE_UNIFORMS": 35718,
+    "ACTIVE_ATTRIBUTES": 35721,
+    "SHADING_LANGUAGE_VERSION": 35724,
+    "CURRENT_PROGRAM": 35725,
+    "NEVER": 512,
+    "LESS": 513,
+    "EQUAL": 514,
+    "LEQUAL": 515,
+    "GREATER": 516,
+    "NOTEQUAL": 517,
+    "GEQUAL": 518,
+    "ALWAYS": 519,
+    "KEEP": 7680,
+    "REPLACE": 7681,
+    "INCR": 7682,
+    "DECR": 7683,
+    "INVERT": 5386,
+    "INCR_WRAP": 34055,
+    "DECR_WRAP": 34056,
+    "VENDOR": 7936,
+    "RENDERER": 7937,
+    "VERSION": 7938,
+    "NEAREST": 9728,
+    "LINEAR": 9729,
+    "NEAREST_MIPMAP_NEAREST": 9984,
+    "LINEAR_MIPMAP_NEAREST": 9985,
+    "NEAREST_MIPMAP_LINEAR": 9986,
+    "LINEAR_MIPMAP_LINEAR": 9987,
+    "TEXTURE_MAG_FILTER": 10240,
+    "TEXTURE_MIN_FILTER": 10241,
+    "TEXTURE_WRAP_S": 10242,
+    "TEXTURE_WRAP_T": 10243,
+    "TEXTURE": 5890,
+    "TEXTURE_CUBE_MAP": 34067,
+    "TEXTURE_BINDING_CUBE_MAP": 34068,
+    "TEXTURE_CUBE_MAP_POSITIVE_X": 34069,
+    "TEXTURE_CUBE_MAP_NEGATIVE_X": 34070,
+    "TEXTURE_CUBE_MAP_POSITIVE_Y": 34071,
+    "TEXTURE_CUBE_MAP_NEGATIVE_Y": 34072,
+    "TEXTURE_CUBE_MAP_POSITIVE_Z": 34073,
+    "TEXTURE_CUBE_MAP_NEGATIVE_Z": 34074,
+    "MAX_CUBE_MAP_TEXTURE_SIZE": 34076,
+    "TEXTURE0": 33984,
+    "TEXTURE1": 33985,
+    "TEXTURE2": 33986,
+    "TEXTURE3": 33987,
+    "TEXTURE4": 33988,
+    "TEXTURE5": 33989,
+    "TEXTURE6": 33990,
+    "TEXTURE7": 33991,
+    "TEXTURE8": 33992,
+    "TEXTURE9": 33993,
+    "TEXTURE10": 33994,
+    "TEXTURE11": 33995,
+    "TEXTURE12": 33996,
+    "TEXTURE13": 33997,
+    "TEXTURE14": 33998,
+    "TEXTURE15": 33999,
+    "TEXTURE16": 34000,
+    "TEXTURE17": 34001,
+    "TEXTURE18": 34002,
+    "TEXTURE19": 34003,
+    "TEXTURE20": 34004,
+    "TEXTURE21": 34005,
+    "TEXTURE22": 34006,
+    "TEXTURE23": 34007,
+    "TEXTURE24": 34008,
+    "TEXTURE25": 34009,
+    "TEXTURE26": 34010,
+    "TEXTURE27": 34011,
+    "TEXTURE28": 34012,
+    "TEXTURE29": 34013,
+    "TEXTURE30": 34014,
+    "TEXTURE31": 34015,
+    "ACTIVE_TEXTURE": 34016,
+    "REPEAT": 10497,
+    "CLAMP_TO_EDGE": 33071,
+    "MIRRORED_REPEAT": 33648,
+    "FLOAT_VEC2": 35664,
+    "FLOAT_VEC3": 35665,
+    "FLOAT_VEC4": 35666,
+    "INT_VEC2": 35667,
+    "INT_VEC3": 35668,
+    "INT_VEC4": 35669,
+    "BOOL": 35670,
+    "BOOL_VEC2": 35671,
+    "BOOL_VEC3": 35672,
+    "BOOL_VEC4": 35673,
+    "FLOAT_MAT2": 35674,
+    "FLOAT_MAT3": 35675,
+    "FLOAT_MAT4": 35676,
+    "SAMPLER_2D": 35678,
+    "SAMPLER_CUBE": 35680,
+    "VERTEX_ATTRIB_ARRAY_ENABLED": 34338,
+    "VERTEX_ATTRIB_ARRAY_SIZE": 34339,
+    "VERTEX_ATTRIB_ARRAY_STRIDE": 34340,
+    "VERTEX_ATTRIB_ARRAY_TYPE": 34341,
+    "VERTEX_ATTRIB_ARRAY_NORMALIZED": 34922,
+    "VERTEX_ATTRIB_ARRAY_POINTER": 34373,
+    "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING": 34975,
+    "IMPLEMENTATION_COLOR_READ_TYPE": 35738,
+    "IMPLEMENTATION_COLOR_READ_FORMAT": 35739,
+    "COMPILE_STATUS": 35713,
+    "LOW_FLOAT": 36336,
+    "MEDIUM_FLOAT": 36337,
+    "HIGH_FLOAT": 36338,
+    "LOW_INT": 36339,
+    "MEDIUM_INT": 36340,
+    "HIGH_INT": 36341,
+    "FRAMEBUFFER": 36160,
+    "RENDERBUFFER": 36161,
+    "RGBA4": 32854,
+    "RGB5_A1": 32855,
+    "RGB565": 36194,
+    "DEPTH_COMPONENT16": 33189,
+    "STENCIL_INDEX8": 36168,
+    "DEPTH_STENCIL": 34041,
+    "RENDERBUFFER_WIDTH": 36162,
+    "RENDERBUFFER_HEIGHT": 36163,
+    "RENDERBUFFER_INTERNAL_FORMAT": 36164,
+    "RENDERBUFFER_RED_SIZE": 36176,
+    "RENDERBUFFER_GREEN_SIZE": 36177,
+    "RENDERBUFFER_BLUE_SIZE": 36178,
+    "RENDERBUFFER_ALPHA_SIZE": 36179,
+    "RENDERBUFFER_DEPTH_SIZE": 36180,
+    "RENDERBUFFER_STENCIL_SIZE": 36181,
+    "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE": 36048,
+    "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME": 36049,
+    "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL": 36050,
+    "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE": 36051,
+    "COLOR_ATTACHMENT0": 36064,
+    "DEPTH_ATTACHMENT": 36096,
+    "STENCIL_ATTACHMENT": 36128,
+    "DEPTH_STENCIL_ATTACHMENT": 33306,
+    "NONE": 0,
+    "FRAMEBUFFER_COMPLETE": 36053,
+    "FRAMEBUFFER_INCOMPLETE_ATTACHMENT": 36054,
+    "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT": 36055,
+    "FRAMEBUFFER_INCOMPLETE_DIMENSIONS": 36057,
+    "FRAMEBUFFER_UNSUPPORTED": 36061,
+    "FRAMEBUFFER_BINDING": 36006,
+    "RENDERBUFFER_BINDING": 36007,
+    "MAX_RENDERBUFFER_SIZE": 34024,
+    "INVALID_FRAMEBUFFER_OPERATION": 1286,
+    "UNPACK_FLIP_Y_WEBGL": 37440,
+    "UNPACK_PREMULTIPLY_ALPHA_WEBGL": 37441,
+    "CONTEXT_LOST_WEBGL": 37442,
+    "UNPACK_COLORSPACE_CONVERSION_WEBGL": 37443,
+    "BROWSER_DEFAULT_WEBGL": 37444
+};

+ 142 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/GLmethod.js

@@ -0,0 +1,142 @@
+let i = 1;
+
+const GLmethod = {};
+
+GLmethod.activeTexture = i++;         //1
+GLmethod.attachShader = i++;
+GLmethod.bindAttribLocation = i++;
+GLmethod.bindBuffer = i++;
+GLmethod.bindFramebuffer = i++;
+GLmethod.bindRenderbuffer = i++;
+GLmethod.bindTexture = i++;
+GLmethod.blendColor = i++;
+GLmethod.blendEquation = i++;
+GLmethod.blendEquationSeparate = i++; //10
+GLmethod.blendFunc = i++;
+GLmethod.blendFuncSeparate = i++;
+GLmethod.bufferData = i++;
+GLmethod.bufferSubData = i++;
+GLmethod.checkFramebufferStatus = i++;
+GLmethod.clear = i++;
+GLmethod.clearColor = i++;
+GLmethod.clearDepth = i++;
+GLmethod.clearStencil = i++;
+GLmethod.colorMask = i++;              //20
+GLmethod.compileShader = i++;
+GLmethod.compressedTexImage2D = i++;
+GLmethod.compressedTexSubImage2D = i++;
+GLmethod.copyTexImage2D = i++;
+GLmethod.copyTexSubImage2D = i++;
+GLmethod.createBuffer = i++;
+GLmethod.createFramebuffer = i++;
+GLmethod.createProgram = i++;
+GLmethod.createRenderbuffer = i++;
+GLmethod.createShader = i++;           //30
+GLmethod.createTexture = i++;
+GLmethod.cullFace = i++;
+GLmethod.deleteBuffer = i++;
+GLmethod.deleteFramebuffer = i++;
+GLmethod.deleteProgram = i++;
+GLmethod.deleteRenderbuffer = i++;
+GLmethod.deleteShader = i++;
+GLmethod.deleteTexture = i++;
+GLmethod.depthFunc = i++;
+GLmethod.depthMask = i++;              //40
+GLmethod.depthRange = i++;
+GLmethod.detachShader = i++;
+GLmethod.disable = i++;
+GLmethod.disableVertexAttribArray = i++;
+GLmethod.drawArrays = i++;
+GLmethod.drawArraysInstancedANGLE = i++;
+GLmethod.drawElements = i++;
+GLmethod.drawElementsInstancedANGLE = i++;
+GLmethod.enable = i++;
+GLmethod.enableVertexAttribArray = i++;    //50
+GLmethod.flush = i++;
+GLmethod.framebufferRenderbuffer = i++;
+GLmethod.framebufferTexture2D = i++;
+GLmethod.frontFace = i++;
+GLmethod.generateMipmap = i++;
+GLmethod.getActiveAttrib = i++;
+GLmethod.getActiveUniform = i++;
+GLmethod.getAttachedShaders = i++;
+GLmethod.getAttribLocation = i++;
+GLmethod.getBufferParameter = i++;         //60
+GLmethod.getContextAttributes = i++;
+GLmethod.getError = i++;
+GLmethod.getExtension = i++;
+GLmethod.getFramebufferAttachmentParameter = i++;
+GLmethod.getParameter = i++;
+GLmethod.getProgramInfoLog = i++;
+GLmethod.getProgramParameter = i++;
+GLmethod.getRenderbufferParameter = i++;
+GLmethod.getShaderInfoLog = i++;
+GLmethod.getShaderParameter = i++;         //70
+GLmethod.getShaderPrecisionFormat = i++;
+GLmethod.getShaderSource = i++;
+GLmethod.getSupportedExtensions = i++;
+GLmethod.getTexParameter = i++;
+GLmethod.getUniform = i++;
+GLmethod.getUniformLocation = i++;
+GLmethod.getVertexAttrib = i++;
+GLmethod.getVertexAttribOffset = i++;
+GLmethod.isBuffer = i++;
+GLmethod.isContextLost = i++;              //80
+GLmethod.isEnabled = i++;
+GLmethod.isFramebuffer = i++;
+GLmethod.isProgram = i++;
+GLmethod.isRenderbuffer = i++;
+GLmethod.isShader = i++;
+GLmethod.isTexture = i++;
+GLmethod.lineWidth = i++;
+GLmethod.linkProgram = i++;
+GLmethod.pixelStorei = i++;
+GLmethod.polygonOffset = i++;              //90
+GLmethod.readPixels = i++;
+GLmethod.renderbufferStorage = i++;
+GLmethod.sampleCoverage = i++;
+GLmethod.scissor = i++;
+GLmethod.shaderSource = i++;
+GLmethod.stencilFunc = i++;
+GLmethod.stencilFuncSeparate = i++;
+GLmethod.stencilMask = i++;
+GLmethod.stencilMaskSeparate = i++;
+GLmethod.stencilOp = i++;                  //100
+GLmethod.stencilOpSeparate = i++;
+GLmethod.texImage2D = i++;
+GLmethod.texParameterf = i++;
+GLmethod.texParameteri = i++;
+GLmethod.texSubImage2D = i++;
+GLmethod.uniform1f = i++;
+GLmethod.uniform1fv = i++;
+GLmethod.uniform1i = i++;
+GLmethod.uniform1iv = i++;
+GLmethod.uniform2f = i++;                  //110
+GLmethod.uniform2fv = i++;
+GLmethod.uniform2i = i++;
+GLmethod.uniform2iv = i++;
+GLmethod.uniform3f = i++;
+GLmethod.uniform3fv = i++;
+GLmethod.uniform3i = i++;
+GLmethod.uniform3iv = i++;
+GLmethod.uniform4f = i++;
+GLmethod.uniform4fv = i++;
+GLmethod.uniform4i = i++;                  //120
+GLmethod.uniform4iv = i++;
+GLmethod.uniformMatrix2fv = i++;
+GLmethod.uniformMatrix3fv = i++;
+GLmethod.uniformMatrix4fv = i++;
+GLmethod.useProgram = i++;
+GLmethod.validateProgram = i++;
+GLmethod.vertexAttrib1f = i++; //new
+GLmethod.vertexAttrib2f = i++; //new
+GLmethod.vertexAttrib3f = i++; //new
+GLmethod.vertexAttrib4f = i++; //new       //130
+GLmethod.vertexAttrib1fv = i++; //new
+GLmethod.vertexAttrib2fv = i++; //new
+GLmethod.vertexAttrib3fv = i++; //new
+GLmethod.vertexAttrib4fv = i++; //new
+GLmethod.vertexAttribPointer = i++;
+GLmethod.viewport = i++;
+
+export default GLmethod;

+ 23 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/GLtype.js

@@ -0,0 +1,23 @@
+const GLtype = {};
+
+[
+    "GLbitfield",    
+    "GLboolean",
+    "GLbyte",
+    "GLclampf",
+    "GLenum",
+    "GLfloat",
+    "GLint",
+    "GLintptr",
+    "GLsizei",
+    "GLsizeiptr",
+    "GLshort",
+    "GLubyte",
+    "GLuint",
+    "GLushort"
+].sort().map((typeName, i) => GLtype[typeName] = 1 >> (i + 1));
+
+export default GLtype;
+
+
+

+ 21 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Program.js

@@ -0,0 +1,21 @@
+import {getTransferedObjectUUID} from './classUtils';
+
+const name = 'WebGLProgram';
+
+function uuid(id) {
+    return getTransferedObjectUUID(name, id);
+}
+
+export default class WebGLProgram {
+    className = name;
+
+    constructor(id) {
+        this.id = id;
+    }
+
+    static uuid = uuid;
+
+    uuid() {
+        return uuid(this.id);
+    }
+}

+ 21 - 0
pagesPoster/comps/u-draw-poster/lib/extends/create-gcanvas/gcanvas/context-webgl/Renderbuffer.js

@@ -0,0 +1,21 @@
+import {getTransferedObjectUUID} from './classUtils';
+
+const name = 'WebGLRenderBuffer';
+
+function uuid(id) {
+    return getTransferedObjectUUID(name, id);
+}
+
+export default class WebGLRenderbuffer {
+    className = name;
+
+    constructor(id) {
+        this.id = id;
+    }
+
+    static uuid = uuid;
+
+    uuid() {
+        return uuid(this.id);
+    }
+}

Някои файлове не бяха показани, защото твърде много файлове са промени