shish 6 years ago
parent
commit
88f89ba9a0

+ 252 - 0
store/src/admin-goods/add.vue

@@ -0,0 +1,252 @@
+<template>
+	<div class="app-content">
+		<!-- 商品基本信息 -->
+		<form @submit="formSubmit">
+			<div class="module-com input-line-wrap">
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title required">名称</div>
+					<input v-model="form.goodsName" placeholder-class="phcolor" class="tui-input" name="goodsName" placeholder="请输入" maxlength="50" type="text" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">已售</div>
+					<input v-model="form.sold" placeholder-class="phcolor" class="tui-input" name="sold" placeholder="请输入" maxlength="50" type="number" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">库存</div>
+					<input v-model="form.stock" placeholder-class="phcolor" class="tui-input" name="stock" placeholder="请输入" maxlength="50" type="number" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell category-wrap" :hover="false">
+					<div class="tui-title">类型</div>
+					<div class="tui-input">
+						<block v-for="(item, index) in categoryData" :key="index">
+							<button class="admin-button-com" :class="[form.categoryIdList.includes(item.id) ? '' : 'default']" @click="selCategoryFn(item)">{{ item.categoryName || '暂无' }}</button>
+						</block>
+					</div>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">价格</div>
+					<input v-model="form.price" placeholder-class="phcolor" class="tui-input" name="price" placeholder="请输入" maxlength="50" type="number" />
+					<div class="tui-prompt">元</div>
+				</tui-list-cell>
+				<!-- <tui-list-cell class="line-cell" :arrow="true">
+					<div class="tui-title">分类</div>
+					<div v-if="form.receiveFullAddress" class="tui-input">{{ form.receiveFullAddress }}</div>
+					<div v-else class="tui-placeholder">请选择</div>
+				</tui-list-cell>-->
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">自动涨价</div>
+					<label for="autoPrice" class="tui-input" @click="autoRiseChange(form.autoRise)">
+						<checkbox id="autoPrice" class="ljd-checkbox" :checked="form.autoRise == 1"></checkbox>
+						<span>需要</span>
+					</label>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">配送方式</div>
+					<label for="autoPrice" class="tui-input" @click="needSendChange(form.needSend)">
+						<checkbox id="autoPrice" class="ljd-checkbox" :checked="form.needSend == 1" @change="giftChange"></checkbox>
+						<span>到店自提</span>
+					</label>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">运费</div>
+					<radio-group class="tui-input flex-center-between" @change="freightChange">
+						<label class="list" for="customLink">
+							<radio id="customLink" value="0" :checked="form.freightType == 0" />
+							<span class="checkbox-text">按距离收费</span>
+						</label>
+						<label class="list" for="goodsLink">
+							<radio id="goodsLink" value="1" :checked="form.freightType == 1" />
+							<span class="checkbox-text">免运费</span>
+						</label>
+					</radio-group>
+				</tui-list-cell>
+			</div>
+			<!-- 商品图片 -->
+			<div class="module-com input-line-wrap goods-wrap">
+				<div class="module-tit">
+					<span>商品图片</span>
+					<span class="app-color-3">(最多上传4张)</span>
+				</div>
+				<div class="module-det">
+					<app-uploader ref="appUploader" :imgList.sync="form.shopImg" :isMain="true" :num="4" />
+				</div>
+			</div>
+			<!-- 商品简介 -->
+			<div class="module-com input-line-wrap summary-wrap">
+				<div class="module-tit">商品简介</div>
+				<div class="module-det" style="padding-bottom: 10px">
+					<!-- <span class="app-price">商品简介请在电脑端进行修改</span> -->
+					<textarea v-model="form.briefContent" class="goods-summary" placeholder-class="phcolor" placeholder="请输入商品简介" />
+				</div>
+			</div>
+			<!-- button -->
+			<div class="app-footer">
+				<button class="admin-button-com middle default" formType="submit" @click="status = 1">上架出售</button>
+				<button class="admin-button-com middle blue" formType="submit" @click="status = 0">加入仓库</button>
+			</div>
+		</form>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import TuiListCell from '@/components/plugin/list-cell'
+import AppUploader from '@/components/app-uploader'
+const form = require('@/utils/formValidation.js')
+// api
+import { getCategory } from '@/utils/config'
+import { getDetailB, addB, updateB } from '@/api/goods'
+export default {
+	name: 'goods-add',
+	components: {
+		TuiListCell,
+		AppUploader
+	},
+	data() {
+		return {
+			// 上架状态
+			status: 1,
+			form: {
+				goodsName: '',
+				stock: '',
+				price: '',
+				categoryIdList: [],
+				// goodsStyle: '1',
+				// content: '',
+				autoRise: '1',
+				needSend: '0',
+				freightType: '0',
+				shopImg: []
+				// goodsStyleList: [],
+			}
+		}
+	},
+	computed: {
+		...mapGetters({ categoryData: 'getCategory' })
+	},
+	onLoad() {
+		// this.init()
+	},
+	methods: {
+		init() {
+			getCategory().then(() => {
+				if (this.option.id) {
+					this._getDet()
+				}
+			})
+		},
+		_getDet() {
+			return getDetailB({ id: this.option.id }).then(res => {
+				if (this.$util.isEmpty(res.data)) return
+				Object.keys(this.form).forEach((i, index) => {
+					this.form[i] = res.data[i]
+				})
+			})
+		},
+		// 确认
+		confirmFn() {
+			let host = this.option.id ? updateB : addB
+			let form = JSON.parse(JSON.stringify(this.form))
+			form.shopImg = this.$util.imgSubstr(form.shopImg)
+			host({
+				status: this.status,
+				...form
+			}).then(res => {
+				this.$msg('操作成功!')
+			})
+		},
+		// operate
+		selCategoryFn(item) {
+			let index = this.form.categoryIdList.findIndex(e => e == item.id)
+			if (index == -1) {
+				this.form.categoryIdList.push(item.id)
+			} else {
+				this.form.categoryIdList.splice(index, 1)
+			}
+			console.log(this.form.categoryIdList)
+		},
+		autoRiseChange(e) {
+			this.form.autoRise = e == '0' ? '1' : '0'
+		},
+		needSendChange(e) {
+			this.form.needSend = e == '0' ? '1' : '0'
+		},
+		freightChange(e) {
+			this.form.freightType = e.detail.value
+		},
+		// 表单验证
+		formSubmit(e) {
+			// 表单规则
+			let rules = [
+				{
+					name: 'goodsName',
+					rule: ['required'],
+					msg: ['请输入商品名']
+				}
+			]
+			// 进行表单检查
+			let formData = e.detail.value
+			let checkRes = form.validation(formData, rules)
+			// 验证通过!
+			if (!checkRes) {
+				setTimeout(() => {
+					this.confirmFn()
+				})
+			} else {
+				this.$msg(checkRes)
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		min-height: calc(100vh - 100px);
+		padding-bottom: 100px;
+	}
+	// 公共模块
+	.module-com {
+		margin-bottom: 20px;
+		background-color: #fff;
+		color: $fontColor2;
+		.module-tit {
+			padding: 20px 30px;
+			font-size: 28px;
+			// font-weight: 600;
+			// border-bottom: 1px solid $borderColor;
+		}
+		.module-det {
+			padding: 0 30px;
+		}
+	}
+	.category-wrap {
+		align-items: flex-start;
+		padding-bottom: 0 !important;
+		.tui-input {
+			@include disFlex(center, flex-start);
+			flex-wrap: wrap;
+			.admin-button-com {
+				// width: 104px;
+				margin-right: 20px;
+				margin-bottom: 20px;
+				// &:nth-child(4n + 1) {
+				// 	margin-left: 0;
+				// }
+			}
+		}
+	}
+	.summary-wrap {
+		.goods-summary {
+			height: 400px;
+			// font-size: 24px;
+		}
+	}
+	// button
+	.app-footer {
+		justify-content: space-evenly;
+		.admin-button-com {
+			width: 46%;
+		}
+	}
+</style>

+ 362 - 0
store/src/admin-goods/category.vue

@@ -0,0 +1,362 @@
+<template>
+	<div class="app-content">
+		<!-- list -->
+		<div class="list-wrap">
+			<block v-if="!$util.isEmpty(list.data)">
+				<div class="list" v-for="(item, index) in list.data" :key="index">
+					<div class="list-index">{{ item.inTurn }}</div>
+					<div class="list-img">
+						<img :src="item.img" alt="分类图" mode="center" />
+					</div>
+					<div class="list-det">
+						<div class="app-size-28 app-color-0">{{ item.categoryName || '暂无' }}</div>
+						<div>{{ item.description || '暂无' }}</div>
+						<div class="list-operate">
+							<div class="operate-det">
+								<span>商品数: {{ item.goodsNum }}</span>
+								<span>销量: {{ item.sold }}</span>
+								<span :style="{color: item.status == 1 ? '#049E2C' : '#ff6900'}">{{ item.status == 1? '启用' : '禁用' }}</span>
+							</div>
+							<div class="operate-icon-wrap" @click="operateFn(item, index)">
+								<div class="operate-icon">
+									<i class="iconfont" :class="[ index == operateIndex ? 'iconcaozuojihuo' : 'iconcaozuo']"></i>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<!-- operate -->
+				<operate-module v-show="operateShow" :top="operateTop" :right="30" :btnData="btnData" />
+			</block>
+			<block v-else>
+				<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+			</block>
+		</div>
+		<!-- button -->
+		<div class="app-footer">
+			<button class="admin-button-com middle blue" @click="addCategoryFn">添加分类</button>
+		</div>
+		<!-- modify -->
+		<modal-module :show="modifyModal" :maskClosable="false" @cancel="modalCancel" @click="modifyModalClick" width="92%" :title="modifyTitle" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap modify-modal">
+					<div class="inp-list-line">
+						<div class="line-label">分类名称</div>
+						<div class="line-input">
+							<input type="text" v-model="modifyForm.categoryName" :adjust-position="false" class="inp-input" placeholder="填价格,图片可当商品卖(选填)" />
+						</div>
+					</div>
+					<div class="inp-list-line">
+						<div class="line-label">图片</div>
+						<div class="line-input flex-strat">
+							<app-uploader :multiple="false" ref="appUploader" :imgList.sync="modifyForm.img" />
+						</div>
+					</div>
+					<div class="prompt-text">建议尺寸 500X500</div>
+					<div class="inp-list-line">
+						<div class="line-label">排序</div>
+						<div class="line-input">
+							<input type="text" v-model="modifyForm.inTurn" :adjust-position="false" class="inp-input" placeholder="默认排序最新在前面" />
+						</div>
+					</div>
+					<div class="inp-list-line switch-wrap">
+						<div class="line-label">启用状态</div>
+						<div class="line-input flex-strat">
+							<switch :checked="modifyForm.status == '0' ? false : true" @change="switchChangeFn" />
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 删除提示 -->
+		<modal-module :show="delModal" :maskClosable="false" @cancel="modalCancel" @click="delModalClick" content="确定删除该分类吗?" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+import ModalModule from '@/components/plugin/modal'
+import AppUploader from '@/components/app-uploader'
+import OperateModule from '@/admin/home/components/module/operate'
+import AppWrapperEmpty from '@/components/app-wrapper-empty'
+import { list } from '@/mixins'
+// api
+import { categoryListB, categoryStatusB, categoryAddB, categoryUpdateB, categoryDelB } from '@/api/goods'
+export default {
+	name: 'category-manage',
+	components: {
+		ModalModule,
+		AppUploader,
+		OperateModule,
+		AppWrapperEmpty
+	},
+	mixins: [list],
+	data() {
+		return {
+			modifyModal: false,
+			modifyTitle: '添加',
+			modifyForm: {
+				categoryName: '',
+				img: [],
+				inTurn: 0,
+				status: 1
+			},
+			// 删除弹窗
+			delModal: false,
+			// operate
+			operateShow: false,
+			operateData: {},
+			operateIndex: null,
+			operateTop: 0
+		}
+	},
+	computed: {
+		btnData() {
+			return [
+				{
+					text: '编辑',
+					icon: 'iconbianji',
+					click: () => {
+						// this.operateShow = false
+						this.modifyModal = true
+						this.modifyTitle = '编辑'
+
+						this.modifyForm = {
+							categoryName: this.operateData.categoryName,
+							img: [this.operateData.img],
+							inTurn: this.operateData.inTurn,
+							status: this.operateData.status
+						}
+					}
+				},
+				{
+					text: this.operateData.status == 1 ? '禁用' : '启用',
+					icon: this.operateData.status == 1 ? 'iconjinyong' : 'iconqiyong',
+					click: () => {
+						this.changeStatusFn()
+					}
+				},
+				{
+					text: '删除',
+					icon: 'iconshanchu1',
+					click: () => {
+						// this.operateCancle()
+						this.delModal = true
+					}
+				}
+				// {
+				// 	text: '分享',
+				// 	icon: 'iconfenxiang1',
+				// 	click: () => {
+				// 		this.$msg('功能开发中...')
+				// 	}
+				// }
+			]
+		}
+	},
+	onPullDownRefresh() {
+		this.resetList()
+		this._list().then(res => {
+			uni.stopPullDownRefresh()
+		})
+	},
+	onReachBottom() {
+		if (!this.list.finished) {
+			this._list().then(res => {
+				uni.stopPullDownRefresh()
+			})
+		} else {
+			uni.stopPullDownRefresh()
+		}
+	},
+	onLoad() {
+		// this.init()
+	},
+	methods: {
+		async init() {
+			this._list()
+		},
+		_list() {
+			return categoryListB().then(res => {
+				let data = {
+					code: res.code,
+					msg: res.msg,
+					data: {
+						list: res.data
+					}
+				}
+				this.completes(data)
+			})
+		},
+		// modal
+		_categoryAddOrEditB() {
+			if (!this.modifyForm.categoryName) {
+				this.$msg('请输入分类名称!')
+				return false
+			}
+			let host = this.modifyTitle == '编辑' ? categoryUpdateB : categoryAddB
+			let form = JSON.parse(JSON.stringify(this.modifyForm))
+			form.img = this.$util.imgSubstr(form.img)
+			form.img = form.img.join()
+			if (this.modifyTitle == '编辑') {
+				form.categoryId = this.operateData.id
+			}
+			host({
+				...form
+			}).then(res => {
+				this.$msg('操作成功!')
+				this.modalCancel()
+				this.operateCancle()
+				setTimeout(() => {
+					this.resetList()
+					this._list()
+				}, 1000)
+			})
+		},
+		// 操作
+		addCategoryFn() {
+			this.resetForm()
+			this.modifyModal = true
+			this.modifyTitle = '新增'
+		},
+		resetForm() {
+			this.modifyForm = {
+				categoryName: '',
+				img: [],
+				inTurn: 0,
+				status: 1
+			}
+		},
+		modifyModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				this._categoryAddOrEditB()
+			}
+		},
+		modalCancel() {
+			this.delModal = false
+			this.modifyModal = false
+		},
+		switchChangeFn(e) {
+			this.modifyForm.status = e.detail.value ? 1 : 0
+		},
+		delModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				console.log('this.operateData', this.operateData)
+				categoryDelB({ categoryId: this.operateData.id }).then(res => {
+					this.modalCancel()
+					this.operateCancle()
+					this.$msg('删除成功!')
+					this.resetList()
+					this._list()
+				})
+			}
+		},
+		// operate
+		operateFn(item, index) {
+			if (this.operateIndex == index) {
+				this.operateCancle()
+			} else {
+				this.operateData = item
+				this.operateIndex = index
+				this.operateShow = true
+				this.operateTop = (index + 1) * 191
+			}
+		},
+		operateCancle() {
+			this.operateData = {}
+			this.operateIndex = null
+			this.operateShow = false
+		},
+		changeStatusFn() {
+			let status = this.operateData.status == 1 ? 0 : 1
+			categoryStatusB({
+				categoryId: this.operateData.id,
+				status: status
+			}).then(res => {
+				this.list.data[this.operateIndex].status = status
+				this.operateCancle()
+				this.$msg('操作成功!')
+			})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		min-height: calc(100vh - 100px);
+		padding-bottom: 100px;
+	}
+	// list
+	.list-wrap {
+		position: relative;
+		background-color: #fff;
+		.list {
+			height: 130px;
+			@include disFlex(center, flex-start);
+			padding: 30px 0;
+			margin: 0 30px;
+			color: $fontColor3;
+			border-bottom: 1px solid $borderColor;
+			.list-index {
+				width: 50px;
+			}
+			.list-img {
+				width: 130px;
+				height: 130px;
+				img {
+					height: 100%;
+				}
+			}
+			.list-det {
+				width: calc(100% - 200px);
+				margin-left: 20px;
+				& > div {
+					margin-top: 14px;
+					&:first-child {
+						margin-top: 0;
+					}
+				}
+				.list-operate {
+					@include disFlex(center, space-between);
+					.operate-det {
+						& > span {
+							margin-left: 60px;
+							&:first-child {
+								margin-left: 0;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	// button
+	.app-footer {
+		justify-content: flex-end;
+		.admin-button-com {
+			width: 200px;
+			margin-right: 30px;
+		}
+	}
+	// 编辑弹窗
+	.modify-modal {
+		.prompt-text {
+			color: red;
+			position: relative;
+			right: 52px;
+			bottom: 24px;
+			// margin-bottom: 10px;
+		}
+		.line-label {
+			width: 140px;
+			flex-shrink: 0;
+		}
+		.switch-wrap {
+			margin-top: 30px;
+		}
+	}
+</style>

+ 104 - 0
store/src/admin-goods/freight.vue

@@ -0,0 +1,104 @@
+<template>
+	<div class="app-content">
+		<div class="module-com new_wrap">
+			<div class="module-det">
+				<div>
+					<input type="text" v-model="form.first" class="setting-inp" />
+					<span>公里内免运费,超过每增加1公里,</span>
+				</div>
+				<div>
+					<span>运费增加</span>
+					<input type="text" v-model="form.add" class="setting-inp" />
+					<span>元。</span>
+				</div>
+			</div>
+		</div>
+		<div class="admin-button-com blue big" @click="confirmFn">确认</div>
+	</div>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex'
+import { getUser } from '@/utils/auth'
+import { freightSet } from '@/api/goods'
+export default {
+	name: 'setting-freight',
+	data() {
+		return {
+			form: {
+				first: 0,
+				add: 0
+			}
+		}
+	},
+	computed: {
+		...mapGetters({ userInfo: 'getUser' })
+	},
+	onLoad() {},
+	mounted() {
+		// this.init()
+	},
+	watch: {
+		userInfo() {
+			if (!this.$util.isEmpty(this.userInfo)) {
+				this.form.first = this.userInfo.extend.freeDistance
+				this.form.add = this.userInfo.extend.freight
+			}
+		}
+	},
+	methods: {
+		init() {
+			getUser().then(res => {
+				this.form.first = this.userInfo.extend.freeDistance
+				this.form.add = this.userInfo.extend.freight
+			})
+		},
+		confirmFn() {
+			freightSet(this.form).then(res => {
+				this.$msg('修改成功!')
+			})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.module-com {
+		margin-bottom: 20px;
+		padding: 30px;
+		background-color: #fff;
+		color: $fontColor2;
+	}
+	.admin-button-com {
+		width: calc(100% - 100px);
+		margin: 60px 30px 0;
+	}
+	.new_wrap {
+		.module-det {
+			color: $fontColor3;
+			font-size: 28px;
+			& > div {
+				@include disFlex(center, flex-start);
+				flex-wrap: wrap;
+				margin-bottom: 20px;
+				&:last-child {
+					margin-bottom: 0;
+				}
+			}
+			.setting-inp {
+				width: 140px;
+				height: 70px;
+				border: 2px solid $borderColor;
+				border-radius: 10px;
+				margin: 0 16px;
+				text-align: center;
+				&:first-child {
+					margin-left: 0;
+				}
+				&:last-child {
+					margin-right: 0;
+				}
+			}
+		}
+	}
+</style>

+ 92 - 0
store/src/admin-goods/goods-name.vue

@@ -0,0 +1,92 @@
+<template>
+	<div class="app-content">
+		<!-- 商品 -->
+		<div class="prompt-text">客户想买此商品,但没价格,请设置</div>
+		<div class="img-wrap">
+			<img class="goods-img" :src="data.imgUrl" mode="widthFix" alt="商品图片" />
+		</div>
+		<!-- 信息 -->
+		<div class="input-line-wrap">
+			<tui-list-cell class="line-cell" :hover="false">
+				<div class="tui-title">名称</div>
+				<input placeholder-class="phcolor" v-model="form.name" class="tui-input" name="name" placeholder="请输入" type="text" />
+			</tui-list-cell>
+			<tui-list-cell class="line-cell" :hover="false">
+				<div class="tui-title">价格</div>
+				<input placeholder-class="phcolor" v-model="form.price" class="tui-input" name="price" placeholder="请输入" maxlength="50" type="number" />
+				<div class="tui-prompt">元</div>
+			</tui-list-cell>
+		</div>
+		<!-- button -->
+		<button class="admin-button-com blue big confirm-btn" @click="confirmFn">确定</button>
+	</div>
+</template>
+
+<script>
+import TuiListCell from '@/components/plugin/list-cell'
+// api
+import { getDetB, picRemark } from '@/api/img-store'
+export default {
+	name: 'goods-name-setting',
+	components: {
+		TuiListCell
+	},
+	data() {
+		return {
+			data: {},
+			form: {
+				picIdList: [],
+				price: 0,
+				name: '',
+				categoryIdList: []
+			}
+		}
+	},
+	onLoad() {
+		// this.init()
+	},
+	methods: {
+		init() {
+			this._getDet()
+		},
+		_getDet() {
+			getDetB({ id: this.option.id }).then(res => {
+				if (this.$util.isEmpty(res.data)) return
+				this.data = res.data
+				Object.keys(this.form).forEach((i, index) => {
+					this.form[i] = res.data[i]
+				})
+				this.form.picIdList = [res.data.id]
+				console.log(this.form)
+			})
+		},
+		confirmFn() {
+			picRemark(this.form).then(res => {
+				this.$msg('修改成功!')
+			})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.prompt-text {
+		color: $fontColor2;
+		font-size: 32px;
+		padding: 36px 0;
+		text-align: center;
+	}
+	.img-wrap {
+		width: 80%;
+		background-color: #fff;
+		margin: 0 auto 54px;
+		padding: 20px;
+		.goods-img {
+			width: 100%;
+		}
+	}
+	.confirm-btn {
+		width: calc(100% - 60px);
+		margin: 60px 30px 0;
+	}
+</style>

+ 448 - 0
store/src/admin-goods/img-store.vue

@@ -0,0 +1,448 @@
+<template>
+	<div class="app-content" @click="dropdownShow = false">
+		<!-- bar -->
+		<div class="bar-wrap">
+			<dropdown-list :show="dropdownShow" :top="80" :width="750" :height="400">
+				<template v-slot:selectionbox>
+					<div class="sel-open-btn" @click.stop="dropdownShow = dropdownShow ? false : true">
+						<span>{{ categoryName }}</span>
+						<i class="iconfont iconsanjiao_xia"></i>
+					</div>
+				</template>
+				<template v-slot:dropdownbox>
+					<div class="sel-list-wrap">
+						<scroll-view scroll-y class="tui-dropdown-scroll">
+							<div class="sel-list" v-for="(item, index) in categoryData" :key="index" @click.stop="selCategory(item)">{{ item.categoryName }}</div>
+						</scroll-view>
+					</div>
+				</template>
+			</dropdown-list>
+			<div class="share-wrap" @click.stop="$msg('开发中!')">
+				<i class="iconfont iconfenxiang1"></i>
+				<span>分享</span>
+			</div>
+		</div>
+		<!-- list -->
+		<div class="list-wrap">
+			<block v-if="!$util.isEmpty(list.data)">
+				<div class="list" v-for="(item, index) in list.data" :key="index">
+					<div class="list-img" :style="{ height: listWidth + 'px' }">
+						<img :src="item.imgUrl" alt="商品图片" mode="widthFix" />
+					</div>
+					<div class="list-det">
+						<div class="app-size-28">{{ item.name }}</div>
+						<div class="flex-center-between">
+							<div v-if="index == 4" class="app-price">¥{{ item.price }}</div>
+							<div v-else class="app-color-3">暂无</div>
+							<div class="operate-icon-wrap" @click="operateFn(item, index)">
+								<div class="operate-icon">
+									<i class="iconfont" :class="[ operateIndex == index ? 'iconcaozuojihuo' : 'iconcaozuo']"></i>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+				<!-- 操作 -->
+				<operate-module v-show="operateShow" :top="operateTop" :right="operateRight" :btnData="btnData" />
+			</block>
+			<block v-else>
+				<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+			</block>
+		</div>
+		<app-uploader :multiple="false" ref="appUploader" :uploadPicApi="picAdd" @resultData="chooseImage" :imgList.sync="form.picIdList">
+			<span></span>
+		</app-uploader>
+		<!-- button -->
+		<div class="app-footer">
+			<button class="admin-button-com middle default" @click="pageTo('/admin/goodsManage/category')">查看分类</button>
+			<button class="admin-button-com middle blue" @click="$refs.appUploader.chooseImage()">新增</button>
+		</div>
+		<!-- 图片上传成功弹窗! -->
+		<modal-module :show="settingModal" :custom="true" width="92%" @cancel="modalCancel" @click="modalClick" padding="30rpx 30rpx">
+			<template>
+				<div class="upload-confirm-wrap">
+					<!--  -->
+					<div class="modal-tit">
+						<i class="iconfont iconxuanzhong"></i>
+						<span>图片上传成功!</span>
+					</div>
+					<!-- 选择分类 -->
+					<div class="sel-wrap">
+						<div class="sel-tit">选择分类(可多选)</div>
+						<div class="sel-btn">
+							<block v-for="(item, index) in categoryData" :key="index">
+								<button class="admin-button-com" :class="[form.categoryIdList.includes(item.id) ? '' : 'default']" @click="selCategoryFn(item)">{{ item.categoryName || '暂无' }}</button>
+							</block>
+						</div>
+					</div>
+					<!-- 输入框 -->
+					<div class="app-modal-input-wrap">
+						<div class="inp-list-line">
+							<div class="line-label">售价</div>
+							<div class="line-input">
+								<input type="text" v-model="form.price" class="inp-input" placeholder="填价格,图片可当商品卖(选填)" />
+								<div class="inp-prompt">元</div>
+							</div>
+						</div>
+						<div class="inp-list-line">
+							<div class="line-label">名称</div>
+							<div class="line-input">
+								<input type="text" v-model="form.name" class="inp-input" placeholder="选填" />
+							</div>
+						</div>
+					</div>
+					<!-- button -->
+					<div class="redeem-btn">
+						<button class="admin-button-com default big" @click="modalCancel">取消</button>
+						<button class="admin-button-com blue big" @click="saveFn">确定</button>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 删除提示 -->
+		<modal-module :show="delModal" @cancel="modalCancel" @click="delModalClick" content="确定删除该广告吗?" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+	import { mapGetters } from 'vuex'
+	import ModalModule from '@/components/plugin/modal'
+	import DropdownList from '@/components/plugin/dropdown-list'
+	import AppWrapperEmpty from '@/components/app-wrapper-empty'
+	import AppUploader from '@/components/app-uploader'
+	import OperateModule from '@/admin/home/components/module/operate'
+	import { list } from '@/mixins'
+	// api
+	import { getCategory } from '@/utils/config'
+	import { getListB, picRemark, picAdd, picDel, picTop } from '@/api/img-store'
+	export default {
+		name: 'image-store',
+		components: {
+			ModalModule,
+			DropdownList,
+			AppWrapperEmpty,
+			AppUploader,
+			OperateModule
+		},
+		mixins: [list],
+		data() {
+			return {
+				picAdd: picAdd,
+				listHei: 76,
+				listWidth: 76,
+				categoryName: '全部',
+				categoryId: -1,
+				// modal
+				imgList: [],
+				form: {
+					picIdList: [],
+					price: '',
+					name: '',
+					categoryIdList: []
+				},
+				dropdownShow: false,
+				settingModal: false,
+				// ==
+				delModal: false,
+				// operate
+				operateIndex: null,
+				operateShow: false,
+				operateData: {},
+				operateTop: 0,
+				operateRight: 30,
+				btnData: [
+					{
+						text: '编辑',
+						icon: 'iconbianji',
+						click: () => {
+							this.modalCancel()
+							this.form.picIdList = [this.operateData.id]
+							this.settingModal = true
+						}
+					},
+					{
+						text: '置顶',
+						icon: 'iconxiajia',
+						click: () => {
+							picTop({ id: this.operateData.id }).then(res => {
+								this.operateCloseFn()
+								this.$msg('置顶成功!')
+								setTimeout(() => {
+									this.resetList()
+									this._list()
+								}, 1000)
+							})
+						}
+					},
+					{
+						text: '删除',
+						icon: 'iconshanchu1',
+						click: () => {
+							this.delModal = true
+						}
+					},
+					{
+						text: '分享',
+						icon: 'iconfenxiang1',
+						click: () => {
+							this.delModal = true
+						}
+					}
+				]
+			}
+		},
+		computed: {
+			...mapGetters({ categoryData: 'getCategory' })
+		},
+		onLoad() {
+			// this.init()
+		},
+		methods: {
+			// 获取高度
+			getListHei(dom) {
+				let listDom = uni.createSelectorQuery().select(dom)
+				listDom
+					.boundingClientRect(data => {
+						this.listHei = data.height
+					})
+					.exec()
+			},
+			async init() {
+				uni.getSystemInfo({
+					success: res => {
+						console.log('江总', res)
+						this.listWidth = parseInt(res.screenWidth * 0.3)
+					}
+				})
+				getCategory()
+				this._list()
+			},
+			_list() {
+				return getListB({
+					categoryId: this.categoryId,
+					page: this.list.page
+				}).then(res => {
+					this.completes(res)
+					if (!this.$util.isEmpty(list.data)) {
+						setTimeout(() => {
+							this.getListHei('.list')
+						}, 100)
+					}
+				})
+			},
+			saveFn() {
+				picRemark(this.form).then(res => {
+					this.$msg('操作成功!')
+					this.modalCancel()
+					this.operateCancle()
+					setTimeout(() => {
+						this.resetList()
+						this._list()
+					}, 1000)
+				})
+			},
+			// 操作
+			selCategory(item) {
+				this.categoryName = item.categoryName
+				this.categoryId = item.id
+				this.dropdownShow = false
+				this.resetList()
+				this._list()
+			},
+			selCategoryFn(item) {
+				let index = this.form.categoryIdList.findIndex(e => e == item.id)
+				if (index == -1) {
+					this.form.categoryIdList.push(item.id)
+				} else {
+					this.form.categoryIdList.splice(index, 1)
+				}
+			},
+			// 图片上传成功
+			chooseImage(e) {
+				console.log('图片上传成功', e)
+				this.form.picIdList = [e.id]
+				this.settingModal = true
+			},
+			modalCancel() {
+				this.delModal = false
+				this.settingModal = false
+				this.form = {
+					picIdList: [],
+					price: '',
+					name: '',
+					categoryIdList: []
+				}
+			},
+			delModalClick(e) {
+				if (e.index === 0) {
+					this.modalCancel()
+				} else {
+					picDel({ id: this.operateData.id }).then(res => {
+						this.modalCancel()
+						this.operateCancle()
+						this.$msg('删除成功!')
+						setTimeout(() => {
+							this.resetList()
+							this._list()
+						}, 1000)
+					})
+				}
+			},
+			// operate
+			operateFn(item, index) {
+				if (this.operateIndex == index) {
+					this.operateCancle()
+				} else {
+					this.operateData = item
+					this.operateIndex = index
+					this.operateShow = true
+					this.operateTop = (index + 1) * (this.listHei + 10)
+					let rightIndex = (index + 1) % 3
+					this.operateRight = rightIndex == 0 ? 20 : rightIndex == 1 ? 348 : 160
+				}
+			},
+			operateCancle() {
+				this.operateData = {}
+				this.operateIndex = null
+				this.operateShow = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		min-height: calc(100vh - 100px);
+		// padding-top: 100px;
+		padding-bottom: 100px;
+	}
+	// bar
+	.bar-wrap {
+		// position: fixed;
+		// top: 0;
+		width: 100%;
+		height: 80px;
+		background-color: #fff;
+		@include disFlex(center, space-between);
+		font-size: 28px;
+		color: $fontColor2;
+		& > div {
+			padding: 0 30px;
+		}
+		.share-wrap {
+			position: absolute;
+			right: 0;
+		}
+		.iconfont {
+			color: $fontColor2;
+		}
+		.iconsanjiao_xia {
+			font-size: 24px;
+			margin-left: 10px;
+		}
+		.iconfenxiang1 {
+			font-size: 36px;
+			margin-right: 10px;
+		}
+		// 下拉框
+		.sel-open-btn {
+			width: 30%;
+			height: 80px;
+			line-height: 80px;
+			padding-left: 30px;
+		}
+		.sel-list-wrap {
+			background-color: #fff;
+			box-shadow: 6px 6px 10px #cccccc;
+			.sel-list {
+				padding: 20px 30px;
+				// border-top: 1px solid $borderColor;
+			}
+		}
+		.tui-dropdown-scroll {
+			height: 400px;
+		}
+	}
+	// list
+	.list-wrap {
+		// height: calc(100vh - 220px);
+		// @include disFlex(flex-start, flex-start);
+		display: flex;
+		align-items: flex-start;
+		flex-wrap: wrap;
+		position: relative;
+		padding-top: 20px;
+		.list {
+			width: 30%;
+			margin-left: 2.5%;
+			margin-bottom: 20px;
+			background-color: #fff;
+			.list-img {
+				min-width: 224px;
+				img {
+					width: 100%;
+					height: 100%;
+				}
+			}
+			.list-det {
+				padding: 10px;
+				& > div {
+					margin-top: 10px;
+				}
+				.iconfont {
+					color: $fontColor3;
+				}
+			}
+		}
+	}
+	// 按钮
+	.app-footer {
+		justify-content: space-evenly;
+		.admin-button-com {
+			width: 46%;
+		}
+	}
+	// 弹窗
+	.upload-confirm-wrap {
+		.modal-tit {
+			@include disFlex(center, center);
+			font-size: 40px;
+			margin-top: 30px;
+			margin-bottom: 50px;
+			.iconfont {
+				color: #09bb07;
+				margin-right: 20px;
+				font-size: 50px;
+			}
+		}
+		//  分类
+		.sel-wrap {
+			color: $fontColor2;
+			font-size: 32px;
+			.sel-btn {
+				@include disFlex(center, flex-start);
+				flex-wrap: wrap;
+				padding: 10px 0 40px;
+				.admin-button-com {
+					// width: 170px;
+					margin-right: 20px;
+					margin-top: 20px;
+					padding-top: 16px;
+					padding-bottom: 16px;
+					border-radius: 4px;
+					// &:nth-child(3n + 1) {
+					// 	margin-left: 0;
+					// }
+				}
+			}
+		}
+		.redeem-btn {
+			@include disFlex(center, space-between);
+			margin-top: 40px;
+			width: 100%;
+			.admin-button-com {
+				width: 48%;
+			}
+		}
+	}
+</style>

+ 456 - 0
store/src/admin-goods/list.vue

@@ -0,0 +1,456 @@
+<template>
+	<div class="app-content" @click="operateBottomShow = false">
+		<app-tabs :tabs="tabs" :isFixed="true" :currentTab="tabIndex" @change="change" itemWidth="50%" />
+		<!-- 中间 -->
+		<div class="app-middle">
+			<scroll-view scroll-y scroll-with-animation class="tab-view" :scroll-top="scrollTop" :style="{height:height+'px'}">
+				<div v-for="(item,index) in tabbar" :key="index" class="tab-bar-item" :class="[currentTab==index ? 'active' : '']" :data-current="index" @tap.stop="swichNav($event ,item)">
+					<text>{{item.categoryName || '暂无'}}</text>
+				</div>
+			</scroll-view>
+			<block v-for="(item,index) in tabbar" :key="index">
+				<scroll-view scroll-y class="right-box" :style="{height:height+'px'}" v-if="currentTab==index">
+					<!--内容部分 start -->
+					<block v-if="!$util.isEmpty(list.data)">
+						<div class="page-view">
+							<div class="goods-list" v-for="(item, index) in list.data" :key="index">
+								<div class="goods-list-top">
+									<div class="img-blo">
+										<img :src="item.imgList[0].middle" alt="商品图" mode="center" />
+									</div>
+									<div class="goods-det">
+										<div class="goods-det-top">
+											<div class="goods-name">{{ item.goodsName }}</div>
+											<!-- <div class="goods-sales">已售{{ item.sold }}</div> -->
+											<!-- <div class="goods-sales">{{ item.categoryName }}</div> -->
+										</div>
+										<div class="operate-wrap">
+											<div class="goods-price">¥{{ item.price }}</div>
+											<div class="operate-icon-wrap" @click="operateFn(item, index)">
+												<div class="operate-icon">
+													<i class="iconfont" :class="[ index == operateIndex ? 'iconcaozuojihuo' : 	'iconcaozuo']"></i>
+												</div>
+											</div>
+										</div>
+									</div>
+								</div>
+								<div class="goods-list-bottom flex-center-between">
+									<div>已售: {{ item.sold }}</div>
+									<div>销量: {{ item.stock }}</div>
+									<div>浏览: {{ item.viewNum }}</div>
+								</div>
+							</div>
+						</div>
+						<!-- 操作 -->
+						<operate-module v-show="operateShow" :top="operateTop" :right="30" :btnData="btnData" />
+					</block>
+					<block v-else>
+						<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+					</block>
+					<!--内容部分 end -->
+				</scroll-view>
+			</block>
+		</div>
+		<!-- 底部 -->
+		<div class="app-footer">
+			<div class="btn-list other-btn" @click.stop="changeOperateShowFn">
+				<i class="iconfont iconxiala" :class="[operateBottomShow ? 'animate-open' : 'animate-close']"></i>
+				<span>其他设置</span>
+			</div>
+			<div class="btn-list">
+				<button class="admin-button-com default" @click="pageTo('/admin/goodsManage/category')">分类管理</button>
+			</div>
+			<div class="btn-list">
+				<button class="admin-button-com blue" @click="pageTo('/admin/goodsManage/add')">新增商品</button>
+			</div>
+		</div>
+		<!-- 操作弹窗 -->
+		<operate-line-module v-if="operateBottomShow" :btnData="btnBottomData" :bottom="120" :right="528" />
+		<!-- 删除提示 -->
+		<modal-module :show="delModal" :maskClosable="false" @cancel="modalCancel" @click="delModalClick" content="确定删除该商品吗?" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+	import AppTabs from '@/components/plugin/tabs'
+	import OperateModule from '@/admin/home/components/module/operate'
+	import OperateLineModule from '@/admin/home/components/module/operate-line'
+	import AppWrapperEmpty from '@/components/app-wrapper-empty'
+	import ModalModule from '@/components/plugin/modal'
+	// api
+	import { categoryListB, getCategoryGoodsB, delB, changeStatusB } from '@/api/goods'
+	import { list } from '@/mixins'
+	export default {
+		name: 'goods-manage-list',
+		components: {
+			AppTabs,
+			OperateLineModule,
+			OperateModule,
+			AppWrapperEmpty,
+			ModalModule
+		},
+		mixins: [list],
+		data() {
+			return {
+				// tabs
+				tabIndex: 0,
+				tabs: [
+					{
+						name: '出售中'
+					},
+					{
+						name: '已下架'
+					}
+				],
+				// 中间
+				tabbar: [],
+				height: 0, // scroll-view高度
+				currentTab: 0, // 预设当前项的值
+				scrollTop: 0, // tab标题的滚动条位置
+				form: {
+					categoryId: ''
+				},
+				// 删除弹窗
+				delModal: false,
+				// 操作菜单
+				operateData: {},
+				operateShow: false,
+				operateIndex: null,
+				operateTop: 0,
+				// 底部操作
+				operateBottomShow: false,
+				btnBottomData: [
+					// {
+					// 	name: '图库管理',
+					// 	click: () => this.$util.pageTo('/admin/goodsManage/img-store')
+					// },
+					{
+						name: '运费设置',
+						click: () => this.$util.pageTo('/admin/goodsManage/freight')
+					},
+					{
+						name: '通用简介',
+						click: () => {
+							// alert('请在电脑端进行设置!')
+							this.$msg('请在电脑端进行设置!')
+						}
+					},
+					{
+						name: '自动涨价',
+						click: () => this.$util.pageTo('/admin/goodsManage/price-increase')
+					}
+				]
+			}
+		},
+		computed: {
+			btnData() {
+				return [
+					// {
+					// 	text: '置顶',
+					// 	icon: 'iconzhiding',
+					// 	click: () => {
+					// 		this.delModal = true
+					// 	}
+					// },
+					{
+						text: '编辑',
+						icon: 'iconbianji',
+						click: () => {
+							this.$util.pageTo({
+								url: '/admin/goodsManage/add',
+								query: {
+									type: this.tabIndex,
+									id: this.operateData.id
+								}
+							})
+						}
+					},
+					{
+						text: this.operateData.status == 1 ? '下架' : '上架',
+						icon: this.operateData.status == 1 ? 'iconxiajia' : 'iconqiyong',
+						click: () => {
+							this.changeStatusFn()
+						}
+					},
+					{
+						text: '删除',
+						icon: 'iconshanchu1',
+						click: () => {
+							this.delModal = true
+						}
+					}
+					// {
+					// 	text: '分享',
+					// 	icon: 'iconfenxiang1',
+					// 	click: () => {
+					// 		this.$msg('功能开发中。。。')
+					// 	}
+					// }
+				]
+			}
+		},
+		onLoad: function() {
+			if (this.$util.isLogin()) {
+				setTimeout(() => {
+					uni.getSystemInfo({
+						success: res => {
+							this.height = res.windowHeight - 90
+							this.sInit()
+						}
+					})
+				}, 50)
+			}
+		},
+		methods: {
+			async sInit() {
+				this._getClass()
+				this._list()
+			},
+			// 分类
+			_getClass() {
+				categoryListB().then(res => {
+					this.tabbar = res.data
+				})
+			},
+			// 列表
+			_list() {
+				return getCategoryGoodsB({
+					status: this.tabIndex == 0 ? 1 : 0,
+					...this.form
+				}).then(res => {
+					this.completes(res)
+				})
+			},
+			// tabs
+			change(e) {
+				if (this.tabIndex == e.index) {
+					return false
+				} else {
+					this.tabIndex = e.index
+					this.operateCloseFn()
+					this.resetList()
+					this._list()
+				}
+			},
+			// 操作按钮
+			operateFn(item, index) {
+				if (this.operateIndex == index) {
+					this.operateCloseFn()
+				} else {
+					this.operateData = item
+					this.operateData.index = index
+					this.operateIndex = index
+					this.operateTop = (index + 1) * 224 - 20
+					this.operateShow = true
+				}
+			},
+			// 关闭操作按钮
+			operateCloseFn() {
+				this.operateData = {}
+				this.operateIndex = null
+				this.operateShow = false
+			},
+			// 点击标题切换当前页时改变样式
+			swichNav(e, item) {
+				let cur = e.currentTarget.dataset.current
+				if (this.currentTab == cur) {
+					return false
+				} else {
+					this.currentTab = cur
+					this.form.categoryId = item.id
+					this.resetList()
+					this._list()
+					// this.checkCor()
+				}
+			},
+			// 判断当前滚动超过一屏时,设置tab标题滚动条。
+			checkCor() {
+				let that = this
+				// 这里计算按照实际情况进行修改,动态数据要进行动态分析
+				// 思路:窗体高度/单个分类高度 200rpx 转px计算 =>得到一屏幕所显示的个数,结合后台传回分类总数进行计算
+				// 数据很多可以多次if判断然后进行滚动距离计算即可
+				if (that.currentTab > 7) {
+					that.scrollTop = 500
+				} else {
+					that.scrollTop = 0
+				}
+			},
+			// operate
+			// operateCancle() {
+			// 	this.operateData = {}
+			// 	this.operateIndex = null
+			// 	this.operateShow = false
+			// },
+			changeOperateShowFn() {
+				this.operateBottomShow = !this.operateBottomShow
+			},
+			changeStatusFn() {
+				let status = this.operateData.status == 1 ? 0 : 1
+				changeStatusB({
+					id: this.operateData.id,
+					status: status
+				}).then(res => {
+					this.list.data[this.operateIndex].status = status
+					this.operateCloseFn()
+					this.$msg('操作成功!')
+				})
+			},
+			// delModal
+			modalCancel() {
+				this.delModal = false
+			},
+			delModalClick(e) {
+				if (e.index === 0) {
+					this.modalCancel()
+				} else {
+					delB({ id: this.operateData.id }).then(res => {
+						this.modalCancel()
+						this.operateCloseFn()
+						this.$msg('删除成功!')
+						this.resetList()
+						this._list()
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		min-height: calc(100vh - 80px);
+		padding-top: 80px;
+		background-color: #fff;
+		// padding-bottom: 100px;
+	}
+
+	page {
+		background: #fff;
+	}
+
+	/* 左侧导航布局 start*/
+
+	/* 隐藏scroll-view滚动条*/
+
+	::-webkit-scrollbar {
+		width: 0;
+		height: 0;
+		color: transparent;
+	}
+
+	.tab-view {
+		/* height: 100%; */
+		width: 200upx;
+		position: fixed;
+		left: 0;
+		z-index: 10;
+		background-color: #f0f2f6;
+
+		.tab-bar-item {
+			width: 200upx;
+			height: 110upx;
+			box-sizing: border-box;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			font-size: 26upx;
+			color: #444;
+			font-weight: 400;
+		}
+
+		.active {
+			position: relative;
+			color: $mainColor;
+			font-size: 26px;
+			background: #fff;
+		}
+
+		.active::before {
+			content: '';
+			position: absolute;
+			border-left: 8upx solid $mainColor;
+			height: 100%;
+			left: 0;
+		}
+	}
+
+	/* 左侧导航布局 end*/
+
+	.right-box {
+		width: 100%;
+		position: fixed;
+		padding-left: 220upx;
+		box-sizing: border-box;
+		left: 0;
+		.page-view {
+			width: 100%;
+			overflow: hidden;
+			box-sizing: border-box;
+			padding-bottom: env(safe-area-inset-bottom);
+			.goods-list {
+				margin: 40px 0;
+				.goods-list-top {
+					position: relative;
+					@include disFlex(flex-start, flex-start);
+				}
+				.goods-list-bottom {
+					width: 74%;
+					margin-top: 16px;
+					color: $fontColor2;
+				}
+				.img-blo {
+					width: 130px;
+					height: 130px;
+					margin-right: 20px;
+				}
+				.goods-det {
+					width: calc(100% - 150px);
+					// padding-top: 18px;
+					font-size: 28px;
+					.operate-wrap {
+						@include disFlex(flex-end, space-between);
+					}
+					.operate-icon-wrap {
+						left: -20px;
+					}
+					.goods-name {
+						margin-bottom: 10px;
+					}
+					.goods-sales {
+						color: $fontColor3;
+						font-size: 24px;
+					}
+					.goods-price {
+						margin-top: 50px;
+						color: #ff2842;
+						font-weight: bold;
+					}
+				}
+			}
+		}
+	}
+	// 底部
+	.app-footer {
+		justify-content: space-between;
+		.btn-list {
+			width: 33.33%;
+			border-left: 1px solid $borderColor;
+			&:first-child {
+				border-left: 0;
+			}
+			.admin-button-com {
+				width: 160px;
+				padding-top: 16px;
+				padding-bottom: 16px;
+			}
+		}
+		.other-btn {
+			color: $fontColor2;
+			.iconfont {
+				font-size: 24px;
+				color: $fontColor3;
+				transform: scale(0.4);
+			}
+		}
+	}
+</style>

+ 168 - 0
store/src/admin-goods/price-increase.vue

@@ -0,0 +1,168 @@
+<template>
+	<div class="app-content">
+		<div class="module-com flex-center-between switch-blo">
+			<div class="app-size-32">开启自动涨价</div>
+			<div>
+				<switch :checked="form.riseSwitch == '0' ? false : true" @change="switchChangeFn" />
+			</div>
+		</div>
+		<block v-if="form.riseSwitch != 0">
+			<!-- 选项设置 -->
+			<div class="input-line-wrap new-wrap">
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">要涨价节日</div>
+					<div class="tui-input button-wrap">
+						<block v-for="(item, index) in festData" :key="index">
+							<button class="admin-button-com" :class="[form.festIdList.includes(item.id) ? '' : 'default']" @click="selFestFn(item)">{{ item.name || '暂无' }}</button>
+						</block>
+					</div>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">涨价方式</div>
+					<radio-group class="tui-input flex-center-between" @change="radioChange">
+						<label class="list" for="customLink">
+							<radio id="customLink" value="0" :checked="form.riseType == 0" />
+							<span class="checkbox-text">按百分比</span>
+						</label>
+						<label class="list" for="goodsLink">
+							<radio id="goodsLink" value="1" :checked="form.riseType == 1" />
+							<span class="checkbox-text">按金额</span>
+						</label>
+					</radio-group>
+				</tui-list-cell>
+				<block v-if="form.riseType == 0">
+					<tui-list-cell class="line-cell" :hover="false">
+						<div class="tui-title">比例</div>
+						<input v-model="form.riseAmount" placeholder-class="phcolor" class="tui-input" name="phone" placeholder="涨价10%,请输入10" maxlength="50" type="number" />
+					</tui-list-cell>
+				</block>
+				<block v-else>
+					<tui-list-cell class="line-cell" :hover="false">
+						<div class="tui-title">金额</div>
+						<input v-model="form.riseAmount" placeholder-class="phcolor" class="tui-input" name="phone" placeholder="涨价80元请输入80" maxlength="50" type="number" />
+					</tui-list-cell>
+				</block>
+			</div>
+			<div class="prompt-text">节日当天和前一天,勾选自动涨价的商品将统一按上面规则涨价。</div>
+		</block>
+		<button class="admin-button-com blue big confirm-btn" @click="setPrice">确定</button>
+	</div>
+</template>
+
+<script>
+	import { mapGetters } from 'vuex'
+	import TuiListCell from '@/components/plugin/list-cell'
+	// api
+	import { getFest } from '@/utils/config'
+	import { getRise, updateRise } from '@/api/goods'
+	export default {
+		name: 'setting-price-increase',
+		components: {
+			TuiListCell
+		},
+		data() {
+			return {
+				// radioVal: '0',
+				form: {
+					riseSwitch: '0',
+					riseType: '0',
+					festIdList: [],
+					riseAmount: ''
+				}
+			}
+		},
+		computed: {
+			...mapGetters({ festData: 'getFest' })
+		},
+		onLoad() {
+			// this.init()
+		},
+		methods: {
+			init() {
+				getFest().then(() => {
+					this._getDet()
+				})
+			},
+			_getDet() {
+				return getRise().then(res => {
+					if (this.$util.isEmpty(res.data)) return
+					res.data.festIdList = res.data.festIdList.map(e => e + '')
+					Object.keys(this.form).forEach((i, index) => {
+						this.form[i] = res.data[i]
+					})
+				})
+			},
+			setPrice() {
+				if (this.form.festIdList.length == 0) {
+					this.$msg('请先选择节日!')
+					return false
+				}
+				if (!this.form.riseAmount) {
+					this.$msg('请先输入比例或者金额!')
+					return false
+				}
+				updateRise(this.form).then(res => {
+					this.$msg('更新成功!')
+				})
+			},
+			selFestFn(item) {
+				let index = this.form.festIdList.findIndex(e => e == item.id)
+				if (index == -1) {
+					this.form.festIdList.push(item.id)
+				} else {
+					this.form.festIdList.splice(index, 1)
+				}
+			},
+			switchChangeFn(e) {
+				this.form.riseSwitch = e.detail.value ? '1' : '0'
+			},
+			radioChange(e) {
+				this.form.riseAmount = ''
+				this.form.riseType = e.detail.value
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.prompt-text {
+		color: $fontColor3;
+		padding-bottom: 20px;
+		padding-left: 30px;
+	}
+	.module-com {
+		margin-bottom: 20px;
+		padding: 30px;
+		background-color: #fff;
+		color: $fontColor2;
+		.module-tit {
+			font-size: 28px;
+		}
+	}
+	.confirm-btn {
+		width: calc(100% - 60px);
+		margin: 60px 30px 0;
+	}
+	.switch-blo {
+		padding: 15px 30px;
+	}
+	.new-wrap {
+		margin-bottom: 20px;
+		.checkbox-text {
+			color: $fontColor2;
+		}
+		.button-wrap {
+			justify-content: flex-start;
+			flex-wrap: wrap;
+			.admin-button-com {
+				padding-top: 12px;
+				padding-bottom: 12px;
+				margin-right: 20px;
+				border-radius: 4px;
+				// &:first-child {
+				// 	margin-left: 0;
+				// }
+			}
+		}
+	}
+</style>

+ 317 - 0
store/src/admin-official/apply.vue

@@ -0,0 +1,317 @@
+<template>
+	<div class="app-content">
+		<form @submit="formSubmit">
+			<div class="module-com">
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">花店名称</div>
+					<input v-model="form.name" placeholder-class="phcolor" class="tui-input" name="name" placeholder="请输入姓名" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false" :arrow="true" @click="openAddres">
+					<div class="tui-title">花店地址</div>
+					<div class="tui-input" v-if="form.province">{{ form.province + '-' + form.city }}</div>
+					<div class="tui-placeholder" v-else>请选择</div>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false" :arrow="true" @click="selRegionFn">
+					<div class="tui-title">详细地址</div>
+					<div class="tui-input" v-if="form.address">{{ form.address }}</div>
+					<div class="tui-placeholder" v-else>请选择详细地址</div>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">门牌号</div>
+					<input v-model="form.floor" placeholder-class="phcolor" class="tui-input" name="floor" placeholder="楼号门牌号(选填)" />
+				</tui-list-cell>
+			</div>
+			<!-- 手机号 -->
+			<div class="module-com">
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">手机号</div>
+					<input v-model="form.mobile" placeholder-class="phcolor" class="tui-input" name="mobile" placeholder="请输入" type="number" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell code-wrap" :hover="false">
+					<div class="tui-title">验证码</div>
+					<input v-model="form.code" placeholder-class="phcolor" class="tui-input" name="code" placeholder="请输入验证码" type="number" />
+					<div class="tui-code" v-if="isSend">{{ countDown + 's' }}</div>
+					<div class="tui-code" v-else @click="getCode">获取验证码</div>
+				</tui-list-cell>
+			</div>
+			<!-- 推荐人 -->
+			<div class="module-com recommend-wrap" v-if="!$util.isEmpty(merchantData)">
+				<div class="recommend-tag">推荐花店</div>
+				<div class="recommend-det">
+					<app-avatar-module :src="merchantData.smallLogoUrl" :width="78" alt="推荐人头像" />
+					<div class="recommend-info">
+						<div class="app-size-32">{{ merchantData.merchantName }}</div>
+						<div class="app-color-2">{{ merchantData.fullAddress }}</div>
+					</div>
+				</div>
+			</div>
+
+			<div class="btn-wrap">
+				<button class="admin-button-com blue big" formType="submit">确认</button>
+			</div>
+			<!-- 选择地区 -->
+			<app-area-sel :show.sync="showRegion" @change="changeAreaFn" :city="form.city" />
+			<!-- 省市联动 -->
+			<simple-address ref="simpleAddress" :region="regionData" :pickerValueDefault="cityPickerValueDefault" @onConfirm="onCityConfirm"></simple-address>
+		</form>
+	</div>
+</template>
+
+<script>
+	import TuiListCell from '@/components/plugin/list-cell'
+	import AppAreaSel from '@/components/app-area-sel'
+	import SimpleAddress from '@/components/plugin/simple-address'
+	import AppAvatarModule from '@/components/module/app-avatar'
+	const form = require('@/utils/formValidation.js')
+	// api
+	import { getIntroduce, applyRegister, sendSmsW, regionTree } from '@/api/official'
+	// import { getShopUser } from '@/utils/auth'
+	export default {
+		name: 'apply-data',
+		components: {
+			TuiListCell,
+			AppAreaSel,
+			SimpleAddress,
+			AppAvatarModule
+		},
+		data() {
+			return {
+				merchantData: {},
+				form: {
+					name: '',
+					mobile: '',
+					province: '',
+					city: '',
+					dist: '',
+					address: '',
+					floor: '',
+					longitude: '',
+					latitude: ''
+					// 推荐商家id
+					// oldId: ''
+				},
+				showRegion: false,
+				// 省市联动
+				regionData: [],
+				cityPickerValueDefault: [0, 0],
+				// 验证码
+				isSend: 0,
+				countDown: 119,
+				timer: null
+			}
+		},
+		onLoad() {
+			// if (!this.$util.isLogin()) {
+			// 	// getShopUser()
+			// 	return false
+			// }
+			// this.init()
+		},
+		methods: {
+			init() {
+				this.$util.getCheckLogin().then(res => {
+					if (res) {
+						// #ifdef H5
+						let id = sessionStorage.getItem('introMerchantId')
+						if (id) {
+							this._getMerchantDet()
+						}
+						// #endif
+						this._regionTree()
+					}
+				})
+			},
+			_regionTree() {
+				regionTree().then(res => {
+					this.regionData = res.data.tree
+				})
+			},
+			_getMerchantDet() {
+				// #ifdef H5
+				let id = sessionStorage.getItem('introMerchantId')
+				getIntroduce({ id: id }).then(res => {
+					this.merchantData = res.data
+				})
+				// #endif
+			},
+			// ==============
+			confirmFn() {
+				let id = sessionStorage.getItem('introMerchantId')
+				applyRegister({
+					// oldId: this.option.merchantId || 0,
+					introMerchantId: id || 0,
+					...this.form
+				}).then(res => {
+					uni.setStorageSync('officialApply', res.data)
+					this.$util.pageTo({
+						// url: '/official/pay',
+						url: '/official/callback',
+						type: 2,
+						query: {
+							pagestatus: 3
+							// orderSn: this.option.orderSn,
+							// payDiscountPrice: res.data.discountAmount
+						}
+					})
+				})
+			},
+			// 验证码
+			getCode() {
+				if (!this.form.mobile || !this.$util.checkMobile(this.form.mobile)) {
+					this.$msg('请输入正确的手机号!')
+					return false
+				}
+				this.isSend = 1
+				sendSmsW({
+					type: 1,
+					mobile: this.form.mobile
+				})
+					.then(res => {
+						this.beginCountDown()
+						this.$msg('发送成功!')
+					})
+					.catch(() => {
+						this.isSend = 0
+						this.$msg('发送失败!')
+					})
+			},
+			// 倒计时
+			beginCountDown() {
+				this.countDown = 119
+				this.timer = setInterval(() => {
+					if (this.countDown === 0) {
+						clearInterval(this.timer)
+						this.isSend = 0
+						return
+					}
+					this.countDown -= 1
+				}, 1000)
+			},
+			// 选择地址
+			selRegionFn() {
+				if (!this.form.city) {
+					this.$msg('请先选择地址!')
+					return false
+				}
+				this.showRegion = true
+				// let that = this
+				// uni.chooseLocation({
+				// 	success: (res) => {
+				// 		this.form.address = res.address
+				// 		this.form.latitude = res.latitude
+				// 		this.form.longitude = res.longitude
+				// 		console.log('位置名称:' + res.name)
+				// 		console.log('详细地址:' + res.address)
+				// 		console.log('纬度:' + res.latitude)
+				// 		console.log('经度:' + res.longitude)
+				// 	}
+				// })
+			},
+			changeAreaFn(e) {
+				console.log('changeAreaFn', e)
+				this.form.address = e.address
+				this.form.latitude = e.location.lat
+				this.form.longitude = e.location.lng
+			},
+			// -----
+			// 省市联动
+			openAddres() {
+				this.$refs.simpleAddress.open()
+			},
+			onCityConfirm(e) {
+				// this.form.receiveAddress = e.label
+				this.form.province = e.provinceName
+				this.form.city = e.cityName
+				// this.pickerText = JSON.stringify(e)
+			},
+			// 表单验证
+			formSubmit(e) {
+				// 表单规则
+				let rules = []
+				// 进行表单检查
+				let formData = e.detail.value
+				let checkRes = form.validation(formData, rules)
+				// 验证通过!
+				if (!checkRes) {
+					setTimeout(() => {
+						this.confirmFn()
+					})
+				} else {
+					this.$msg(checkRes)
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.module-com {
+		margin-bottom: 20px;
+		background-color: #fff;
+		.module-tit {
+			padding: 20px 18px;
+			font-size: 28px;
+			font-weight: 600;
+			border-bottom: 1px solid $borderColor;
+		}
+		.module-det {
+			padding: 0 30px;
+		}
+	}
+	// 公共
+	.line-cell {
+		.tui-title {
+			width: 210px;
+			color: $fontColor2;
+		}
+		.tui-input {
+			width: calc(100% - 210px);
+			font-size: 28px;
+		}
+		.tui-placeholder {
+			color: #ccc;
+		}
+		.phcolor {
+			color: #ccc;
+		}
+	}
+	.btn-wrap {
+		width: 90%;
+		margin: 60px auto;
+		.admin-button-com {
+			width: 100%;
+			margin: 0 auto;
+		}
+	}
+	// 验证码
+	.code-wrap {
+		.tui-input {
+			width: calc(100% - 410px);
+			font-size: 28px;
+		}
+		.tui-code {
+			width: 200px;
+			text-align: center;
+			border-left: 1px solid $borderColor;
+			color: $mainColor;
+		}
+	}
+	// 推荐人
+	.recommend-wrap {
+		padding: 30px 45px;
+		.recommend-tag {
+			font-size: 28px;
+			color: $fontColor2;
+			margin-bottom: 24px;
+		}
+		.recommend-det {
+			@include disFlex(center, flex-start);
+			.recommend-info {
+				margin-left: 20px;
+				.app-size-32 {
+					margin-bottom: 4px;
+				}
+			}
+		}
+	}
+</style>

+ 285 - 0
store/src/admin-official/callback.vue

@@ -0,0 +1,285 @@
+<template>
+	<!-- 官网各种回调页面 -->
+	<div class="app-content">
+		<div class="callback-wrap">
+			<div class="callback-blo" :class="{ 'paddingTop' : pageStatus == 7 }">
+				<block v-if="pageStatus == 7">
+					<div class="module-wrap">
+						<div class="module-tit">提示</div>
+						<div class="module-det">
+							<div class="module-list" v-for="(item, index) in promptData" :key="index">
+								<span class="dot-wrap"></span>
+								<span>{{ item }}</span>
+							</div>
+						</div>
+					</div>
+				</block>
+				<block v-else>
+					<!-- 使用icon -->
+					<!-- 成功 icon -->
+					<block v-if="pageStatus == 1">
+						<div class="status-img">
+							<img :src="`${constant.imgUrl}/retail/callback/success.png`" alt mode="widthFix" />
+						</div>
+					</block>
+					<!-- 使用图片 -->
+					<!-- 支付成功 -->
+					<block v-else>
+						<div class="icon">
+							<i class="iconfont icondaizhifu"></i>
+						</div>
+					</block>
+					<!-- prompt-wrap -->
+					<div class="prompt-wrap">
+						<block v-if="pageStatus == 1">
+							<div class="prompt-tit" style="color: #09bb07">恭喜您, 续订成功!</div>
+							<div>
+								<span class="app-color-2">你的帐号有效期已延长至:</span>
+								<span>{{ data.deadline | formatTime('YYYY-MM-DD hh:mm:ss') }}</span>
+							</div>
+						</block>
+						<block v-if="pageStatus == 2">
+							<div class="prompt-tit">申请已提交</div>
+							<div>
+								<span class="app-color-2">审核大约需要一个工作日,请耐心等候</span>
+							</div>
+						</block>
+					</div>
+					<!-- qr-code -->
+					<!-- <div class="qr-code-wrap" v-if="option.focus == 0"> -->
+					<block v-if="pageStatus == 2">
+						<div class="qr-code-wrap">
+							<div class="qr-code-img">
+								<!-- <img :src="`${constant.imgUrl}/retail/common/qr-code.png`" alt /> -->
+								<img :src="officialApply.qrCode" alt="">
+							</div>
+							<div>识别二维码关注花卉宝</div>
+							<div>审核结果将通过微信通知您</div>
+						</div>
+					</block>
+				</block>
+				<!-- button -->
+				<div class="button-wrap">
+					<block v-if="pageStatus == 1 || pageStatus == 7">
+						<button class="admin-button-com big blue" @click="jumpPage">{{ btnText }}</button>
+					</block>
+					<block v-else>
+						<button class="admin-button-com big default" @click="jumpPage">{{ btnText }}</button>
+					</block>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	/** *
+	 * 页面状态
+	 * @parmas pageStatus 进入页面的状态
+	 * @parmas 1 续订成功
+	 * @parmas 2 申请已提交
+	 * @parmas 3 申请已提交 - 返回二维码 -- successPay
+	 * @parmas 4 审核未通过 -- successEval
+	 * @parmas 5 审核通过 - 扫码支付 -- successPayCode
+	 * @parmas 6 授权成功 - 扫码支付 -- successPayCode
+	 * @parmas 7 授权提示 - 扫码支付 -- successPayCode
+	 */
+	// api
+	import { accountDet, applyStatus, getAuthUrl } from '@/api/official'
+	// import { getShopUser } from '@/utils/auth'
+	export default {
+		name: 'callback',
+		data() {
+			return {
+				constant: this.$constant,
+				data: {},
+				// pageStatus: '2',
+				pageStatus: '2',
+				promptData: ['确认你已经有公众号(服务号),并且已认证和申请微 信支付', '满足以上条件,可以点下方按钮开始授权。', '点击之后会跳到新页面,页面有个二维码,识别后按确 认授权即可。'],
+				officialApply: {}
+			}
+		},
+		computed: {
+			btnText() {
+				let text = ''
+				switch (this.pageStatus) {
+					case '1':
+						text = '返回管理中心'
+						break
+					case '2':
+						text = '返回首页'
+						break
+					case '3':
+						text = '返回首页'
+						break
+					case '4':
+						text = '返回首页'
+						break
+					case '5':
+						text = '开始授权'
+						break
+					case '6':
+						text = '管理中心'
+						break
+					case '7':
+						text = '开始授权'
+						break
+					default:
+						text = '返回管理中心'
+						break
+				}
+				return text
+			}
+		},
+		onLoad() {
+			// if (!this.$util.isLogin()) {
+			// 	getShopUser()
+			// 	return false
+			// }
+		},
+		mounted() {
+			// this.pageStatus = this.option.pageStatus
+			// this.init()
+		},
+		methods: {
+			init() {
+				let officialApply = uni.getStorageSync('officialApply')
+				if (!this.$util.isEmpty(officialApply)) {
+					this.officialApply = officialApply
+				}
+				if (this.option.pagestatus == 1) {
+					this.pageStatus = 1
+				}
+				this.$util.getCheckLogin().then(res => {
+					if (res) {
+						// this._getStatus()
+						if (this.pageStatus == 1 || this.pageStatus == 5) {
+							this._accountDet()
+						}
+					}
+				})
+			},
+			// 获取状态
+			_getStatus() {
+				applyStatus().then(res => {
+					let status = res.data.status
+					if (status == 1) {
+						this.pageStatus = 2
+					}
+				})
+			},
+			// 获取用户信息
+			_accountDet() {
+				accountDet().then(res => {
+					this.data = res.data
+				})
+			},
+			jumpPage() {
+				if (this.btnText == '返回首页') {
+					this.$util.pageTo({
+						url: '/official/index',
+						query: {
+							id: this.option.id
+						}
+					})
+				} else if (this.btnText == '返回管理中心') {
+					// this.$util.pageTo({
+					// 	url: '/official/index',
+					// 	query: {
+					// 		id: this.option.id
+					// 	}
+					// })
+					// #ifdef H5
+					location.href = `${window.location.protocol}//b.${this.$constant.firstHost}.com/#/`
+					// #endif
+				} else if (this.btnText == '开始授权') {
+					getAuthUrl().then(res => {
+						// #ifdef H5
+						location.href = res.data.url
+						// #endif
+					})
+					// this.$msg('功能待对接!')
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.callback-wrap {
+		padding-top: 30px;
+		.callback-blo {
+			width: calc(100% - 60px);
+			margin: 0 30px;
+			padding: 70px 0;
+			background-color: #fff;
+			box-shadow: 2px 2px 16px 0px rgba(181, 181, 181, 0.29);
+			border-radius: 10px;
+			text-align: center;
+			&.paddingTop {
+				padding-top: 40px;
+			}
+			// 使用icon
+			.icon {
+				.iconfont {
+					font-size: 170px;
+				}
+				.icondaizhifu {
+					color: #ffa92e;
+				}
+			}
+			// 使用状态图片
+			.status-img {
+				width: 294px;
+				margin: 0 auto;
+			}
+		}
+		// module
+		.module-wrap {
+			padding: 0 32px;
+			text-align: left;
+			.module-tit {
+				font-size: 38px;
+				// margin-bottom: 20px;
+			}
+			.module-det {
+				.module-list {
+					@include disFlex(flex-start, flex-start);
+					margin-top: 30px;
+					.dot-wrap {
+						width: 10px;
+						height: 10px;
+						border-radius: 50%;
+						background-color: $mainColor;
+						margin-top: 12px;
+						margin-right: 24px;
+					}
+				}
+			}
+		}
+		// prompt
+		.prompt-wrap {
+			margin-top: 60px;
+			.prompt-tit {
+				font-size: 36px;
+				margin-bottom: 10px;
+			}
+		}
+		// qr-code
+		.qr-code-wrap {
+			color: $fontColor2;
+			text-align: center;
+			& > div {
+				margin-top: 10px;
+			}
+			.qr-code-img {
+				width: 226px;
+				margin: 60px auto 40px;
+			}
+		}
+		// button
+		.button-wrap {
+			margin-top: 80px;
+		}
+	}
+</style>

+ 283 - 0
store/src/admin-official/index.vue

@@ -0,0 +1,283 @@
+<template>
+	<div class="app-content">
+		<div class="tab-wrap">
+			<div class="logo-img">
+				<img :src="`${constant.imgUrl}/retail/official/logo.png`" alt="" />
+			</div>
+			<div class="phone-img" @click="contactFn">
+				<img :src="`${constant.imgUrl}/retail/official/phone.png`" alt="" />
+			</div>
+		</div>
+		<app-swiper :height="{type: 'number',val: 750}" :list="swiper" />
+		<div class="module-com" v-for="(item, index) in contentData" :key="index">
+			<div class="module-tit">
+				<div class="tit-main" v-html="item.title"></div>
+				<div class="tit-sub">{{ item.subTitle }}</div>
+			</div>
+			<div class="module-det">
+				<app-img class="module-img" :src="item.img" :lazy-load="true" />
+			</div>
+		</div>
+		<!-- ad -->
+		<div class="cooperation-wrap" :style="{backgroundImage:'url(' + backgroundImg + ')'}">
+			<div class="ad-title">
+				<span>他们</span>
+				<span class="app-color-1">都在用</span>
+			</div>
+			<div class="ad-list-wrap">
+				<div class="ad-list" v-for="(item, index) in adData" :key="index">
+					<app-img :src="`${constant.imgUrl}/retail/official/list-${index + 1}.png`" alt="" />
+				</div>
+			</div>
+			<div class="official-wrap">
+				<div class="off-title">花卉宝,花店数字化建设者</div>
+				<div class="off-sub-tit" @click="contactFn">
+					<app-img :src="`${constant.imgUrl}/retail/official/phone-small.png`" alt="" />
+					<span>咨询热线:0592 - 3272000</span>
+				</div>
+			</div>
+		</div>
+		<!-- trademark -->
+		<div class="bottom-trademark">
+			<img :src="`${constant.imgUrl}/retail/common/trademark.png`" alt="" />
+		</div>
+		<!-- buttom -->
+		<div v-if="status == 3" class="app-footer" @click="pageTo({
+			url: '/admin/official/pay',
+			status: 1
+		})">立即续费</div>
+		<div v-else class="app-footer" @click="pageTo({
+			url: '/admin/official/pay'
+		})">申请试用</div>
+		<!-- <div v-if="status == -1" class="app-footer" @click="pageTo({
+			url: '/admin/official/pay',
+			status: 2
+		})">申请试用</div>
+		<div v-if="status == 0" class="app-footer under-review">审核中</div>
+		<div v-if="status == 1" class="app-footer under-review">试用中</div>
+		<div v-if="status == 2" class="app-footer under-review">审核未通过</div> -->
+		<!-- <div v-if="status == 4" class="app-footer" @click="pageTo({
+			url: '/admin/official/apply',
+			status: 2
+		})">立即订购</div> -->
+	</div>
+</template>
+
+<script>
+	import AppSwiper from '@/components/app-swiper'
+	import AppImg from '@/components/app-img'
+	// api
+	import { applyStatus } from '@/api/official'
+	export default {
+		name: 'index',
+		components: {
+			AppSwiper,
+			AppImg
+		},
+		data() {
+			return {
+				constant: this.$constant,
+				status: -2,
+				swiper: [
+					{
+						img: `${this.$constant.imgUrl}/retail/official/banner-1.png`
+					},
+					{
+						img: `${this.$constant.imgUrl}/retail/official/banner-2.png`
+					},
+					{
+						img: `${this.$constant.imgUrl}/retail/official/banner-3.png`
+					},
+					{
+						img: `${this.$constant.imgUrl}/retail/official/banner-4.png`
+					}
+				],
+				backgroundImg:`${this.$constant.imgUrl}/retail/official/bg.png`,
+				contentData: [
+					{
+						title: `<span class="app-color-1">一键搭建</span>花店商城`,
+						subTitle: `各大节日商城自动涨价,客户下单自动按距离计算运费`,
+						img: `${this.$constant.imgUrl}/retail/official/content-1.png`
+					},
+					{
+						title: `<span class="app-color-1">流程化</span>管理订单`,
+						subTitle: `有效把控订单的生命周期,从下单、打单、制作到发货、配送、 送达自动通知客户,大幅提升客户体验`,
+						img: `${this.$constant.imgUrl}/retail/official/content-2.png`
+					},
+					{
+						title: `丰富多样的<span class="app-color-1">营销工具</span>`,
+						subTitle: `契合花店日常经营的营销工具,拉新、转化、复购、裂变, 面面俱到`,
+						img: `${this.$constant.imgUrl}/retail/official/content-3.png`
+					},
+					{
+						title: `连通各渠道<span class="app-color-1">客户和订单</span>`,
+						subTitle: `线上、门店、微信、支付宝和美团等自动汇总后台,客户统一接待,订单统一管理,不必周旋于各个平台`,
+						img: `${this.$constant.imgUrl}/retail/official/content-4.png`
+					},
+					{
+						title: `<span class="app-color-1">一键吸粉 </span>注册会员`,
+						subTitle: `告别繁琐手续,一键操作,注册会员简单快捷,到店客户粉丝转化率提升80%`,
+						img: `${this.$constant.imgUrl}/retail/official/content-5.png`
+					},
+					{
+						title: `智能的<span class="app-color-1">会员系统</span>`,
+						subTitle: `客户充值消费自动累积成长值、升级会员,付款自动识别会员打折,精准把握每个客户的个性和特征`,
+						img: `${this.$constant.imgUrl}/retail/official/content-6.png`
+					},
+					{
+						title: `经营<span class="app-color-1">数据分析</span>`,
+						subTitle: `系统实时分析数据,花店每个时期的经营情况一目了然,知己知彼,百战百胜`,
+						img: `${this.$constant.imgUrl}/retail/official/content-7.png`
+					}
+				],
+				adData: [1, 2, 3, 4, 5, 6, 7, 8]
+			}
+		},
+		onLoad() {
+			// this.init()
+		},
+		methods: {
+			init() {
+				// 续费
+				if (this.option.pay == 1) {
+					// #ifdef H5
+					this.status = 3
+					sessionStorage.setItem('renewOption', JSON.stringify(this.option))
+					// #endif
+				} else {
+					// #ifdef H5
+					sessionStorage.removeItem('renewOption')
+					// #endif
+				}
+
+				// 邀请新华店
+				if (this.option.introMerchantId) {
+					// #ifdef H5
+					sessionStorage.setItem('introMerchantId', this.option.introMerchantId)
+					// #endif
+				}
+				// let token = uni.getStorageSync('token')
+				// if (token) {
+				// 	this._getDet()
+				// } else {
+				// 	this.status = -1
+				// }
+			},
+			_getDet() {
+				applyStatus().then(res => {
+					this.status = res.data.status
+				})
+			},
+			contactFn() {
+				uni.makePhoneCall({
+					phoneNumber: '05923272000'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		background-color: #fff;
+		padding-bottom: 100px;
+	}
+	.tab-wrap {
+		@include disFlex(center, space-between);
+		height: 100px;
+		padding: 0 30px;
+		.logo-img {
+			width: 160px;
+		}
+		.phone-img {
+			width: 50px;
+		}
+	}
+	// module
+	.module-com {
+		margin-top: 80px;
+		.module-tit {
+			text-align: center;
+			.tit-main {
+				font-size: 36px;
+				font-weight: 600;
+				margin-bottom: 14px;
+			}
+			.tit-sub {
+				width: 90%;
+				margin: 0 auto;
+				color: $fontColor3;
+				line-height: 34px;
+			}
+		}
+		.module-det {
+			.module-img {
+				min-height: 470px;
+			}
+		}
+	}
+	// cooperation
+	.cooperation-wrap {
+		width: 100%;
+		height: 552px;
+		padding-top: 60px;
+		.ad-title {
+			color: #fff;
+			font-size: 36px;
+			font-weight: 600;
+			margin-bottom: 50px;
+			text-align: center;
+		}
+		.ad-list-wrap {
+			@include disFlex(center, center);
+			flex-wrap: wrap;
+			margin-bottom: 30px;
+			.ad-list {
+				width: 166px;
+				margin-right: 10px;
+				margin-bottom: 10px;
+			}
+		}
+		.official-wrap {
+			color: #fff;
+			background-color: rgba(#000000, 0.6);
+			width: 90%;
+			margin: 0 auto;
+			padding: 20px 0;
+			.off-title {
+				font-size: 36px;
+				font-weight: 600;
+				margin-bottom: 10px;
+				text-align: center;
+			}
+			.off-sub-tit {
+				@include disFlex(center, center);
+				img {
+					width: 28px;
+					height: 28px;
+					margin-right: 10px;
+				}
+			}
+		}
+	}
+	// trademark
+	.bottom-trademark {
+		height: 150px;
+		@include disFlex(center, center);
+		background-color: #242627;
+		img {
+			width: 140px;
+		}
+	}
+	// footer
+	.app-footer {
+		color: #fff;
+		font-size: 36px;
+		font-weight: 600;
+		background: linear-gradient(90deg, #3ab7ff, #3385ff);
+		&.under-review {
+			background: #fff !important;
+			color: #333 !important;
+		}
+	}
+</style>

+ 195 - 0
store/src/admin-official/pay.vue

@@ -0,0 +1,195 @@
+<template>
+	<div class="app-content">
+		<div class="banner-wrap">
+			<div class="banner-img">
+				<img :src="`${constant.imgUrl}/retail/official/pay-banner.png`" alt />
+				<div class="meal-det">
+					<div class="meal-title">{{ detail.name }}</div>
+					<div class="meal-introduce">{{ detail.introduce }}</div>
+				</div>
+			</div>
+			<div class="flex-center-between app-size-28">
+				<div>软件周期</div>
+				<div>1年</div>
+			</div>
+		</div>
+		<!-- list -->
+		<div class="module-wrap">
+			<div class="module-tit">主要功能</div>
+			<div class="module-det">
+				<div class="list-wrap">
+					<div class="list" v-for="(item, index) in funcitonData" :key="index">
+						<span :class="{ 'app-color-3' : !item.has}">{{ item.name }}</span>
+						<i class="iconfont" :class="[item.has ? 'icondagou' : 'iconguanbi']"></i>
+					</div>
+				</div>
+			</div>
+		</div>
+		<!-- buttom -->
+		<div class="page-btn app-footer">
+			<div class="flex-center">
+				<span>合计</span>
+				<span class="app-price">
+					<span>¥</span>
+					<span class="app-size-40">{{ detail.price }}</span>
+				</span>
+			</div>
+			<button v-if="$util.isEmpty(renewOption)" class="admin-button-com middle blue" @click="pageTo({
+			url: '/official/apply'
+		})">免费试用</button>
+			<button v-else class="admin-button-com middle blue" @click="wxPay">支付</button>
+		</div>
+	</div>
+</template>
+
+<script>
+	// import { getShopUser } from '@/utils/auth'
+	import wexinPay from '@/utils/pay/wxPay'
+	import { getMealDet, renewWxPay } from '@/api/official'
+	export default {
+		name: 'pay-page',
+		data() {
+			return {
+				constant: this.$constant,
+				detail: {},
+				funcitonData: [],
+				renewOption: null
+			}
+		},
+		onLoad() {
+			// if (!this.$util.isLogin()) {
+			// 	getShopUser()
+			// 	return false
+			// }
+			// this.init()
+		},
+		methods: {
+			init() {
+				this.$util.getCheckLogin().then(res => {
+					if (res) {
+						this._getMealDet()
+
+						// 续费
+						// #ifdef H5
+						let renewOption = sessionStorage.getItem('renewOption')
+						if (renewOption) {
+							this.renewOption = JSON.parse(renewOption)
+						}
+						// #endif
+					}
+				})
+			},
+			_getMealDet() {
+				getMealDet({ id: 1 }).then(res => {
+					if (this.$util.isEmpty(res.data)) return false
+					this.detail = res.data.detail
+					this.funcitonData = res.data.function
+				})
+			},
+			wxPay() {
+				renewWxPay({ id: this.detail.id, merchantId: this.renewOption.merchantId }).then(res => {
+					wexinPay(res.data, this.paySuccess, this.payFail)
+				})
+			},
+			// 支付成功
+			paySuccess() {
+				// alert('支付成功!')
+				this.$util.pageTo({
+					url: '/official/callback',
+					type: 2,
+					query: {
+						pagestatus: 1
+						// orderSn: this.option.orderSn,
+						// payDiscountPrice: res.data.discountAmount
+					}
+				})
+			},
+			payFail() {
+				this.$msg('支付失败,请重新支付!')
+			}
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.app-content {
+		background-color: #fff;
+	}
+	.banner-wrap {
+		padding: 32px;
+		width: calc(100% - 64px);
+		border-bottom: 20px solid $backColor;
+		.banner-img {
+			width: 100%;
+			margin-bottom: 6px;
+			position: relative;
+			.meal-det {
+				position: absolute;
+				top: 40px;
+				left: 30px;
+				width: 60%;
+				color: #fff;
+				.meal-title {
+					font-size: 42px;
+					font-weight: 600;
+					margin-bottom: 28px;
+					letter-spacing: 8px;
+				}
+				.meal-introduce {
+					line-height: 40px;
+					letter-spacing: 2px;
+				}
+			}
+		}
+	}
+	// list
+	.module-wrap {
+		padding: 40px 30px 0;
+		.module-tit {
+			font-size: 28px;
+			font-weight: 600;
+			margin-bottom: 24px;
+		}
+		.module-det {
+			.list-wrap {
+				border: 2px solid #f9f9f9;
+				border-top: none;
+				.list {
+					@include disFlex(center, space-between);
+					padding: 20px 26px;
+					border-top: 2px solid #f9f9f9;
+					&:nth-child(odd) {
+						background-color: #eee;
+					}
+					.iconfont {
+						font-size: 30px;
+					}
+					.icondagou {
+						color: $mainColor;
+					}
+					.iconguanbi {
+						font-size: 24px;
+						color: $fontColor3;
+					}
+				}
+			}
+		}
+	}
+	// button
+	.page-btn {
+		width: calc(100% - 60px);
+		@include disFlex(center, space-between);
+		padding: 0 30px;
+		.app-price {
+			margin-bottom: 8px;
+			margin-left: 4px;
+		}
+		.red {
+			width: 270px;
+		}
+		.admin-button-com {
+			width: 200px;
+			font-size: 32px;
+		}
+	}
+</style>

+ 50 - 0
store/src/admin-order/components/card-name.vue

@@ -0,0 +1,50 @@
+<template>
+	<div class="card-name-module">
+        <div class="app-size-30 app-color-0">{{ info.receiveUserName }}</div>
+        <div>{{ info.receiveMobile }}</div>
+        <div>{{ info.receiveAddress }}</div>
+        <div class="card-tag">
+            <img :src="`${constant.imgUrl}/retail/order/tag.png`" alt="" mode="widthFix" >
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+	name: 'card-name-module',
+	props: {
+		info: {
+			type: Object,
+			default: () => {}
+		}
+	},
+	data() {
+		return {
+			constant: this.$constant
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.card-name-module {
+    position: relative;
+    color: $fontColor3;
+    box-shadow: 0 0 10px #ccc;
+    border-radius: 4px;
+    padding: 24px 0 24px 20px;
+    & > div {
+        margin-top: 14px;
+        &:first-child {
+            margin-top: 0;
+        }
+    }
+    .card-tag {
+        position: absolute;
+        top: 0;
+        right: 0;
+        width: 100px;
+        margin-top: 0;
+    }
+}
+</style>

+ 286 - 0
store/src/admin-order/components/sel-confirm.vue

@@ -0,0 +1,286 @@
+<template>
+	<div class="sel-confirm-module">
+		<!-- 列表 -->
+		<time-axis v-if="!$util.isEmpty(orderComData)">
+			<!-- 完成 -->
+			<timeaxis-item class="axis-list axis-first com-wrap" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">完成</div>
+						<div class="axis-det">
+							<button class="admin-button-com big blue confirm-btn" @click="confirmFn">订单归类</button>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 送达 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[1].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[1].addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 发货 -->
+			<timeaxis-item class="axis-list confirm-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[2].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[2].addTime | formatTime }}</div>
+							<block v-if="!$util.isEmpty(orderComData[2].sendInfo)">
+								<div>配送方:{{ orderComData[2].sendInfo.sideName }}</div>
+								<div>距离:{{ orderComData[2].sendInfo.distance }}km</div>
+								<div>运费:¥{{ orderComData[2].sendInfo.cost }}</div>
+								<div>小费:¥{{ orderComData[2].sendInfo.tip }}</div>
+								<div>
+									<span>状态:</span>
+									<span class="app-color-4">{{ orderComData[2].sendInfo.status | constantfilter('SEND_STATUS') }}</span>
+								</div>
+							</block>
+							<block v-else>
+								<div>配送方:门店</div>
+							</block>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[3].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-bold">{{ orderComData[3].addTime | formatTime }}</div>
+							<card-name v-if="!$util.isEmpty(orderComData[3].receive)" :info="orderComData[3].receive" />
+							<block v-else>
+								<div>无配送信息</div>
+							</block>
+							<div class="btn-wrap-com">
+								<!-- <button class="admin-button-com default">明细</button> -->
+								<!-- <button class="admin-button-com default" @click="mobilePrintFn" >重打</button> -->
+							</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[4].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[4].addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+		<!-- 选取分类 -->
+		<modal-module :show="selModal" :maskClosable="false" @cancel="modalCancel" @click="selModalClick" title="订单归类" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="upload-confirm-wrap">
+					<!-- 选择分类 -->
+					<div class="sel-wrap">
+						<div class="sel-tit">选择分类</div>
+						<div class="sel-btn">
+							<block v-for="(item, index) in categoryData" :key="index">
+								<button class="admin-button-com" :class="[form.categoryId == item.id ? '' : 'default']" @click="selCategoryFn(item)">{{ item.categoryName || '暂无' }}</button>
+							</block>
+						</div>
+					</div>
+					<!-- 选择用途 -->
+					<div class="sel-wrap">
+						<div class="sel-tit">选择用途</div>
+						<div class="sel-btn">
+							<block v-for="(item, index) in usageData" :key="index">
+								<button class="admin-button-com" :class="[form.usageId == item.id ? '' : 'default']" @click="selUsageFn(item)">{{ item.usageName || '暂无' }}</button>
+							</block>
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import ModalModule from '@/components/plugin/modal'
+import CardName from './card-name'
+// api
+import { getCategory, getUsage } from '@/utils/config'
+import { orderClass } from '@/api/order'
+export default {
+	name: 'sel-confirm-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem,
+		ModalModule,
+		CardName
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	},
+	data() {
+		return {
+			selModal: false,
+			form: {
+				categoryId: '',
+				usageId: ''
+			}
+		}
+	},
+	computed: {
+		...mapGetters({ categoryData: 'getCategory' }),
+		...mapGetters({ usageData: 'getUsage' })
+	},
+	mounted() {
+		getCategory()
+		getUsage()
+	},
+	methods: {
+		confirmFn() {
+			this.selModal = true
+		},
+		// modal
+		// 操作
+		selCategoryFn(item) {
+			this.form.categoryId = item.id
+		},
+		selUsageFn(item) {
+			this.form.usageId = item.id
+		},
+		selModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				orderClass({
+					id: this.orderData.id,
+					...this.form
+				}).then(res => {
+					this.$msg('订单归类成功!')
+					setTimeout(() => {
+						this.$util.pageTo({
+							url: '/admin/order/ship',
+							query: {
+								id: this.query.id,
+								pageStatus: 6
+							}
+						})
+					}, 1000)
+				})
+			}
+		},
+		modalCancel() {
+			this.selModal = false
+		},
+		mobilePrintFn(){
+		    this.$msg('此功能即将开通')
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	// 完成
+	.axis-first {
+		.axis-det {
+			margin-top: 40px !important;
+		}
+		.confirm-btn {
+			width: 100%;
+		}
+	}
+	// 发货
+	.confirm-wrap {
+		.axis-det {
+			margin-top: 20px;
+			margin-bottom: 10px;
+			color: $fontColor2;
+			& > div {
+				margin-top: 14px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+			.admin-button-com {
+				width: 120px;
+				margin-top: 20px;
+			}
+		}
+	}
+	// 打单
+	.com-wrap {
+		.axis-det {
+			margin-top: 14px;
+			& > div {
+				margin-top: 20px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+		}
+	}
+	// 弹窗
+	.upload-confirm-wrap {
+		max-height: 600px;
+		overflow-y: auto;
+		.modal-tit {
+			@include disFlex(center, center);
+			font-size: 40px;
+			margin-top: 30px;
+			margin-bottom: 50px;
+			.iconfont {
+				color: #09bb07;
+				margin-right: 20px;
+				font-size: 50px;
+			}
+		}
+		//  分类
+		.sel-wrap {
+			color: $fontColor2;
+			font-size: 32px;
+			.sel-tit {
+				text-align: left;
+			}
+			.sel-btn {
+				@include disFlex(center, flex-start);
+				flex-wrap: wrap;
+				padding: 10px 0 40px;
+				.admin-button-com {
+					// width: 170px;
+					margin-right: 20px;
+					margin-top: 20px;
+					padding-top: 16px;
+					padding-bottom: 16px;
+					border-radius: 4px;
+					// &:nth-child(3n + 1) {
+					// 	margin-left: 0;
+					// }
+				}
+			}
+		}
+	}
+</style>

+ 206 - 0
store/src/admin-order/components/sel-express-confirm.vue

@@ -0,0 +1,206 @@
+<template>
+	<div class="sel-confirm-module">
+		<!-- 列表 -->
+		<time-axis v-if="!$util.isEmpty(orderComData)">
+			<!-- 送达 -->
+			<timeaxis-item class="axis-list axis-first com-wrap" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">送达</div>
+						<div class="axis-det express-wrap">
+							<button class="admin-button-com big blue" @click="askConfirmReachFn">确认送达</button>
+							<div class="button-prompt">送达会通知客户哦</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 发货 -->
+			<timeaxis-item class="axis-list confirm-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[1].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[1].addTime | formatTime }}</div>
+							<block v-if="!$util.isEmpty(orderComData[1].sendInfo)">
+								<div>配送方:{{ orderComData[1].sendInfo.sideName }}</div>
+								<div>距离:{{ orderComData[1].sendInfo.distance }}km</div>
+								<div>运费:¥{{ orderComData[1].sendInfo.cost }}</div>
+								<div>小费:¥{{ orderComData[1].sendInfo.tip }}</div>
+								<div>
+									<span>状态:</span>
+									<span class="app-color-4">{{ orderComData[1].sendInfo.status | constantfilter('SEND_STATUS') }}</span>
+								</div>
+							</block>
+							<block v-else>
+								<div>配送方:门店</div>
+							</block>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[2].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-bold">{{ orderComData[2].finishTime | formatTime }}</div>
+							<block v-if="!$util.isEmpty(orderComData[2].receive)">
+								<card-name :info="orderComData[2].receive" />
+							</block>
+							<block v-else>
+								<div>无配送信息</div>
+							</block>
+							<block v-if="!$util.isEmpty(orderComData[2].receive)">
+								<div class="btn-wrap-com">
+									<!-- <button class="admin-button-com default">明细</button> -->
+									<button class="admin-button-com default" @click="mobilePrintFn">重打</button>
+								</div>
+							</block>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[3].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[3].finishTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+		<modal-module :show="showManualConfirmModal" @cancel="cancelConfirmReachFn" @click="manualConfirmReachFn" content="此订单由快递配送,送到会自动确认,确定要手动确认?" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import CardName from './card-name'
+import ModalModule from '@/components/plugin/modal'
+// api
+import { orderReach } from '@/api/order'
+export default {
+	name: 'sel-confirm-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem,
+		CardName,
+		ModalModule
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	},
+	data() {
+		return {
+		    showManualConfirmModal:false
+		}
+    },
+	methods: {
+		confirmReachFn() {
+			orderReach({
+				id: this.orderData.id,
+				option: 1
+			}).then(res => {
+				this.$msg('已确认')
+				setTimeout(() => {
+					this.$util.pageTo({
+						url: '/admin/order/ship',
+						query: {
+							id: this.query.id,
+							pageStatus: 5
+						}
+					})
+				}, 1000)
+			})
+		},
+		askConfirmReachFn(){
+		    if(this.orderData.sendType == 3){
+		        this.showManualConfirmModal = true
+		    }else{
+                this.confirmReachFn()
+		    }
+		},
+		manualConfirmReachFn(e){
+			if (e.index === 0) {
+				this.cancelConfirmReachFn()
+			} else {
+            	this.confirmReachFn()
+			}
+		},
+		cancelConfirmReachFn(){
+			this.showManualConfirmModal = false
+		},
+		mobilePrintFn(){
+		    this.$msg('此功能即将开通')
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	// 发货
+	.confirm-wrap {
+		.axis-det {
+			margin-top: 20px;
+			margin-bottom: 10px;
+			color: $fontColor2;
+			& > div {
+				margin-top: 14px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+			.admin-button-com {
+				width: 120px;
+				margin-top: 20px;
+			}
+			.modify-btn {
+				color: $mainColor;
+				font-size: 24px;
+				margin-left: 30px;
+			}
+		}
+	}
+	// 打单
+	.com-wrap {
+		.axis-det {
+			margin-top: 14px;
+			& > div {
+				margin-top: 20px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+		}
+		.express-wrap {
+			.admin-button-com {
+				width: 100%;
+			}
+			.button-prompt {
+				text-align: center;
+				color: $fontColor2;
+			}
+		}
+	}
+</style>

+ 130 - 0
store/src/admin-order/components/sel-mention.vue

@@ -0,0 +1,130 @@
+<template>
+	<div class="sel-mention-module">
+		<!-- 列表 -->
+		<time-axis>
+			<!-- 完成 -->
+			<timeaxis-item class="axis-list axis-first confirm-wrap" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">完成</div>
+						<div class="axis-det">
+							<div class="app-color-0">2019-10-10 18:00:00</div>
+                            <div>类型: 花束/花盒</div>
+                            <div>用途:送爱人/恋人</div>
+                            <div>消息推送:未推送</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 送达 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">送达</div>
+						<div class="axis-det">
+							<div>2019-10-10 18:00:00</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 发货 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">发货</div>
+						<div class="axis-det">
+							<div>2019-10-10 18:00:00</div>
+                            <div class="app-color-2">自己送</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">打单</div>
+						<div class="axis-det">
+							<div>2019-10-10 18:00:00</div>
+                            <div class="app-color-2">免打单</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">下单</div>
+						<div class="axis-det">
+							<div>2019-10-10 18:00:00</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+export default {
+	name: 'sel-mention-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+    // 发货
+    .confirm-wrap {
+		.axis-slot-wrap {
+			top: -4px !important;
+		}
+		.axis-det {
+			margin-top: 20px;
+            margin-bottom: 10px;
+            color: $fontColor2;
+            & > div {
+                margin-top: 10px;
+                &:first-child {
+                    margin-top: 0;
+                }
+            }
+		}
+    }
+	// 打单
+	.com-wrap {
+		.axis-det {
+			margin-top: 14px;
+            & > div {
+                margin-top: 10px;
+                &:first-child {
+                    margin-top: 0;
+                }
+            }
+		}
+	}
+</style>

+ 110 - 0
store/src/admin-order/components/sel-order.vue

@@ -0,0 +1,110 @@
+<template>
+	<div class="sel-order-module">
+		<!-- 列表 -->
+		<time-axis>
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list axis-first print-order" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">打单</div>
+						<div class="axis-det">
+							<button class="admin-button-com big blue" @click="hasSendOrderFn">有配送单</button>
+							<button class="admin-button-com big blue" @click="pageTo({
+						url: '/admin/order/fill-form',
+						query: {
+							id: orderData.id
+						}
+							})">填单</button>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list down-order" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">下单</div>
+						<div class="axis-det">
+							<div>{{ orderData.addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+// api
+import { printOrder } from '@/api/order'
+export default {
+	name: 'sel-order-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		}
+	},
+	data() {
+		return {
+			data: {}
+		}
+	},
+	mounted() {
+	},
+	methods: {
+		hasSendOrderFn() {
+			printOrder({
+				id: this.orderData.id,
+				option: 1
+			}).then(res => {
+				this.$util.pageTo({
+					url: '/admin/order/ship',
+					query: {
+						id: this.orderData.id,
+						pageStatus: 7
+					}
+				})
+			})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	// 打单
+	.print-order {
+		.axis-slot-wrap {
+			top: -4px !important;
+		}
+		.axis-det {
+			@include disFlex(center, space-between);
+			margin-top: 50px;
+			margin-bottom: 10px;
+			.admin-button-com {
+				width: 48%;
+			}
+		}
+	}
+	// 下单
+	.down-order {
+		.axis-det {
+			margin-top: 14px;
+		}
+	}
+</style>

+ 129 - 0
store/src/admin-order/components/sel-pending-order.vue

@@ -0,0 +1,129 @@
+<template>
+	<div class="sel-pending-order-module">
+		<!-- 列表 -->
+		<time-axis>
+			<!-- 发货 -->
+			<timeaxis-item class="axis-list axis-first confirm-wrap" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[0].actionName }}</div>
+						<div class="axis-det">
+							<div>配送方:{{ orderComData[0].sendInfo.sideName }}</div>
+                            <div>距离:{{ orderComData[0].sendInfo.distance }}km</div>
+                            <div>运费:¥{{ orderComData[0].sendInfo.cost }}</div>
+                            <div>
+                                <span>小费:¥{{ orderComData[0].sendInfo.tip }}</span>
+                                <i class="iconfont iconbianjijiage1 modify-btn"></i>
+                            </div>
+                            <div>
+								<span>状态:</span>
+								<span class="app-price">{{ orderComData[0].sendInfo.status | constantfilter('SEND_STATUS') }}</span>
+							</div>
+                            <div>期待送花时间:{{ orderComData[2].addTime | formatTime }}</div>
+                            <div class="admin-button-com default">取消</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">打单</div>
+						<div class="axis-det">
+							<div>2019-10-10 18:00:00</div>
+                            <card-name />
+                            <div class="btn-wrap-com">
+                                <button class="admin-button-com default">修改</button>
+                                <button class="admin-button-com default">明细</button>
+                                <button class="admin-button-com default">打印</button>
+                            </div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">下单</div>
+						<div class="axis-det">
+							<div>2019-10-10 18:00:00</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import CardName from './card-name'
+export default {
+	name: 'sel-pending-order-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem,
+		CardName
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+    // 发货
+    .confirm-wrap {
+		.axis-det {
+			margin-top: 20px;
+            margin-bottom: 10px;
+            color: $fontColor2;
+            & > div {
+                margin-top: 14px;
+                &:first-child {
+                    margin-top: 0;
+                }
+            }
+            .admin-button-com {
+                width: 120px;
+                margin-top: 20px;
+            }
+            .modify-btn {
+                color: $mainColor;
+                font-size: 24px;
+                margin-left: 30px;
+            }
+		}
+    }
+	// 打单
+	.com-wrap {
+		.axis-det {
+			margin-top: 14px;
+            & > div {
+                margin-top: 20px;
+                &:first-child {
+                    margin-top: 0;
+                }
+            }
+		}
+	}
+</style>

+ 155 - 0
store/src/admin-order/components/sel-ship-confirm.vue

@@ -0,0 +1,155 @@
+<template>
+	<div class="sel-ship-confirm-module">
+		<!-- 列表 -->
+		<time-axis v-if="!$util.isEmpty(orderComData)">
+			<!-- 完成 -->
+			<timeaxis-item class="axis-list axis-first confirm-wrap" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[0].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[0].finishTime | formatTime }}</div>
+							<!-- <div>订单归类: {{ orderComData[0].classify.category }}</div> -->
+							<!-- <div>用途:{{ orderComData[0].classify.usage }}</div> -->
+							<!-- <div>消息推送:已推送</div> -->
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 送达 -->
+			<!-- <timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[1].actionName }}</div>
+						<div class="axis-det">
+							<div class="app-bold">{{ orderComData[1].addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item> -->
+			<!-- 发货 -->
+			<timeaxis-item class="axis-list confirm-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[1].actionName}}</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[1].addTime | formatTime }}</div>
+							<block v-if="!$util.isEmpty(orderComData[1].sendInfo)">
+								<div>配送方:{{ orderComData[1].sendInfo.sideName }}</div>
+								<div>距离:{{ orderComData[1].sendInfo.distance }}km</div>
+								<div>运费:¥{{ orderComData[1].sendInfo.cost }}</div>
+								<div>小费:¥{{ orderComData[1].sendInfo.tip }}</div>
+								<div>状态:{{ orderComData[1].sendInfo.status | constantfilter('SEND_STATUS') }}</div>
+							</block>
+							<block v-else>
+								<div>配送方:门店</div>
+							</block>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[2].actionName}}</div>
+						<div class="axis-det">
+							<div class="app-bold">{{ orderComData[2].addTime | formatTime }}</div>
+							<card-name v-if="!$util.isEmpty(orderComData[2].receive)" :info="orderComData[2].receive" />
+							<block v-else>
+								<div>无配送信息</div>
+							</block>
+							<div class="btn-wrap-com">
+								<!-- <button class="admin-button-com default">明细</button> -->
+								<button class="admin-button-com default" @click="() => { alert('打印功能待开发!') }">重打</button>
+							</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[3].actionName}}</div>
+						<div class="axis-det">
+							<div class="app-bold">{{ orderComData[3].addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import CardName from './card-name'
+export default {
+	name: 'sel-ship-confirm-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem,
+		CardName
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	// 发货
+	.confirm-wrap {
+		.axis-det {
+			margin-top: 20px;
+			margin-bottom: 10px;
+			color: $fontColor2;
+			& > div {
+				margin-top: 10px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+			.admin-button-com {
+				width: 120px;
+				margin-top: 20px;
+			}
+			.modify-btn {
+				color: $mainColor;
+				font-size: 24px;
+				margin-left: 30px;
+			}
+		}
+	}
+	// 打单
+	.com-wrap {
+		.axis-det {
+			margin-top: 14px;
+			& > div {
+				margin-top: 20px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+		}
+	}
+</style>
+

+ 261 - 0
store/src/admin-order/components/sel-ship-manage.vue

@@ -0,0 +1,261 @@
+<template>
+	<div class="sel-confirm-module">
+		<!-- 列表 -->
+		<time-axis>
+			<!-- 完成 -->
+			<timeaxis-item class="axis-list axis-first com-wrap" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">发货</div>
+                        <div v-if="orderData.hasDeliver == 1" class="axis-det btn-wrap">
+                            <button class="admin-button-com big blue confirm-btn" @click="sendSelfFn(1)">确认发货</button>
+                        </div>
+						<div v-else class="axis-det btn-wrap">
+							<button class="admin-button-com big blue confirm-btn" @click="sendSelfFn(0)" style="margin:auto;">自己送</button>
+							<button class="admin-button-com big blue confirm-btn" @click="sendShipFn" style="margin:auto;">代送</button>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 送达 -->
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">打单</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[1].addTime | formatTime }}</div>
+							<block v-if="!$util.isEmpty(orderComData[1].receive)">
+								<card-name :info="orderComData[1].receive" />
+								<div class="btn-wrap-com">
+									<button class="admin-button-com default" @click="mobilePrintFn">重打</button>
+								</div>
+							</block>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<timeaxis-item class="axis-list com-wrap" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">下单</div>
+						<div class="axis-det">
+							<div class="app-color-0 app-bold">{{ orderComData[1].addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+		<!-- ship -->
+		<modal-module :show="shipModal" :maskClosable="false" @cancel="modalCancel" @click="shipModalClick" title="确认发货?" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap ship-modal">
+					<!-- <div class="inp-list-line switch-wrap">
+						<div class="line-label">快递代送</div>
+						<div class="line-input flex-strat">
+							<switch :checked="form.sendType == '0' ? false : true" @change="switchChangeFn" />
+						</div>
+					</div> -->
+					<!-- <block v-if="form.sendType == 1"> -->
+						<div class="inp-list-line">
+							<div class="line-label">送花时间</div>
+							<div class="line-input">
+								<picker mode="multiSelector" :range="timeList" :value="timeValue" @change="changeTimeFn" class="inp-select">
+									<div v-if="form.sendTime">{{ form.sendTime }}</div>
+									<div class="tui-placeholder" v-else>请选择</div>
+								</picker>
+							</div>
+						</div>
+						<div class="inp-list-line">
+							<div class="line-label">配送方</div>
+							<div class="line-input">
+								<picker mode="selector" :range="deliveryList" @change="changeDeliveryFn" range-key="text" class="inp-select">
+									<div v-if="form.sendSide">{{ sendSideText }}</div>
+									<div class="tui-placeholder" v-else>请选择</div>
+								</picker>
+							</div>
+						</div>
+					<!-- </block> -->
+				</div>
+			</template>
+		</modal-module>
+		<!-- 删除提示 -->
+		<modal-module :show="selfShipModal" @cancel="modalCancel" @click="shipModalClick" :content="selfShipHint" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import CardName from './card-name'
+import ModalModule from '@/components/plugin/modal'
+// api
+import { orderSend, printOrder } from '@/api/order'
+export default {
+	name: 'sel-confirm-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem,
+		CardName,
+		ModalModule
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	},
+	data() {
+		return {
+			shipModal: false,
+			form: {
+				sendType: 0,
+				sendTime: '',
+				sendSide: 1
+			},
+			sendSideText: '达达配送',
+			// time
+			timeList: [
+				['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24'],
+				['00', '10', '20', '30', '40', '50']
+			],
+			timeValue: [0, 0],
+			// deliveryList
+			deliveryList: [
+				{
+					text: '达达配送',
+					key: 1
+				}
+			],
+			// 自己送
+			selfShipModal: false,
+			selfShipHint:''
+		}
+	},
+	methods: {
+		sendShipFn() {
+			this.shipModal = true
+            this.sendSideText = '达达配送'
+			this.form = {
+				sendType: 3,
+				sendTime: '',
+				sendSide: 1
+			}
+		},
+		sendSelfFn(num) {
+		    if(num == 0){
+		        this.selfShipHint='确认自己配送?';
+		    }else{
+		        this.selfShipHint='确认发货?';
+		    }
+			this.selfShipModal = true
+			this.form = {
+				sendType: 2,
+				sendTime: '',
+				sendSide: ''
+			}
+		},
+		printOrderFn() {
+			printOrder({
+				id: this.orderData.id,
+				option: 1
+			}).then(res => {
+				this.$util.pageTo({
+					url: '/admin/order/ship',
+					query: {
+						id: this.orderData.id,
+						pageStatus: 7
+					}
+				})
+			})
+		},
+		// moadl
+		switchChangeFn(e) {
+			this.form.sendType = e.detail.value ? 1 : 0
+		},
+		changeTimeFn(e) {
+			let oneIndex = e.detail.value[0] || 0
+			let twoIndex = e.detail.value[1] || 0
+			this.form.sendTime = this.timeList[0][oneIndex] + ':' + this.timeList[1][twoIndex]
+		},
+		changeDeliveryFn(e) {
+			this.form.sendSide = this.deliveryList[e.detail.value].key
+			this.sendSideText = this.deliveryList[e.detail.value].text
+		},
+		shipModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				orderSend({
+					id: this.query.id,
+					option: 1,
+					...this.form
+				}).then(res => {
+					this.modalCancel()
+					this.$util.pageTo({
+						url: '/admin/order/ship',
+						query: {
+							id: this.query.id,
+							pageStatus: 3
+						}
+					})
+				})
+			}
+		},
+		modalCancel() {
+			this.shipModal = false
+			this.selfShipModal = false
+		},
+		mobilePrintFn(){
+		    this.$msg('此功能即将开通')
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	// 完成
+	.axis-first {
+		.axis-det {
+			margin-top: 40px !important;
+		}
+		.confirm-btn {
+			width: 40%;
+		}
+	}
+	// 打单
+	.com-wrap {
+		.axis-det {
+			margin-top: 14px;
+			& > div {
+				margin-top: 20px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+		}
+	}
+	// modal
+	.ship-modal {
+		.line-label {
+			width: 140px;
+		}
+	}
+	.btn-wrap {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+	}
+</style>

+ 137 - 0
store/src/admin-order/components/sel-ship.vue

@@ -0,0 +1,137 @@
+<template>
+	<div class="sel-ship-module">
+		<!-- 列表 -->
+		<time-axis>
+			<!-- 发货 -->
+			<!-- <timeaxis-item class="axis-list axis-first ship-goods" bgcolor="none">
+				<template v-slot:node>
+					<div class="tui-node node-big">
+						<div class="node-small"></div>
+					</div>
+				</template>
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">发货</div>
+						<div class="axis-det">
+							<button class="admin-button-com big blue">自己送</button>
+							<button class="admin-button-com big blue">快递送</button>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item> -->
+			<!-- 打单 -->
+			<timeaxis-item class="axis-list axis-first print-order" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">打单</div>
+						<div class="axis-det">
+							<div>{{ orderComData[0].addTime | formatTime }}</div>
+                            <card-name :info="orderComData[0].receive" />
+                            <div class="btn-wrap-com">
+                                <!-- <button class="admin-button-com default">修改</button> -->
+                                <!-- <button class="admin-button-com default">明细</button> -->
+                                <button class="admin-button-com default" @click="mobilePrintFn">打印</button>
+                                <button class="admin-button-com default" @click="printOrderFn">确定</button>
+                            </div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+			<!-- 下单 -->
+			<timeaxis-item class="axis-list down-order" bgcolor="none">
+				<template v-slot:content>
+					<div class="axis-slot-wrap">
+						<div class="axis-title">{{ orderComData[1].actionName }}</div>
+						<div class="axis-det">
+							<div>{{ orderComData[1].addTime | formatTime }}</div>
+						</div>
+					</div>
+				</template>
+			</timeaxis-item>
+		</time-axis>
+	</div>
+</template>
+
+<script>
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import CardName from './card-name'
+// api
+import { printOrder } from '@/api/order'
+export default {
+	name: 'sel-order-module',
+	components: {
+		TimeAxis,
+		TimeaxisItem,
+		CardName
+	},
+	props: {
+		query: {
+			type: Object,
+			default: () => {}
+		},
+		orderData: {
+			type: Object,
+			default: () => {}
+		},
+		orderComData: {
+			type: Array,
+			default: () => []
+		}
+	},
+	methods: {
+		printOrderFn() {
+			printOrder({
+				id: this.orderData.id,
+				option: 2
+			}).then(res => {
+				this.$util.pageTo({
+					url: '/admin/order/ship',
+					query: {
+						id: this.orderData.id,
+						pageStatus: 7
+					}
+				})
+			})
+		},
+		mobilePrintFn(){
+            this.$msg('此功能即将开通')
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+    // 发货
+    .ship-goods {
+		.axis-slot-wrap {
+			top: -4px !important;
+		}
+		.axis-det {
+			@include disFlex(center, space-between);
+			margin-top: 50px;
+			margin-bottom: 10px;
+			.admin-button-com {
+				width: 48%;
+			}
+		}
+    }
+	// 打单
+	.print-order {
+		.axis-det {
+            margin-top: 14px;
+            & > div {
+                margin-top: 20px;
+                &:first-child {
+                    margin-top: 0;
+                }
+            }
+		}
+	}
+	// 下单
+	.down-order {
+		.axis-det {
+			margin-top: 14px;
+		}
+	}
+</style>

+ 370 - 0
store/src/admin-order/detail.vue

@@ -0,0 +1,370 @@
+<template>
+	<div class="app-content">
+		<div class="page-top">
+			<div class="page-top-img">
+				<img :src="`${constant.imgUrl}/retail/order/bg.png`" alt />
+			</div>
+			<div class="page-top-det">
+				<div>
+					<div class="page-status">{{ data.status | constantfilter('ORDER_STATUS') }}</div>
+					<!-- <div class="page-prompt">请尽快支付哟~</div> -->
+				</div>
+				<div class="page-status-img">
+					<img :src="data.status == 0 ? waitPayImg : waitDeliveryImg" alt />
+				</div>
+			</div>
+		</div>
+		<!-- 订单详情 -->
+		<div class="page-det">
+			<!-- 商品信息 -->
+			<div class="module-com">
+				<div class="module-tit">商品信息</div>
+				<div class="module-det">
+					<block v-if="!$util.isEmpty(data.goodsInfoList)">
+						<list-module v-for="(items, subIndex) in data.goodsInfoList" :key="subIndex" :info="items" />
+					</block>
+				</div>
+			</div>
+			<!-- 订单信息 -->
+			<div class="module-com order-msg">
+				<div class="module-tit">订单信息</div>
+				<div class="module-det">
+					<!--  -->
+					<div class="order-msg-blo">
+						<div class="msg-list">
+							<div class="label">收花人</div>
+							<div class="value">{{ data.receiveUserName }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">电话</div>
+							<div class="value">{{ data.receiveMobile }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">地址</div>
+							<div class="value">{{ data.receiveFullAddress }}</div>
+						</div>
+					</div>
+					<!--  -->
+					<div class="order-msg-blo">
+						<div class="msg-list">
+							<div class="label">送达时间</div>
+							<div class="value">{{ data.reachDate || '暂无' }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">贺卡</div>
+							<div class="value">{{ data.needCard == 1 ? "需要" : '不需要' }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">祝福语</div>
+							<div class="value">{{ data.cardInfo || '暂无' }}</div>
+						</div>
+					</div>
+					<!--  -->
+					<!-- <div class="order-msg-blo">
+						<div class="msg-list">
+							<div class="label">订花人</div>
+							<div class="value">{{ data.bookName }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">微信</div>
+							<div class="value">{{ data.bookName }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">手机</div>
+							<div class="value">{{ data.bookMobile }}</div>
+						</div>
+					</div>-->
+					<!--  -->
+					<div class="order-msg-blo">
+						<div class="msg-list">
+							<div class="label">客户评分</div>
+							<div class="value">
+								<!-- <span>{{ data.totalFlow }}</span> -->
+								<rate-module :current="Number(data.totalFlow) || 0" :disabled="true"></rate-module>
+							</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">客户留言</div>
+							<div class="value">{{ data.evaluate || '暂无' }}</div>
+						</div>
+					</div>
+					<!--  -->
+					<div class="order-msg-blo">
+						<div class="msg-list">
+							<div class="label">订单号</div>
+							<div class="value">{{ data.orderSn }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">时间</div>
+							<div class="value">{{ data.addTime | formatTime }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">总价</div>
+							<div class="value">¥{{ data.prePrice }}</div>
+						</div>
+						<div class="msg-list">
+							<div class="label">运费</div>
+							<div class="value">¥{{ data.sendCost }}</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<!-- 优惠信息 -->
+			<div class="module-com coupon-wrap" v-if="data.discountAmount && data.discountAmount != '0.00'">
+				<div class="module-det flex-center-between">
+					<div class="app-color-3">{{ data.discountType == 0 ? '使用优惠券' : data.discountType == 1 ? '会员打折' : '付款随机优惠' }}</div>
+					<div class="app-price">-¥{{ data.discountAmount }}</div>
+				</div>
+			</div>
+		</div>
+		<!-- 按钮 -->
+		<div class="page-btn app-footer">
+			<div class="flex-center">
+				<span>应付款</span>
+				<span class="app-price">
+					<span>¥</span>
+					<span class="app-size-40">{{ data.prePrice }}</span>
+				</span>
+			</div>
+			<template>
+			    <!--
+				<button class="admin-button-com middle" @click="updatePriceFn">修改价格</button>
+				-->
+			</template>
+			<template>
+				<div class="operate-btn-wrap">
+				    <block v-if="data.status == 0">
+				        <button class="admin-button-com middle" style="color: #666666;border-color: #dddddd;">自取</button>
+                        <button class="admin-button-com middle" style="color: #666666;border-color: #dddddd;">发货</button>
+				    </block>
+				    <block v-else-if="data.status == 4">
+				    </block>
+					<block v-else-if="['5','6'].indexOf(data.status) != -1">
+
+					    <button v-if="data.sendType == 3" class="admin-button-com middle" style="color: #dddddd;border-color:#dddddd;">已自取</button>
+						<button v-else class="admin-button-com middle" @click="seeSendFn">已送达</button>
+
+					</block>
+					<block v-else>
+						<button class="admin-button-com middle" @click.stop="freeShippingFn">自取</button>
+						<button class="admin-button-com middle" @click.stop="pageTo({
+						url: '/admin/order/ship',
+						query: {
+							id: data.id,
+							pageStatus: 0
+						}
+					})">发货</button>
+					</block>
+				</div>
+			</template>
+			<!-- <template v-if="data.status == 5">
+				<button class="admin-button-com middle">退款</button>
+			</template>-->
+		</div>
+		<!-- 修改价格 -->
+		<modal-module :show="updatePriceModal" @cancel="modalCancel" @click="updateModalClick" title="修改价格" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap">
+					<div class="inp-list-line required">
+						<!-- <div class="line-label">角色名称</div> -->
+						<div class="line-input">
+							<input v-model="form.price" type="text" :adjust-position="false" class="inp-input" placeholder="请输入价格" />
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 免发货弹窗 -->
+		<modal-module :show="freeShipModal" @cancel="modalCancel" @click="freeShipModalClick" content="确认客户已自取?" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+import ListModule from '@/components/module/app-order-list'
+import AppCoupon from '@/components/app-coupon-sel'
+import ModalModule from '@/components/plugin/modal'
+import RateModule from '@/components/plugin/rate'
+// api
+import { getDetB, freeShipping, orderUpdatePrice } from '@/api/order'
+export default {
+	name: 'order-detail',
+	components: {
+		ListModule,
+		AppCoupon,
+		ModalModule,
+		RateModule
+	},
+	data() {
+		return {
+			constant: this.$constant,
+			// img
+			waitPayImg: `${this.$constant.imgUrl}/retail/order/wait-pay.png`,
+			waitDeliveryImg: `${this.$constant.imgUrl}/retail/order/wait-delivery.png`,
+			data: {},
+			// 修改价格
+			updatePriceModal: false,
+			form: {
+				price: ''
+			},
+			// 免发货
+			freeShipModal: false
+		}
+	},
+	onLoad() {
+		// this.init()
+	},
+	methods: {
+		init() {
+			this._getDet()
+		},
+		_getDet() {
+			return getDetB({ id: this.option.id }).then(res => {
+				this.data = res.data
+			})
+		},
+		// 免发货
+		freeShippingFn() {
+			this.freeShipModal = true
+		},
+		// 免发货
+		freeShipModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				this.data.status = 2
+				freeShipping({ id: this.data.id }).then(res => {
+					this.$msg('操作成功!')
+					this.modalCancel()
+				})
+			}
+		},
+		// 查看配送
+		seeSendFn() {
+			this.$util.pageTo({
+				url: '/admin/order/ship',
+				query: {
+					id: this.data.id,
+					pageStatus: 5
+				}
+			})
+		},
+		// 修改价格
+		updatePriceFn() {
+			this.form.price = this.data.prePrice
+			this.updatePriceModal = true
+		},
+		updateModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				orderUpdatePrice({ id: this.data.id, price: this.form.price }).then(res => {
+					this.modalCancel()
+					this.$msg('修改成功!')
+					setTimeout(() => {
+						this._getDet()
+					}, 1000)
+				})
+			}
+		},
+		// 关闭弹窗
+		modalCancel() {
+			this.form.price = ''
+			this.freeShipModal = false
+			this.updatePriceModal = false
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		padding-bottom: 80px;
+	}
+	.page-top {
+		position: relative;
+		.page-top-det {
+			position: absolute;
+			top: 22px;
+			@include disFlex(center, space-between);
+			width: 84%;
+			padding: 0 48px;
+			color: #fff;
+			.page-status {
+				font-size: 36px;
+				font-weight: bold;
+				margin-bottom: 16px;
+			}
+			.page-prompt {
+				color: #ffdede;
+			}
+			.page-status-img {
+				width: 180px;
+			}
+		}
+	}
+	.page-det {
+		width: 94%;
+		margin: 0 auto;
+		position: relative;
+		top: -40px;
+		.order-msg {
+			.order-msg-blo {
+				font-size: 28px;
+				padding: 20px 0;
+				border-top: 1px solid $borderColor;
+				.msg-list {
+					@include disFlex(flex-start, space-between);
+					margin: 16px 0;
+					.label {
+						width: 40%;
+						color: $fontColor3;
+					}
+				}
+			}
+			& .order-msg-blo:first-child {
+				border-top: none;
+			}
+		}
+		.coupon-wrap {
+			.module-det {
+				padding: 20px 0;
+			}
+		}
+	}
+	// 底部按钮
+	.page-btn {
+		width: calc(100% - 60px);
+		@include disFlex(center, space-between);
+		padding: 0 30px;
+		.app-price {
+			margin-bottom: 8px;
+			margin-left: 4px;
+		}
+		.red {
+			width: 270px;
+		}
+		.default {
+			width: 260px;
+		}
+		.operate-btn-wrap {
+			.admin-button-com {
+				margin-left: 30px;
+				padding: 20px 30px;
+			}
+		}
+	}
+	// 公共模块
+	.module-com {
+		border-radius: 10px;
+		background-color: #fff;
+		padding: 0 20px;
+		box-shadow: 0px 6px 16px #ddd;
+		margin-bottom: 20px;
+		.module-tit {
+			padding: 20px 0;
+			font-size: 28px;
+			font-weight: 600;
+			border-bottom: 1px solid $borderColor;
+		}
+	}
+</style>

+ 112 - 0
store/src/admin-order/fill-form.vue

@@ -0,0 +1,112 @@
+<template>
+	<div class="app-content">
+		<form @submit="formSubmit">
+			<app-delivery-module ref="appDelivery" />
+			<!-- 匿名派送 -->
+			<!-- <div class="none-name-delivery flex-center">
+				<checkbox class="ljd-checkbox" @change="anonymityChange"></checkbox>
+				<span class="none-name-text">匿名派送</span>
+			</div> -->
+			<!-- 按钮 -->
+			<div class="app-footer">
+				<button class="admin-button-com blue middle" formType="submit">提交</button>
+			</div>
+		</form>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import AppDeliveryModule from '@/components/app-delivery'
+const form = require('@/utils/formValidation.js')
+// api
+// import { getShopUser } from '@/utils/auth'
+import { getOrderShop } from '@/utils/config'
+import { updateSheet } from '@/api/order'
+export default {
+	name: 'fill-form',
+	components: {
+		AppDeliveryModule
+	},
+	data() {
+		return {
+			// 初始form
+			form: {
+				anonymity: '0' // 是否匿名 0不 1要
+			}
+		}
+	},
+	computed: {
+		...mapGetters({ orderShop: 'getOrderShop' }),
+		// ...mapGetters({ shopUser: 'getShopUser' })
+	},
+	onLoad() {
+		// this.init()
+	},
+	methods: {
+		init() {
+			getOrderShop()
+			// getShopUser()
+		},
+		confirmFn() {
+			let form = this.$refs.appDelivery.form ? this.$refs.appDelivery.form : {}
+			let region = this.$refs.appDelivery.region ? this.$refs.appDelivery.region : {}
+			updateSheet({
+				id: this.option.id,
+				...this.form,
+				...form,
+				...region
+			}).then(res => {
+				this.$util.pageTo({
+					url: '/admin/order/ship',
+					query: {
+						id: this.option.id,
+						pagestatus: 1
+					}
+				})
+			})
+		},
+		// operate
+		anonymityChange(e) {
+			this.form.anonymity = this.form.anonymity == 1 ? 0 : 1
+		},
+		// 表单验证
+		formSubmit(e) {
+			// 表单规则
+			let rules = [
+				// {
+				// 	name: 'receiveUserName',
+				// 	rule: ['required'],
+				// 	msg: ['请输入姓名']
+				// }
+			]
+			// 进行表单检查
+			let formData = e.detail.value
+			let checkRes = form.validation(formData, rules)
+			// 验证通过!
+			if (!checkRes) {
+				this.confirmFn()
+			} else {
+				this.$msg(checkRes)
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	// 匿名派送
+	.none-name-delivery {
+		padding-left: 30px;
+		margin-top: 40px;
+		.none-name-text {
+			margin-left: 14px;
+			color: $fontColor2;
+		}
+	}
+	.app-footer {
+		.admin-button-com {
+			width: 90%;
+		}
+	}
+</style>

+ 246 - 0
store/src/admin-order/ship.vue

@@ -0,0 +1,246 @@
+<template>
+	<div class="app-content">
+		<!-- order-top -->
+		<div class="module-com order-wrap" v-if="!$util.isEmpty(data)">
+			<div class="order-det">
+				<div>
+					<div class="label">订单号</div>
+					<div>{{ data.orderSn }}</div>
+				</div>
+				<div>
+					<div class="label">下单时间</div>
+					<div>{{ data.addTime | formatTime }}</div>
+				</div>
+				<div v-if="!$util.isEmpty(data.goodsInfoList)">
+					<div class="label">商品名称</div>
+					<div>{{ data.goodsInfoList[0].title }}</div>
+				</div>
+				<div>
+					<div class="label">金额</div>
+					<div>¥{{ data.actPrice }}</div>
+				</div>
+			</div>
+			<div class="order-img" v-if="!$util.isEmpty(data.goodsInfoList)">
+				<img :src="data.goodsInfoList[0].smallCoverUrl" alt="商品图" mode="widthFix" />
+			</div>
+		</div>
+		<!-- order-bottom -->
+		<div class="module-com order-axis" v-if="showIndex != null">
+			<!-- 列表 -->
+			<!-- 选择订单 -->
+			<block v-if="showIndex == 0">
+				<sel-order :orderData="data" :query="option" />
+			</block>
+			<!-- 选择发货 -->
+			<block v-if="showIndex == 1">
+				<sel-ship :orderData="data" :query="option" :orderComData="orderComData" />
+			</block>
+			<!-- 选择自提 -->
+			<!-- <block v-if="showIndex == 2">
+				<sel-mention :orderData="data" :query="option" />
+			</block> -->
+			<!-- 快递送待接单 -->
+			<!-- <block v-if="showIndex == 3">
+				<sel-pending-order :orderData="data" :query="option" :orderComData="orderComData" />
+			</block> -->
+			<!-- 发货选择快递送已接单 -->
+			<block v-if="showIndex == 4">
+				<sel-express-confirm :orderData="data" :query="option" :orderComData="orderComData" />
+			</block>
+			<!-- 发货选择完成 -->
+			<block v-if="showIndex == 5">
+				<sel-confirm :orderData="data" :query="option" :orderComData="orderComData" />
+			</block>
+			<!-- 发货管理完成 -->
+			<block v-if="showIndex == 6">
+				<sel-ship-confirm :orderData="data" :query="option" :orderComData="orderComData" />
+			</block>
+			<!-- 有配送单-发货管理 -->
+			<block v-if="showIndex == 7">
+				<sel-ship-manage :orderData="data" :query="option" :orderComData="orderComData" />
+			</block>
+		</div>
+	</div>
+</template>
+
+<script>
+// 选择订单
+import SelOrder from './components/sel-order'
+// 选择发货
+import SelShip from './components/sel-ship'
+// 选择自提
+import SelMention from './components/sel-mention'
+// 快递送待接单
+import SelPendingOrder from './components/sel-pending-order'
+// 发货选择快递送已接单
+import SelExpressConfirm from './components/sel-express-confirm'
+// 发货选择完成
+import SelConfirm from './components/sel-confirm'
+// 发货管理完成
+import SelShipConfirm from './components/sel-ship-confirm'
+// 有配送单-发货管理
+import SelShipManage from './components/sel-ship-manage'
+
+// api
+import { getDetB, orderSendDet } from '@/api/order'
+export default {
+	name: 'admin-ship',
+	components: {
+		SelOrder,
+		SelShip,
+		SelMention,
+		SelPendingOrder,
+		SelExpressConfirm,
+		SelConfirm,
+		SelShipConfirm,
+		// 有配送单
+		SelShipManage
+	},
+	data() {
+		return {
+			showIndex: null,
+			data: {},
+			orderComData: []
+		}
+	},
+	onLoad() {
+		uni.showLoading({
+			title: '加载中...',
+			mask: true
+		})
+		// this.init()
+	},
+	methods: {
+		init() {
+			// this.showIndex = this.option.pageStatus || 0
+			this._getDet()
+
+			this._orderComDet()
+		},
+		_getDet() {
+			return getDetB({ id: this.option.id }).then(res => {
+				this.data = res.data
+			})
+		},
+		_orderComDet() {
+			orderSendDet({ id: this.option.id }).then(res => {
+				this.orderComData = res.data
+				this.getPageStatus()
+			})
+		},
+		getPageStatus() {
+			uni.hideLoading()
+			if (this.$util.isEmpty(this.orderComData)) return false
+			let actionSign = this.orderComData[0].actionSign
+			if (actionSign == 'printOrder') {
+				let receive = this.orderComData[0].receive
+				if (this.$util.isEmpty(receive)) {
+					this.showIndex = 0
+				} else {
+					this.showIndex = 1
+				}
+			} else if (actionSign == 'deliver') {
+				this.showIndex = 7
+			} else if (actionSign == 'reach') {
+				if (this.orderComData[0].finishTime == 0) {
+					this.showIndex = 4
+				} else {
+					// let classify = this.orderComData[0].classify
+					// if (this.$util.isEmpty(classify)) {
+					// 	this.showIndex = 5
+					// } else {
+					this.showIndex = 6
+					// }
+				}
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		background-color: #fff;
+	}
+	// 公共
+	.module-com {
+		padding: 30px;
+		// margin-bottom: 20px;
+	}
+	// 订单信息
+	.order-wrap {
+		@include disFlex(center, space-between);
+		padding: 20px;
+		border-bottom: 20px solid $backColor;
+		.order-det {
+			font-size: 24px;
+			& > div {
+				@include disFlex(center, flex-start);
+				margin-top: 12px;
+				&:first-child {
+					margin-top: 0;
+				}
+				.label {
+					width: 120px;
+					color: $fontColor2;
+				}
+			}
+		}
+		.order-img {
+			width: 146px;
+		}
+	}
+	// 订单详情
+	.order-axis {
+		padding-top: 50px;
+		// 公共
+		/deep/.axis-list {
+			margin-bottom: 50px;
+			.axis-slot-wrap {
+				position: relative;
+				top: -14px;
+				.axis-title {
+					font-size: 30px;
+					font-weight: 600;
+				}
+			}
+			.btn-wrap-com {
+				.admin-button-com {
+					width: 120px;
+					margin-left: 20px;
+					&:first-child {
+						margin-left: 0;
+					}
+				}
+			}
+		}
+		// 首个圆点
+		/deep/.axis-first {
+			.axis-slot-wrap {
+				top: -4px !important;
+			}
+			.node-big {
+				position: absolute;
+				top: 0;
+				left: -20px;
+				transform-origin: 0;
+				transform: translateX(-50%);
+				width: 32px !important;
+				height: 32px !important;
+				border-radius: 50%;
+				background: #fdc3b8;
+			}
+			.node-small {
+				position: absolute;
+				top: 8px;
+				left: 16px;
+				transform-origin: 0;
+				transform: translateX(-50%);
+				background: #f51608;
+				width: 16px !important;
+				height: 16px !important;
+				border-radius: 50%;
+			}
+		}
+	}
+</style>

+ 357 - 0
store/src/admin-staff/add.vue

@@ -0,0 +1,357 @@
+<template>
+  <div class="app-content">
+    <div v-show="showStaffArea">
+      <!-- 员工信息 -->
+      <form @submit="formSubmit" @reset="formReset">
+        <div class="module-com input-line-wrap">
+          <tui-list-cell class="line-cell" :hover="false">
+            <div class="tui-title required">姓名</div>
+            <input
+              v-model="form.adminName"
+              placeholder-class="phcolor"
+              class="tui-input"
+              name="adminName"
+              placeholder="请输入姓名"
+              maxlength="50"
+              type="text"
+            />
+          </tui-list-cell>
+          <!--
+                <tui-list-cell class="line-cell" :hover="false">
+                    <div class="tui-title required">手机号</div>
+                    <input v-model="form.mobile" placeholder-class="phcolor" class="tui-input" name="mobile" placeholder="请输入手机号" maxlength="50" type="number" />
+                </tui-list-cell>
+          -->
+          <tui-list-cell class="line-cell" :arrow="true">
+            <div class="tui-title required">角色</div>
+            <picker
+              mode="selector"
+              :value="form.roleId"
+              :range="roleList"
+              range-key="roleName"
+              @change="changeRoleFn"
+              class="tui-input"
+            >
+              <input v-model="form.roleId" name="roleId" type="text" hidden />
+              <div v-if="form.roleId">{{ roleSelData.roleName }}</div>
+              <div class="tui-placeholder" v-else>请选择</div>
+            </picker>
+          </tui-list-cell>
+          <!--
+				<tui-list-cell class="line-cell" :arrow="true" @click="selMemberFn">
+					<div class="tui-title required">绑定微信</div>
+					<div v-if="form.userId" class="member-wrap flex-center">
+						<input v-model="form.userId" name="userId" type="text" hidden />
+						<div class="member-img">
+							<app-avatar-module :src="memberData.avatarUrl" :width="60" />
+						</div>
+						<div class="member-det">
+							<div class="app-size-28">{{ memberData.userName }}</div>
+							<div>{{ memberData.mobile == 0 ? '暂无' : memberData.mobile }}</div>
+						</div>
+					</div>
+					<div v-else class="tui-placeholder">请选择</div>
+				</tui-list-cell>
+          -->
+        </div>
+        <!-- 收款通知 -->
+        <div class="module-com input-line-wrap">
+          <tui-list-cell class="line-cell between" padding="14rpx 30rpx" :hover="false">
+            <div class="tui-title">收款通知</div>
+            <div>
+              <switch :checked="form.remind == 0 ? false : true" @change="remindChangeFn" />
+            </div>
+          </tui-list-cell>
+        </div>
+        <!-- 登录信息 -->
+        <div class="module-com input-line-wrap">
+          <tui-list-cell class="line-cell" :hover="false">
+            <div class="tui-title">登录密码</div>
+            <input
+              v-model="form.password"
+              placeholder-class="phcolor"
+              class="tui-input"
+              name="password"
+              placeholder="请输入"
+              maxlength="50"
+              type="password"
+            />
+          </tui-list-cell>
+          <tui-list-cell class="line-cell remark-wrap" :hover="false">
+            <div class="tui-title">备注信息</div>
+            <div class="tui-input">
+              <textarea
+                v-model="form.remark"
+                class="tui-textarea remark"
+                placeholder-class="phcolor"
+                placeholder="请输入内容"
+              />
+            </div>
+          </tui-list-cell>
+        </div>
+        <!-- 马上启用 -->
+        <div class="module-com input-line-wrap">
+          <tui-list-cell class="line-cell between" padding="14rpx 30rpx" :hover="false">
+            <div class="tui-title">启用状态</div>
+            <div>
+              <switch :checked="form.status == 0 ? false : true" @change="statusChangeFn" />
+            </div>
+          </tui-list-cell>
+        </div>
+        <!-- 提交 -->
+        <div class="confirm-btn">
+          <button class="admin-button-com big blue" formType="submit">提交</button>
+        </div>
+      </form>
+    </div>
+    <div v-show="showMiniCodeArea">
+      <view style="text-align:center;">
+          <image style="width:200px;height:200px;margin:0 auto;" :src="miniCodeSrc"></image>
+          <view style="text-align:center;margin-top:20px;margin-bottom:20px;">请扫上方小程序码完成绑定</view>
+          <button class="admin-button-com big blue" @click="complete">完成</button>
+      </view>
+    </div>
+  </div>
+</template>
+
+<script>
+import TuiListCell from "@/components/plugin/list-cell";
+import AppAvatarModule from "@/components/module/app-avatar";
+const form = require("@/utils/formValidation.js");
+// api
+import {
+  getRoleList,
+  getStaffDet as getDet,
+  updateStaff as update
+} from "@/api/staff";
+import { getDet as getMemberDet } from "@/api/member";
+import { prepareBind } from "@/api/admin-shop";
+export default {
+  name: "staff-add",
+  components: {
+    TuiListCell,
+    AppAvatarModule
+  },
+  data() {
+    return {
+      form: {
+        adminName: "",
+        //mobile: '',
+        roleId: "",
+        remind: 1,
+        password: "",
+        //userId: '',
+        status: 1,
+        remark: "",
+      },
+      roleList: [],
+      roleSelData: {},
+      showStaffArea: true,
+      showMiniCodeArea: false,
+      miniCodeSrc:'',
+      memberData: {}
+    };
+  },
+  onLoad() {
+    // this.init()
+  },
+  onShow() {
+    if (this.option.id) {
+      uni.setNavigationBarTitle({
+        title: `修改员工`
+      });
+    } else {
+      uni.setNavigationBarTitle({
+        title: `添加员工`
+      });
+    }
+  },
+  methods: {
+    init() {
+      let data = uni.getStorageSync("addStaffData");
+      if (data) {
+        uni.removeStorageSync("addStaffData");
+        this.form = data.form;
+        this.roleList = data.roleList;
+        this.roleSelData = data.roleSelData;
+      }
+      let memberData = uni.getStorageSync("addSelMember");
+      if (memberData) {
+        uni.removeStorageSync("addSelMember");
+        this.memberData = memberData;
+        this.form.userId = memberData.id;
+      }
+
+      if (data) return false;
+
+      this._getRoleList().then(res => {
+        if (this.option.id) {
+          this._getDet();
+        }
+      });
+    },
+    // api
+    async _getRoleList() {
+      await getRoleList().then(res => {
+        if (this.$util.isEmpty(res.data)) return false;
+        this.roleList = res.data.list;
+      });
+    },
+    _getDet() {
+      getDet({ id: this.option.id }).then(res => {
+        if (this.$util.isEmpty(res.data)) return;
+        Object.keys(this.form).forEach((i, index) => {
+          // if (i != 'password') {
+          this.form[i] = res.data[i];
+          // }
+        });
+        this.roleSelData = this.roleList.filter(
+          e => this.form.roleId == e.id
+        )[0];
+
+        if (this.form.userId && this.form.userId != "0") {
+          this._getMemberDet();
+        }
+      });
+    },
+    // 获取客户详情
+    _getMemberDet() {
+      getMemberDet({ userId: this.form.userId }).then(res => {
+        if (this.$util.isEmpty(res.data)) return;
+        this.memberData = res.data;
+      });
+    },
+    // option
+    // 关联微信
+    selMemberFn() {
+      let data = {
+        form: this.form,
+        roleList: this.roleList,
+        roleSelData: this.roleSelData
+      };
+      uni.setStorageSync("addStaffData", data);
+      this.$util.pageTo({
+        url: "/admin/staff/sel-member",
+        query: {
+          ...this.option
+        }
+      });
+    },
+    changeRoleFn(e) {
+      this.roleSelData = this.roleList[e.detail.value];
+      this.form.roleId = this.roleSelData.id;
+    },
+    remindChangeFn(e) {
+      this.form.remind = e.detail.value ? 1 : 0;
+    },
+    statusChangeFn(e) {
+      this.form.status = e.detail.value ? 1 : 0;
+    },
+    confirmFn() {
+      let hostFn = this.option.id ? update : prepareBind;
+      if (this.option.id) {
+        this.form.id = this.option.id;
+      }
+      hostFn(this.form).then(res => {
+        console.log('23rh23r23')
+        console.log(res)
+        console.log(this.option.id)
+        if(typeof(this.option.id) == 'undefined'){
+          this.showMiniCodeArea = true;
+          this.miniCodeSrc = res.data.miniCode;
+          this.showStaffArea = false;
+          console.log(this.miniCodeSrc)
+          console.log('--oo0oooo---')
+        }
+        // let promptText = this.option.id ? "修改成功!" : "添加成功!";
+        // this.$msg(promptText);
+        // setTimeout(() => {
+        //   this.$util.pageTo({
+        //     url: "/admin/staff/list",
+        //     type: 2
+        //   });
+        // }, 1000);
+      });
+    },
+    complete(){
+      this.$util.pageTo(1)
+    },
+    // 表单验证
+    formSubmit(e) {
+      // 表单规则
+      let rules = [
+        {
+          name: "adminName",
+          rule: ["required"],
+          msg: ["请输入姓名"]
+        },
+        // {
+        // 	name: 'mobile',
+        // 	rule: ['required'],
+        // 	msg: ['请输入手机号']
+        // },
+        {
+          name: "roleId",
+          rule: ["required"],
+          msg: ["请选择角色"]
+        }
+        // {
+        // 	name: 'userId',
+        // 	rule: ['required'],
+        // 	msg: ['请选择关联微信']
+        // }
+        // {
+        // 	name: 'password',
+        // 	rule: ['required'],
+        // 	msg: ['请输入密码']
+        // }
+      ];
+      // 进行表单检查
+      let formData = e.detail.value;
+      let checkRes = form.validation(formData, rules);
+      // 验证通过!
+      if (!checkRes) {
+        this.confirmFn();
+      } else {
+        this.$msg(checkRes);
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.app-content {
+  min-height: calc(100vh - 20px);
+  padding-top: 20px;
+}
+.prompt-text {
+  color: $fontColor3;
+  padding-left: 30px;
+  margin-bottom: 30px;
+}
+// ---
+.module-com {
+  margin-bottom: 20px;
+  .member-wrap {
+    .member-det {
+      font-size: 24px;
+      margin-left: 20px;
+    }
+  }
+  .remark-wrap {
+    align-items: flex-start;
+    .remark {
+      height: 240px;
+    }
+  }
+}
+// 按钮
+.confirm-btn {
+  width: calc(100% - 60px);
+  margin: 60px 30px 20px;
+  .admin-button-com {
+    width: 100%;
+  }
+}
+</style>

+ 386 - 0
store/src/admin-staff/list.vue

@@ -0,0 +1,386 @@
+<template>
+	<div class="app-content">
+		<app-tabs :tabs="tabs" :isFixed="true" :currentTab="tabIndex" @change="change" itemWidth="33.33%" />
+		<!-- 员工列表 -->
+		<block v-if="tabIndex == 0">
+			<!-- 列表 -->
+			<div class="list-wrap staff-list">
+				<block v-if="!$util.isEmpty(list.data)">
+					<div class="list" v-for="(item, index) in list.data" :key="index">
+						<div>
+							<app-avatar-module :src="item.avatarUrl" :width="90" />
+						</div>
+						<div class="list-det">
+							<div class="list-det-left">
+								<div>
+									<span class="staff-name">{{ item.adminName }}</span>
+									<span>{{ item.roleName }}</span>
+								</div>
+								<div class="flex-center">
+									<div class="status-list">
+										<i class="iconfont icondagou" :class="[item.incomeNotice ? 'app-color-1' : '' ]"></i>
+										<span :class="[item.incomeNotice ? 'app-color-1' : 'app-color-3' ]">收款通知</span>
+									</div>
+									<div class="status-list">
+										<i class="iconfont icondagou" :class="[item.status ? 'app-color-1' : '' ]"></i>
+										<span :class="[item.status ? 'app-color-1' : 'app-color-3' ]">启用</span>
+									</div>
+								</div>
+							</div>
+							<div class="list-det-right">
+								<div @click="pageTo({
+								url: '/admin/staff/add',
+								query: {
+									id: item.id
+								}
+							})">
+									<i class="iconfont iconbianji"></i>
+								</div>
+								<!-- 删除 -->
+								<div @click="delModalFn(item)">
+									<i class="iconfont iconshanchu1"></i>
+								</div>
+							</div>
+						</div>
+					</div>
+				</block>
+				<block v-else>
+					<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+				</block>
+			</div>
+			<!-- 按钮 -->
+			<div class="app-footer">
+				<div class="admin-button-com middle blue" @click="pageTo('/admin/staff/add')">添加</div>
+			</div>
+		</block>
+		<!-- 角色管理 -->
+		<block v-if="tabIndex == 1">
+			<!-- 列表 -->
+			<div class="list-wrap role-list">
+				<block v-if="!$util.isEmpty(list.data)">
+					<div class="list" v-for="(item, index) in list.data" :key="index">
+						<div class="app-size-32">{{ item.roleName }}(10)</div>
+						<div class="role-option">
+							<div @click="modifyRoleFn(item)">
+								<i class="iconfont iconbianji"></i>
+							</div>
+							<div @click="delModalFn(item)">
+								<i class="iconfont iconshanchu1"></i>
+							</div>
+						</div>
+					</div>
+				</block>
+				<block v-else>
+					<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+				</block>
+			</div>
+			<!-- 按钮 -->
+			<div class="app-footer">
+				<div class="admin-button-com middle blue" @click="addRoleFn">添加角色</div>
+			</div>
+		</block>
+		<!-- 操作记录 -->
+		<block v-if="tabIndex == 2">
+			<!-- 列表 -->
+			<div class="axis-wrap">
+				<block v-if="!$util.isEmpty(list.data)">
+					<time-axis>
+						<timeaxis-item class="axis-list" bgcolor="none" v-for="(item, index) in list.data" :key="index">
+							<template v-slot:content>
+								<div class="axis-title">{{ item.content }}</div>
+								<div class="axis-det">
+									<div>ID:{{ item.id }}</div>
+									<div>IP:{{ item.ip }}</div>
+									<div>操作者:{{ item.adminName }}</div>
+									<div>操作时间:{{ item.addTime | formatTime }}</div>
+								</div>
+							</template>
+						</timeaxis-item>
+					</time-axis>
+				</block>
+				<block v-else>
+					<app-wrapper-empty title="暂无数据" :is-empty="$util.isEmpty(list.data)" />
+				</block>
+			</div>
+		</block>
+		<!-- 角色操作 -->
+		<modal-module :show="roleModal" @cancel="modalCancel" @click="roleModalClick" :title="roleModalText" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap">
+					<div class="inp-list-line required">
+						<div class="line-label">角色名称</div>
+						<div class="line-input">
+							<input v-model="roleModalVal" type="text" :adjust-position="false" class="inp-input">
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 删除弹窗 -->
+		<modal-module :show="delModal" @cancel="modalCancel" @click="delModalClick" :content="delModalText" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+import AppTabs from '@/components/plugin/tabs'
+import AppAvatarModule from '@/components/module/app-avatar'
+// 时间轴
+import TimeAxis from '@/admin/home/components/plugin/time-axis'
+import TimeaxisItem from '@/admin/home/components/plugin/timeaxis-item'
+import AppWrapperEmpty from '@/components/app-wrapper-empty'
+import ModalModule from '@/components/plugin/modal'
+import { list } from '@/mixins'
+// api
+import { getStaffList, delStaff, getRoleList, addRole, updateRole, delRole, getLogList } from '@/api/staff'
+export default {
+	name: 'staff-list',
+	components: {
+		AppTabs,
+		AppAvatarModule,
+		TimeAxis,
+		TimeaxisItem,
+		AppWrapperEmpty,
+		ModalModule
+	},
+	mixins: [list],
+	data() {
+		return {
+			tabIndex: 0,
+			tabs: [
+				{
+					name: '员工列表'
+				},
+				{
+					name: '角色管理'
+				},
+				{
+					name: '操作记录'
+				}
+			],
+			// 删除弹窗操作
+			delModal: false,
+			delModalText: '确定删除该员工吗?',
+			operateData: {},
+			// 角色弹窗操作
+			roleModal: false,
+			roleModalText: '添加',
+			roleModalVal: '',
+			roleOperateData: {}
+		}
+	},
+	onPullDownRefresh() {
+		this.resetList()
+		this._list().then(res => {
+			uni.stopPullDownRefresh()
+		})
+	},
+	onReachBottom() {
+		if (!this.list.finished) {
+			this._list().then(res => {
+				uni.stopPullDownRefresh()
+			})
+		} else {
+			uni.stopPullDownRefresh()
+		}
+	},
+	onLoad: function() {
+		// this.init()
+	},
+	methods: {
+		async init() {
+			this._list()
+		},
+		_list() {
+			let hostFn = this.tabIndex == 0 ? getStaffList : this.tabIndex == 1 ? getRoleList : getLogList
+			return hostFn().then(res => {
+				this.completes(res)
+			})
+		},
+		change(e) {
+			if (this.tabIndex == e.index) {
+				return false
+			} else {
+				this.tabIndex = e.index
+				this.resetList()
+				this._list()
+			}
+		},
+		// 关闭弹窗
+		modalCancel() {
+			this.delModal = false
+			this.roleModal = false
+		},
+		// 删除弹窗
+		delModalFn(item) {
+			this.delModalText = this.tabIndex == 0 ? '确定删除该员工吗?' : '确定删除该角色吗?'
+			this.operateData = item
+			this.delModal = true
+		},
+		delModalClick(e) {
+			let index = e.index
+			if (index === 0) {
+				this.modalCancel()
+			} else {
+				let hostFn = this.tabIndex == 0 ? delStaff : delRole
+				hostFn({ id: this.operateData.id }).then(res => {
+					this.modalCancel()
+					this.$msg('删除成功!')
+					setTimeout(() => {
+						this.resetList()
+						this._list()
+					}, 1000)
+				})
+			}
+		},
+		// 角色操作
+		addRoleFn() {
+			this.roleModal = true
+			this.roleModalText = '添加'
+			this.roleModalVal = ''
+		},
+		modifyRoleFn(item) {
+			this.roleModal = true
+			this.roleModalText = '修改'
+			this.roleModalVal = item.roleName
+			this.roleOperateData = item
+		},
+		roleModalClick(e) {
+			let index = e.index
+			if (index === 0) {
+				this.modalCancel()
+			} else {
+				let hostFn = this.roleModalText == '添加' ? addRole : updateRole
+				let params = {
+					roleName: this.roleModalVal
+				}
+				if (this.roleModalText == '修改') {
+					params.id = this.roleOperateData.id
+				}
+				hostFn(params).then(res => {
+					this.modalCancel()
+					this.$msg(`${this.roleModalText}成功!`)
+					setTimeout(() => {
+						this.resetList()
+						this._list()
+					}, 1000)
+				})
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+	.app-content {
+		min-height: calc(100vh - 200px);
+		padding-top: 100px;
+		padding-bottom: 100px;
+	}
+	// 列表公共
+	.list-wrap {
+		background-color: #fff;
+		.list {
+			@include disFlex(center, flex-start);
+			margin: 0 30px;
+			padding: 30px 0;
+			border-bottom: 2px solid $borderColor;
+		}
+	}
+	// 员工列表
+	.staff-list {
+		.list-det {
+			width: calc(100% - 110px);
+			color: $fontColor3;
+			margin-left: 20px;
+			@include disFlex(center, space-between);
+			.list-det-left {
+				.staff-name {
+					color: #333;
+					font-size: 30px;
+					font-weight: 600;
+					margin-right: 10px;
+				}
+				.flex-center {
+					margin-top: 10px;
+				}
+				.status-list {
+					margin-left: 60px;
+					&:first-child {
+						margin-left: 0;
+					}
+					.iconfont {
+						// color: $fontColor3;
+						font-size: 24px;
+						margin-right: 10px;
+					}
+				}
+			}
+			.list-det-right {
+				@include disFlex(center, flex-start);
+				& > div {
+					margin-left: 50px;
+					&:first-child {
+						margin-left: 0;
+					}
+				}
+				.iconfont {
+					font-size: 36px;
+					color: $fontColor3;
+				}
+			}
+		}
+	}
+	// 角色管理
+	.role-list {
+		.list {
+			justify-content: space-between;
+		}
+		.role-option {
+			@include disFlex(center, flex-start);
+			& > div {
+				margin-left: 50px;
+				&:first-child {
+					margin-left: 0;
+				}
+			}
+			.iconfont {
+				font-size: 36px;
+				color: $fontColor3;
+			}
+		}
+	}
+	// 操作记录
+	.axis-wrap {
+		position: relative;
+		padding: 30px 30px 30px 40px;
+		background-color: #fff;
+		.axis-list {
+			&:last-child .axis-det {
+				margin-bottom: 0;
+			}
+		}
+		.axis-title {
+			font-size: 30px;
+			font-weight: 600;
+			margin-bottom: 14px;
+		}
+		.axis-det {
+			color: $fontColor2;
+			margin-bottom: 40px;
+			& > div {
+				margin-top: 6px;
+				&:first-child {
+					margin-top: 0;
+				}
+			}
+		}
+	}
+	// 按钮
+	.app-footer {
+		justify-content: flex-end;
+		.admin-button-com {
+			width: 160px;
+			margin-right: 30px;
+		}
+	}
+</style>

+ 77 - 0
store/src/admin-staff/sel-member.vue

@@ -0,0 +1,77 @@
+<template>
+	<div class="app-content">
+		<sel-search-module :list="list.data" :isMember="true" @search="searchFn" @change="changeFn"></sel-search-module>
+	</div>
+</template>
+
+<script>
+import SelSearchModule from '@/admin/home/components/sel-search'
+import { list } from '@/mixins'
+// api
+import { getList } from '@/api/member'
+export default {
+	name: 'staff-sel-member',
+	components: {
+		SelSearchModule
+	},
+	mixins: [list],
+	data() {
+		return {
+			search: ''
+		}
+	},
+	onPullDownRefresh() {
+		this.resetList()
+		this._list().then(res => {
+			uni.stopPullDownRefresh()
+		})
+	},
+	onReachBottom() {
+		if (!this.list.finished) {
+			this._list().then(res => {
+				uni.stopPullDownRefresh()
+			})
+		} else {
+			uni.stopPullDownRefresh()
+		}
+	},
+	onLoad: function() {
+		// this.init()
+	},
+	methods: {
+		async init() {
+			this._list()
+		},
+		_list() {
+			let params = {
+				page: this.list.page,
+				goodsName: this.search
+			}
+			return getList(params).then(res => {
+				this.completes(res)
+			})
+		},
+		// 搜索
+		searchFn(val) {
+			if (!val) return false
+			this.search = val
+			this.resetList()
+			this._list()
+		},
+		// 选择员工
+		changeFn(e) {
+			uni.setStorageSync('addSelMember', e)
+			this.$util.pageTo({
+				url: '/admin/staff/add',
+				query: {
+					...this.option
+				},
+				type: 2
+			})
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 131 - 0
store/src/admin-user/add.vue

@@ -0,0 +1,131 @@
+<template>
+	<div class="app-content">
+		<form @submit="formSubmit">
+			<div class="module-com input-line-wrap">
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title required">手机号</div>
+					<input v-model="form.mobile" placeholder-class="phcolor" class="tui-input" name="mobile" placeholder="请输入" maxlength="50" type="number" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title required">确认手机号</div>
+					<input v-model="form.confirmMobile" placeholder-class="phcolor" class="tui-input" name="confirmMobile" placeholder="请输入" maxlength="50" type="number" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title required">余额</div>
+					<input v-model="form.balance" placeholder-class="phcolor" class="tui-input" name="balance" placeholder="请输入" maxlength="50" type="number" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :arrow="true">
+					<div class="tui-title required">会员级别</div>
+					<picker mode="selector" :value="form.memberLevel" :range="levelData.list" range-key="level" @change="changeLevelFn" class="tui-input">
+						<input v-model="form.memberLevel" name="memberLevel" type="text" hidden />
+						<div v-if="form.memberLevel">{{ levelSelData.level }}</div>
+						<div class="tui-placeholder" v-else>请选择</div>
+					</picker>
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title">姓名</div>
+					<input v-model="form.realName" placeholder-class="phcolor" class="tui-input" name="phone" placeholder="请输入(选填)" maxlength="50" type="text" />
+				</tui-list-cell>
+				<tui-list-cell class="line-cell" :hover="false">
+					<div class="tui-title required">确认密码</div>
+					<input v-model="form.confirmPassword" placeholder-class="phcolor" class="tui-input" name="confirmPassword" placeholder="请输入确认密码" maxlength="50" type="password" />
+				</tui-list-cell>
+				<div class="prompt-text">添加后,申请会员时自动根据手机号识别客户,成长值、等级和余 额会自动同步。</div>
+				<div class="btn-wrap">
+					<button class="admin-button-com blue big" formType="submit">确认</button>
+				</div>
+			</div>
+		</form>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import TuiListCell from '@/components/plugin/list-cell'
+const form = require('@/utils/formValidation.js')
+// api
+import { getLevel } from '@/utils/config'
+import { add } from '@/api/member'
+export default {
+	name: 'member-add',
+	components: {
+		TuiListCell
+	},
+	data() {
+		return {
+			form: {
+				mobile: '',
+				confirmMobile: '',
+				balance: 0,
+				memberLevel: '',
+				realName: '',
+				confirmPassword: ''
+			},
+			levelSelData: {}
+		}
+	},
+	computed: {
+		...mapGetters({ levelData: 'getLevel' })
+	},
+	onLoad() {
+		getLevel()
+	},
+	methods: {
+		confirmFn() {
+			add(this.form).then(res => {
+				this.$msg('添加成功!')
+				setTimeout(() => {
+					this.$util.pageTo(1)
+				}, 1000)
+			})
+		},
+		changeLevelFn(e) {
+			this.levelSelData = this.levelData.list[e.detail.value]
+			this.form.memberLevel = this.levelSelData.level
+		},
+		// 表单验证
+		formSubmit(e) {
+			// 表单规则
+			let rules = [
+				{
+					name: 'mobile',
+					rule: ['required'],
+					msg: ['请输入手机号']
+				},
+				{
+					name: 'confirmMobile',
+					rule: ['required'],
+					msg: ['请输入手机号']
+				},
+				{
+					name: 'balance',
+					rule: ['required'],
+					msg: ['请输入余额']
+				},
+				{
+					name: 'memberLevel',
+					rule: ['required'],
+					msg: ['请选择会员级别']
+				},
+				{
+					name: 'confirmPassword',
+					rule: ['required'],
+					msg: ['请输入密码']
+				}
+			]
+			// 进行表单检查
+			let formData = e.detail.value
+			let checkRes = form.validation(formData, rules)
+			// 验证通过!
+			if (!checkRes) {
+				this.confirmFn()
+			} else {
+				this.$msg(checkRes)
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 528 - 0
store/src/admin-user/detail.vue

@@ -0,0 +1,528 @@
+<template>
+	<div class="app-content">
+		<!-- 客户信息 -->
+		<div class="module-com user-info">
+			<div class="user-wrap">
+				<app-avatar-module :src="data.avatarUrl" />
+				<div class="user-top-right">
+					<div>
+						<div class="flex-center">
+							<span class="app-size-32">{{ data.userName }}</span>
+							<app-vip-module class="level-img" v-if="data.member && data.member != 0" :text="`VIP${data.member}`" />
+						</div>
+						<div class="app-color-3">{{ data.id }}</div>
+					</div>
+					<div class="source-wrap">
+						<i v-if="data.source == 0" class="iconfont iconweixinlaiyuan"></i>
+						<i v-if="data.source == 1" class="iconfont iconzhifubao"></i>
+						<i class="iconfont iconweixingongzhonghao" :class="[data.subscribe? 'app-color-4' : '']"></i>
+						<i v-if="data.mobile" class="iconfont iconshoujihao1"></i>
+					</div>
+				</div>
+			</div>
+			<div class="user-bottom">
+				<div class="data-list" v-for="(item, index) in fundsData" :key="index">
+					<div class="app-size-30 app-bold">{{ item.value }}</div>
+					<div class="app-color-3">{{ item.name }}</div>
+				</div>
+			</div>
+		</div>
+		<!-- 客户按钮 -->
+		<div class="module-com tabs-wrap">
+			<div class="tabs-list" v-for="(item, index) in tabsData" :key="index" @click="pageTo(item)">
+				<div class="tabs-img">
+					<img :src="item.img" alt mode="widthFix" />
+				</div>
+				<div class="tabs-name">{{ item.name }}</div>
+			</div>
+		</div>
+		<!-- 备注 -->
+		<div class="module-com remark-wrap" v-if="!$util.isEmpty(data.remarkList)">
+			<div class="app-blod">备注</div>
+			<div class="list-wrap">
+				<div class="list-line" v-for="(item, index) in data.remarkList" :key="index">
+					<div>{{ item.remark }}</div>
+					<div @click="delRemarkFn(item)">
+						<i class="iconfont icondelete"></i>
+					</div>
+				</div>
+			</div>
+		</div>
+		<!-- 消费记录 -->
+		<div class="module-com remark-wrap" v-if="!$util.isEmpty(data.orderList)">
+			<div class="app-blod">消费记录</div>
+			<div class="list-wrap">
+				<block v-for="(item, index) in data.orderList" :key="index">
+					<div class="list-line" v-if="index < 3 || orderMoreStatus">
+						<div class="flex-center">
+							<div class="time">{{ item.createTime }}</div>
+							<div>{{ item.orderName }}</div>
+						</div>
+						<div class="price">¥{{ item.actPrice }}</div>
+					</div>
+				</block>
+			</div>
+			<div class="more-text" v-if="!orderMoreStatus" @click="orderMoreFn">更多 ></div>
+		</div>
+		<!-- 充值弹窗 -->
+		<modal-module :show="rechargeModal" @cancel="modalCancel" @click="rechargeModalClick" :maskClosable="false" title="充值" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap">
+					<div class="inp-list-line">
+						<div class="line-label">充值金额</div>
+						<div class="line-input">
+							<input type="text" v-model="rechargeForm.rechargeAmount" :adjust-position="false" class="inp-input" />
+							<div class="inp-prompt">元</div>
+						</div>
+					</div>
+					<div class="inp-list-line">
+						<div class="line-label">确认密码</div>
+						<div class="line-input">
+							<input type="text" v-model="rechargeForm.confirmPassword" :adjust-position="false" class="inp-input" />
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 修改密码弹窗 -->
+		<modal-module :show="passwordModal" @cancel="modalCancel" @click="passwordModalClick" :maskClosable="false" title="重置密码" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap">
+					<div class="inp-list-line">
+						<div class="line-label">重置密码</div>
+						<div class="line-input">
+							<input type="text" v-model="passwordForm.password" :adjust-position="false" class="inp-input" />
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 升级 -->
+		<modal-module :show="upgradeModal" @cancel="modalCancel" @click="upgradeModalClick" :maskClosable="false" title="升级" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap">
+					<div class="inp-list-line">
+						<div class="line-label">请选择等级</div>
+						<div class="line-input">
+							<picker mode="selector" :value="upgradeForm.member" :range="levelData.list" range-key="level" @change="changeLevelFn" class="inp-select">
+								<div v-if="upgradeForm.member">{{ levelSelData.level }}</div>
+								<div class="tui-placeholder" v-else>请选择</div>
+							</picker>
+						</div>
+					</div>
+					<div class="inp-list-line">
+						<div class="line-label">确认密码</div>
+						<div class="line-input">
+							<input type="text" v-model="upgradeForm.confirmPassword" class="inp-input" />
+						</div>
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 添加备注 -->
+		<modal-module :show="remarkModal" @cancel="modalCancel" @click="remarkModalClick" :maskClosable="false" title="添加备注" padding="30rpx 30rpx">
+			<template v-slot:content>
+				<div class="app-modal-input-wrap">
+					<div class="inp-list-line">
+						<textarea v-model="remarkForm.remark" placeholder-style="phcolor" placeholder="请填写备注内容,如客户喜好,消费情况等" />
+					</div>
+				</div>
+			</template>
+		</modal-module>
+		<!-- 删除备注弹窗 -->
+		<modal-module :show="promptRemarkModal" @cancel="modalCancel" @click="promptModalClick" :content="promptModalText" color="#333" :size="32" padding="30rpx 30rpx"></modal-module>
+	</div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import AppVipModule from '@/components/module/app-vip'
+import AppAvatarModule from '@/components/module/app-avatar'
+import ModalModule from '@/components/plugin/modal'
+// api
+import { getLevel } from '@/utils/config'
+import { getUserDet, remarkAdd, remarkDel, upgrade, rechargeB, resetPassword } from '@/api/member'
+export default {
+	name: 'member-detail',
+	components: {
+		AppVipModule,
+		AppAvatarModule,
+		ModalModule
+	},
+	props: {},
+	data() {
+		return {
+			constant: this.$constant,
+			// data
+			data: {},
+			// modal
+			rechargeModal: false,
+			passwordModal: false,
+			upgradeModal: false,
+			remarkModal: false,
+			// 用户资金情况
+			fundsData: [
+				{
+					name: '消费次数',
+					value: 0
+				},
+				{
+					name: '累计消费(¥)',
+					value: 0
+				},
+				{
+					name: '成长值',
+					value: 0
+				},
+				{
+					name: '余额',
+					value: 0
+				}
+			],
+			// tab按钮
+			tabsData: [
+				{
+					name: '优惠券',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-1.png`,
+					funtion: () => {
+						this.$msg('功能开发中...')
+					}
+				},
+				{
+					name: '老带新',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-2.png`,
+					funtion: () => {
+						this.$msg('功能开发中...')
+					}
+				},
+				{
+					name: '消费登记',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-3.png`,
+					funtion: () => {
+						this.$msg('功能开发中...')
+					}
+				},
+				{
+					name: '备注',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-4.png`,
+					funtion: () => {
+						this.remarkModal = true
+					}
+				},
+				{
+					name: '充值',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-5.png`,
+					funtion: () => {
+						this.rechargeModal = true
+					}
+				},
+				{
+					name: '重置密码',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-6.png`,
+					funtion: () => {
+						this.passwordModal = true
+					}
+				},
+				{
+					name: '升级',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-7.png`,
+					funtion: () => {
+						this.upgradeModal = true
+					}
+				},
+				{
+					name: '发消息',
+					img: `${this.$constant.imgUrl}/retail/member/tab-icon-8.png`,
+					url: '/pages/chat/index'
+				}
+			],
+			// 重置密码
+			passwordForm: {
+				password: ''
+			},
+			// 充值
+			rechargeForm: {
+				rechargeAmount: 0,
+				confirmPassword: ''
+			},
+			// 升级
+			levelSelData: {},
+			upgradeForm: {
+				member: '',
+				confirmPassword: ''
+			},
+			// 备注
+			remarkForm: {
+				remark: ''
+			},
+			remarkOperateData: {},
+			// 订单
+			orderMoreStatus: false,
+			// 确认操作提示
+			promptRemarkModal: false,
+			promptModalText: '是否要删除该备注?'
+		}
+	},
+	computed: {
+		...mapGetters({ levelData: 'getLevel' })
+	},
+	onLoad() {
+		// this.init()
+	},
+	methods: {
+		init() {
+			this._getUserDet()
+			getLevel()
+		},
+		// api
+		_getUserDet() {
+			getUserDet({ userId: this.option.id }).then(res => {
+				if (this.$util.isEmpty(res.data)) return false
+				this.data = res.data
+				this.fundsData[0].value = res.data.userAsset.totalBuyNum
+				this.fundsData[1].value = res.data.userAsset.totalExpend
+				this.fundsData[2].value = res.data.userAsset.growth
+				this.fundsData[3].value = res.data.userAsset.balance
+			})
+		},
+		_rechargeB() {
+			rechargeB({
+				userId: this.data.id,
+				...this.rechargeForm
+			}).then(res => {
+				this._getUserDet()
+				this.$msg('充值成功!')
+				this.modalCancel()
+			})
+		},
+		_upgrade() {
+			upgrade({
+				userId: this.data.id,
+				...this.upgradeForm
+			}).then(res => {
+				this.$msg('升级成功!')
+				this.modalCancel()
+			})
+		},
+		_resetPassword() {
+			resetPassword({
+				userId: this.data.id,
+				...this.passwordForm
+			}).then(res => {
+				this.$msg('重置成功!')
+				this.modalCancel()
+			})
+		},
+		_remarkAdd() {
+			remarkAdd({
+				userId: this.data.id,
+				...this.remarkForm
+			}).then(res => {
+				this.$msg('添加成功!')
+				this.modalCancel()
+				this._getUserDet()
+			})
+		},
+		_delRemark() {
+			remarkDel({ id: this.remarkOperateData.id }).then(res => {
+				this.$msg('删除成功!')
+				this.modalCancel()
+				this._getUserDet()
+			})
+		},
+		// operate ===========================
+		orderMoreFn() {
+			this.orderMoreStatus = false
+		},
+		delRemarkFn(item) {
+			this.remarkOperateData = item
+			this.promptModalText = '是否要删除该备注?'
+			this.promptRemarkModal = true
+		},
+		// 弹窗按钮
+		changeLevelFn(e) {
+			this.levelSelData = this.levelData.list[e.detail.value]
+			this.upgradeForm.member = this.levelSelData.level
+		},
+		passwordModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				this.modalCancel()
+				this.promptModalText = '确认重置密码?'
+				this.promptRemarkModal = true
+			}
+		},
+		upgradeModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				this.modalCancel()
+				this.promptModalText = '确认升级?'
+				this.promptRemarkModal = true
+			}
+		},
+		rechargeModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				this.modalCancel()
+				this.promptModalText = '确认充值?'
+				this.promptRemarkModal = true
+			}
+		},
+		remarkModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				this._remarkAdd()
+			}
+		},
+		promptModalClick(e) {
+			if (e.index === 0) {
+				this.modalCancel()
+			} else {
+				if (this.promptModalText == '是否要删除该备注?') {
+					this._delRemark()
+				}
+				if (this.promptModalText == '确认升级?') {
+					this._upgrade()
+				}
+				if (this.promptModalText == '确认充值?') {
+					this._rechargeB()
+				}
+				if (this.promptModalText == '确认重置密码?') {
+					this._resetPassword()
+				}
+			}
+		},
+		modalCancel() {
+			this.rechargeModal = false
+			this.passwordModal = false
+			this.upgradeModal = false
+			this.remarkModal = false
+			this.promptRemarkModal = false
+		}
+	}
+}
+</script>
+
+<style lang='scss' scoped>
+	.app-content {
+		background-image: url('../../static/images/member/bg.png');
+		background-size: 100% 330px;
+		background-repeat: no-repeat;
+		padding-top: 30px;
+		padding-bottom: 30px;
+	}
+	// 公共
+	.module-com {
+		margin: 0 30px 20px;
+		padding: 20px;
+		background-color: #fff;
+		box-shadow: 0px 6px 16px #ddd;
+		border-radius: 10px;
+	}
+	// 用户信息
+	.user-info {
+		padding: 40px 30px 50px;
+		.user-wrap {
+			@include disFlex(center, space-between);
+			margin-bottom: 60px;
+			.user-top-right {
+				@include disFlex(flex-start, space-between);
+				width: calc(100% - 120px);
+				.flex-center {
+					margin-bottom: 14px;
+					.level-img {
+						margin-left: 10px;
+						width: 80px;
+						/deep/.vip-text {
+							top: -2px;
+							left: 26px;
+							font-weight: 400;
+							transform: scale(0.7);
+						}
+					}
+				}
+				.source-wrap {
+					.iconfont {
+						margin-left: 10px;
+					}
+					.iconweixinlaiyuan {
+						color: #35b801;
+					}
+					.iconzhifubao {
+						color: #00aaed;
+					}
+					.iconshoujihao1 {
+						color: #fc2e47;
+					}
+				}
+			}
+		}
+		.user-bottom {
+			width: 100%;
+			@include disFlex(center, space-between);
+			.data-list {
+				text-align: center;
+				.app-size-30 {
+					margin-bottom: 14px;
+				}
+			}
+		}
+	}
+	// tabs
+	.tabs-wrap {
+		padding: 40px 10px;
+		@include disFlex(center, center);
+		flex-wrap: wrap;
+		.tabs-list {
+			width: 25%;
+			margin-bottom: 50px;
+			text-align: center;
+			.tabs-img {
+				width: 50px;
+				height: 50px;
+				margin: 0 auto 14px;
+				img {
+					height: 100%;
+				}
+			}
+			.tabs-name {
+				color: $fontColor2;
+			}
+			&:nth-child(n + 5) {
+				margin-bottom: 0;
+			}
+		}
+	}
+	// 备注
+	.remark-wrap {
+		.list-wrap {
+			margin-top: 24px;
+			.list-line {
+				@include disFlex(center, space-between);
+				margin-top: 10px;
+				padding: 16px 20px;
+				background-color: #f7f7f8;
+				color: $fontColor2;
+				border-radius: 4px;
+				.iconfont {
+					color: $fontColor3;
+				}
+				.time {
+					margin-right: 70px;
+				}
+				.price {
+					color: #333;
+				}
+			}
+		}
+		.more-text {
+			margin-top: 24px;
+			text-align: center;
+			color: $fontColor3;
+		}
+	}
+</style>