index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. <template>
  2. <base-page>
  3. <view class="uni-flex uni-row height-all">
  4. <view class="common-wrap uni-flex uni-column" style="-webkit-flex: 1;flex: 1;">
  5. <view class="common-tab-wrap" id="tab">
  6. <view class="tab-item" :class="{ 'active-bar': active == 0 }" @click="switchTab(0)"><text class="text">预约看板</text></view>
  7. <view class="tab-item" :class="{ 'active-bar': active == 1 }" @click="switchTab(1)"><text class="text">预约列表</text></view>
  8. <view class="active" :style="activeStyle"></view>
  9. </view>
  10. <swiper :interval="3000" :duration="300" :current="active" @change="swiperChange">
  11. <!-- 预约看板 -->
  12. <swiper-item>
  13. <view class="swiper-item common-scrollbar">
  14. <view class="uni-flex panel-head">
  15. <button type="default" class="primary-btn" @click="addYuyue()">添加预约</button>
  16. <view class="status uni-flex">
  17. <block v-for="(item, index) in status" :key="index">
  18. <view class="color" :class="item.state"></view>
  19. <view>{{ item.name }}</view>
  20. </block>
  21. </view>
  22. </view>
  23. <view class="panel-body">
  24. <view class="head-time uni-flex">
  25. <view @click="prevWeek()" class="item"><view class="iconfont iconqianhou1"></view></view>
  26. <view class="time-box">{{ weekDate.start }} - {{ weekDate.end }}</view>
  27. <view @click="nextWeek()" class="item"><view class="iconfont iconqianhou2"></view></view>
  28. <!-- <view class="head-time-switch">
  29. <view :class="yuYueDateType == 'week' ? 'active' : ''" @click="yuYueDateType = 'week'">周</view>
  30. <view :class="yuYueDateType == 'month' ? 'active' : ''" @click="yuYueDateType = 'month'">月</view>
  31. </view> -->
  32. </view>
  33. <block v-if="yuYueDateType == 'week'">
  34. <view class="head uni-flex">
  35. <view v-for="(item, index) in weeks" class="item" :key="index">
  36. <button type="default" class="default-btn" :class="{ active: item.currday }">
  37. {{ item.week }}
  38. <text>{{ item.date }}</text>
  39. </button>
  40. </view>
  41. </view>
  42. <view class="body uni-flex">
  43. <scroll-view scroll-y="true" @scrolltolower="getReserve(index)" class="common-scrollbar item" v-for="(item, index) in weeks" :key="index">
  44. <block v-if="item.data">
  45. <view
  46. class="panel-item"
  47. :class="reserve_item.reserve_state"
  48. v-for="(reserve_item, reserve_index) in item.data.list"
  49. :key="reserve_index"
  50. >
  51. <view class="username">{{ reserve_item.nickname }}</view>
  52. <view class="time" :class="reserve_item.reserve_state">{{ $util.timeFormat(reserve_item.reserve_time, 'm-d h:i') }}</view>
  53. <view
  54. class="service"
  55. v-for="(server_item, server_index) in reserve_item.item"
  56. :key="server_index"
  57. @click="yuyueEvent('info', reserve_item)"
  58. >
  59. {{ server_item.goods_name }}
  60. </view>
  61. <uni-dropdown>
  62. <view class="action" slot="dropdown-link"><text class="iconfont icongengduo"></text></view>
  63. <view slot="dropdown">
  64. <view class="dropdown-menu">
  65. <view class="menu-item" @click="yuyueEvent('info', reserve_item)">详情</view>
  66. <view
  67. class="menu-item"
  68. v-for="(menu_item, menu_index) in operation[reserve_item.reserve_state]"
  69. :key="menu_index"
  70. @click="yuyueEvent(menu_item.event, reserve_item)"
  71. >
  72. {{ menu_item.title }}
  73. </view>
  74. <view class="arrow"></view>
  75. </view>
  76. </view>
  77. </uni-dropdown>
  78. </view>
  79. <view style="height: 1.5rem;"></view>
  80. </block>
  81. </scroll-view>
  82. </view>
  83. </block>
  84. <block v-if="yuYueDateType == 'month'">
  85. <view class="head uni-flex">
  86. <view v-for="(item, index) in week" class="item" :key="index">
  87. <button type="default" class="default-btn">{{ item }}</button>
  88. </view>
  89. </view>
  90. </block>
  91. </view>
  92. </view>
  93. </swiper-item>
  94. <!-- 预约列表 -->
  95. <swiper-item>
  96. <view class="yuyuelist">
  97. <view class="yuyuelist-box">
  98. <view class="yuyuelist-left">
  99. <view class="yuyue-title">预约客户</view>
  100. <view class="yuyue-search">
  101. <view class="search">
  102. <text class="iconfont icon31sousuo" @click="searchYuyueList()"></text>
  103. <input type="text" v-model="yuyueSearchText" placeholder="请输入会员手机号" />
  104. </view>
  105. </view>
  106. <scroll-view @scrolltolower="getYuyueList()" scroll-y="true" class="yuyue-list-scroll all-scroll">
  107. <view
  108. class="item"
  109. v-for="(item, index) in yuyueList"
  110. :key="index"
  111. @click="selectYuyue(item.reserve_id)"
  112. :class="{ active: item.reserve_id == reserveId }"
  113. >
  114. <view class="item-head">
  115. <image mode="aspectFill" v-if="item.headimg" :src="$util.img(item.headimg)" @error="item.headimg = defaultImg.head"></image>
  116. <image mode="aspectFill" v-else :src="$util.img(defaultImg.head)"></image>
  117. <view class="item-right">
  118. <view class="yuyue-name" v-if="item.nickname">{{ item.nickname }}</view>
  119. <view class="yuyue-desc">{{ item.mobile }}</view>
  120. </view>
  121. <text>{{ item.reserve_state_name }}</text>
  122. </view>
  123. <view class="item-common">预约时间:{{ $util.timeFormat(item.create_time) }}</view>
  124. <view class="item-common yuyue-project">
  125. 预约项目:
  126. <block v-for="(sItem, sIndex) in item.item" :key="sIndex">
  127. {{ sItem.goods_name }}{{ sIndex != item.item.length - 1 ? ';' : '' }}
  128. </block>
  129. </view>
  130. </view>
  131. <view v-if="yuyueList.length == 0" class="empty">
  132. <image :src="$util.img('upload/cashier/member-empty.png')" mode="widthFix"></image>
  133. <view class="tips">暂无预约客户</view>
  134. </view>
  135. </scroll-view>
  136. </view>
  137. <view class="yuyuelist-right" v-if="yuyueInfo">
  138. <view class="yuyue-title">预约详情</view>
  139. <view class="yuyue-information common-scrollbar">
  140. <view class="title">预约信息</view>
  141. <view class="information-box">
  142. <view class="box-left">
  143. <view class="information">
  144. <view>预约客户:</view>
  145. <view>{{ yuyueInfo.nickname }}</view>
  146. </view>
  147. <view class="information">
  148. <view>客户手机号:</view>
  149. <view>{{ yuyueInfo.mobile }}</view>
  150. </view>
  151. <view class="information">
  152. <view>预约门店:</view>
  153. <view>{{ yuyueInfo.store_name }}</view>
  154. </view>
  155. <view class="information">
  156. <view>预约状态:</view>
  157. <view>{{ yuyueInfo.reserve_state_name }}</view>
  158. </view>
  159. <view class="information">
  160. <view>预约到店时间:</view>
  161. <view>{{ $util.timeFormat(yuyueInfo.reserve_time, 'y-m-d h:i') }}</view>
  162. </view>
  163. <view class="information">
  164. <view>预约时间:</view>
  165. <view>{{ $util.timeFormat(yuyueInfo.create_time) }}</view>
  166. </view>
  167. <view class="information">
  168. <view>备注:</view>
  169. <view>{{ yuyueInfo.desc ? yuyueInfo.desc : '--' }}</view>
  170. </view>
  171. </view>
  172. </view>
  173. <view class="title title2">预约内容</view>
  174. <view class="table" v-if="yuyueInfo">
  175. <view class="table-th table-all">
  176. <view class="table-td" style="width:50%">项目</view>
  177. <view class="table-td" style="width:50%">员工</view>
  178. </view>
  179. <scroll-view class="table-tb" scroll-y="true">
  180. <view class="table-tr table-all" v-for="(item, index) in yuyueInfo.item" :key="index">
  181. <view class="table-td" style="width:50%">{{ item.goods_name }}</view>
  182. <view class="table-td" style="width:50%">{{ item.uid ? item.username : '--' }}</view>
  183. </view>
  184. </scroll-view>
  185. </view>
  186. <view class="button-box" v-if="yuyueInfo && operation[yuyueInfo.reserve_state]">
  187. <button
  188. class="button"
  189. v-for="(menu_item, menu_index) in operation[yuyueInfo.reserve_state]"
  190. :key="menu_index"
  191. @click="yuyueEvent(menu_item.event, yuyueInfo)"
  192. >
  193. {{ menu_item.title }}
  194. </button>
  195. </view>
  196. </view>
  197. </view>
  198. <view class="yuyuelist-right empty" v-else>
  199. <image :src="$util.img('upload/uniapp/cashier/cart_empty.png')" mode="widthFix"></image>
  200. <view class="tips">暂无预约信息</view>
  201. </view>
  202. </view>
  203. </view>
  204. </swiper-item>
  205. </swiper>
  206. </view>
  207. </view>
  208. <!-- 添加/修改预约 -->
  209. <uni-popup ref="addYuyuePop" :maskClick="false">
  210. <view class="pop-box">
  211. <view class="pop-header">
  212. <view class="pop-header-text">{{ yuYueData.reserve_id ? '修改' : '添加' }}预约</view>
  213. <view class="pop-header-close" @click="closeYuyuePop"><i class="iconguanbi1 iconfont"></i></view>
  214. </view>
  215. <scroll-view scroll-y="true" class="common-scrollbar pop-content">
  216. <view class="form-content">
  217. <view class="form-item" v-if="!yuYueData.reserve_id">
  218. <view class="form-label">
  219. <text class="required">*</text>
  220. 手机号:
  221. </view>
  222. <view class="form-inline search-wrap">
  223. <input type="number" class="form-input" v-model="searchMobile" placeholder="请输入客户手机号" />
  224. <i class="iconfont icon31sousuo" @click="searchMember"></i>
  225. </view>
  226. </view>
  227. <view class="form-item">
  228. <view class="form-label">
  229. <text class="required">*</text>
  230. 客户:
  231. </view>
  232. <view class="form-inline">
  233. <view class="member-info" v-if="yuYueData.member_id">
  234. <image :src="$util.img(yuYueData.member.headimg, { size: 'small' })" mode="widthFix" />
  235. <view class="info">
  236. <view class="name">{{ yuYueData.member.nickname }}</view>
  237. <view>
  238. <text>手机号:{{ yuYueData.member.mobile }}</text>
  239. </view>
  240. </view>
  241. </view>
  242. </view>
  243. </view>
  244. <view class="form-item">
  245. <view class="form-label">
  246. <text class="required">*</text>
  247. 到店时间:
  248. </view>
  249. <view class="form-inline">
  250. <uni-datetime-picker :start="toDay" v-model="yuYueData.date" type="date" :clearIcon="false" @change="changeYuyueTime" />
  251. </view>
  252. <view class="form-inline">
  253. <select-lay
  254. :zindex="10"
  255. :value="yuYueData.time"
  256. name="names"
  257. placeholder="请选择到店时间"
  258. :options="yuYueTime"
  259. @selectitem="selectYuYueTime"
  260. ></select-lay>
  261. </view>
  262. </view>
  263. <view class="form-item">
  264. <view class="form-label">
  265. <text class="required">*</text>
  266. 预约门店:
  267. </view>
  268. <view class="form-inline">{{ storeInfo ? storeInfo.store_name : '--' }}</view>
  269. </view>
  270. <view class="form-item">
  271. <view class="form-label">
  272. <text class="required">*</text>
  273. 项目:
  274. </view>
  275. <view>
  276. <view class="table">
  277. <view class="table-tr table-head">
  278. <view class="table-th">预约项目</view>
  279. <view class="table-th">员工</view>
  280. <view class="table-th">操作</view>
  281. </view>
  282. <view class="table-content table-tr" v-for="(goods_item, goods_index) in yuYueData.goods" :key="goods_index">
  283. <view class="table-td">
  284. <uni-dropdown>
  285. <view class="action" slot="dropdown-link">
  286. <view class="service-item">
  287. <view class="info" v-if="goods_item.goods_id">
  288. <view class="title">{{ goods_item.goods_name }}</view>
  289. <view class="desc">项目时长:{{ goods_item.service_length }}分钟 ¥{{ goods_item.price }}</view>
  290. </view>
  291. <view class="info" v-else>请选择项目</view>
  292. <i class="iconfont iconsanjiao_xia"></i>
  293. </view>
  294. </view>
  295. <view slot="dropdown">
  296. <view class="dropdown-content-box">
  297. <view class="select-service">
  298. <div class="service-wrap">
  299. <div class="flex-wrap">
  300. <div class="item" v-for="(item, index) in goodsList" :key="index" @click="selectGoods(item, goods_index)">
  301. <div class="title">{{ item.goods_name }}</div>
  302. <div class="desc">项目时长:{{ item.service_length }}分钟 ¥{{ item.price }}</div>
  303. </div>
  304. </div>
  305. </div>
  306. </view>
  307. <view class="arrow"></view>
  308. </view>
  309. </view>
  310. </uni-dropdown>
  311. </view>
  312. <view class="table-td">
  313. <uni-dropdown>
  314. <view class="action" slot="dropdown-link">
  315. <view class="service-item" @click="loadServicer(goods_index)">
  316. <view class="info">
  317. <view class="title" v-if="goods_item.uid && goods_item.uid > 0">{{ goods_item.username }}</view>
  318. <view class="title" v-else>不选择员工</view>
  319. </view>
  320. <i class="iconfont iconsanjiao_xia"></i>
  321. </view>
  322. </view>
  323. <view slot="dropdown">
  324. <view class="dropdown-content-box">
  325. <div class="select-servicer">
  326. <div class="select-item">
  327. <div class="title" @click="selectServicer({ uid: 0, username: '' }, goods_index)">不选择员工</div>
  328. </div>
  329. <div class="select-item" v-for="(item, index) in servicerList" :key="index" @click="selectServicer(item, goods_index)">
  330. <div class="title">{{ item.username }}</div>
  331. </div>
  332. </div>
  333. <view class="arrow"></view>
  334. </view>
  335. </view>
  336. </uni-dropdown>
  337. </view>
  338. <view class="table-td"><view class="action-btn" @click="deleleService(goods_index)">删除</view></view>
  339. </view>
  340. </view>
  341. <button class="primary-btn select-btn" @click="addService">添加项目</button>
  342. </view>
  343. </view>
  344. <view class="form-item">
  345. <view class="form-label">
  346. <text class="required"></text>
  347. 备注:
  348. </view>
  349. <view class="form-inline"><textarea class="form-textarea" v-model="yuYueData.desc"></textarea></view>
  350. </view>
  351. </view>
  352. </scroll-view>
  353. <view class="pop-bottom"><button class="primary-btn" @click="yuYueSubmit">确定</button></view>
  354. </view>
  355. </uni-popup>
  356. <!-- 预约详情 -->
  357. <uni-popup ref="yuyuePop">
  358. <view class="pop-box yuyue-info">
  359. <view class="pop-header">
  360. <view class="pop-header-text">预约详情</view>
  361. <view class="pop-header-close" @click="$refs.yuyuePop.close()"><i class="iconguanbi1 iconfont"></i></view>
  362. </view>
  363. <scroll-view scroll-y="true" class="common-scrollbar pop-content">
  364. <view class="yuyue-pop form-content" v-if="yuYueDetail">
  365. <view class="form-item">
  366. <view class="form-label">预约客户:</view>
  367. <view class="form-inline search-wrap">
  368. <text>{{ yuYueDetail.member.nickname }}</text>
  369. </view>
  370. </view>
  371. <view class="form-item">
  372. <view class="form-label">客户手机号:</view>
  373. <view class="form-inline search-wrap">
  374. <text>{{ yuYueDetail.member.mobile }}</text>
  375. </view>
  376. </view>
  377. <view class="form-item">
  378. <view class="form-label">预约门店:</view>
  379. <view class="form-inline search-wrap">{{ yuYueDetail.store_name }}</view>
  380. </view>
  381. <view class="form-item">
  382. <view class="form-label">预约状态:</view>
  383. <view class="form-inline search-wrap">{{ yuYueDetail.reserve_state_name }}</view>
  384. </view>
  385. <view class="form-item">
  386. <view class="form-label">预约到店时间:</view>
  387. <view class="form-inline search-wrap">{{ $util.timeFormat(yuYueDetail.reserve_time, 'y-m-d h:i') }}</view>
  388. </view>
  389. <view class="form-item">
  390. <view class="form-label">创建时间:</view>
  391. <view class="form-inline search-wrap">{{ $util.timeFormat(yuYueDetail.create_time, 'y-m-d h:i:s') }}</view>
  392. </view>
  393. <view class="form-item">
  394. <view class="form-label">预约项目:</view>
  395. <scroll-view scroll-y="true" class="form-inline search-wrap make-server">
  396. <view class="table-container">
  397. <view class="thead">
  398. <view class="th">
  399. <view class="content">项目</view>
  400. <view class="content">员工</view>
  401. <view class="content">时长</view>
  402. </view>
  403. </view>
  404. <view class="tbody">
  405. <view class="tr" v-for="(item, index) in yuYueDetail.item" :key="index">
  406. <view class="td">
  407. <view class="content">{{ item.goods_name }}</view>
  408. <view class="content">{{ item.username ? item.username : '--' }}</view>
  409. <view class="content">{{ item.service_length }}分钟</view>
  410. </view>
  411. </view>
  412. </view>
  413. </view>
  414. </scroll-view>
  415. </view>
  416. <view class="form-item">
  417. <view class="form-label">备注:</view>
  418. <view class="form-inline search-wrap">{{ yuYueDetail.remark ? yuYueDetail.remark : '--' }}</view>
  419. </view>
  420. </view>
  421. </scroll-view>
  422. <view class="pop-bottom"><button class="primary-btn" @click="$refs.yuyuePop.close()">确定</button></view>
  423. </view>
  424. </uni-popup>
  425. <nc-loading :layer-background="{ background: 'rgba(255,255,255,.6)' }" :default-show="false" ref="loading"></nc-loading>
  426. <!-- #ifdef APP-PLUS -->
  427. <nc-update></nc-update>
  428. <!-- #endif -->
  429. </base-page>
  430. </template>
  431. <script>
  432. import uniDatetimePicker from '@/components/uni-datetime-picker/uni-datetime-picker.vue';
  433. import selectLay from '@/components/select-lay/select-lay.vue';
  434. import index from './public/js/index.js';
  435. export default {
  436. components: {
  437. uniDatetimePicker,
  438. selectLay
  439. },
  440. mixins: [index]
  441. };
  442. </script>
  443. <style scoped>
  444. .table-content >>> .tr .td .content.action {
  445. overflow: unset;
  446. }
  447. .form-inline >>> .uni-icons {
  448. height: 0.3rem;
  449. }
  450. </style>
  451. <style lang="scss" scoped>
  452. @import './public/css/index.scss';
  453. </style>