| @ -0,0 +1,14 @@ | |||
| # 默认忽略的文件 | |||
| /shelf/ | |||
| /workspace.xml | |||
| # 基于编辑器的 HTTP 客户端请求 | |||
| /httpRequests/ | |||
| # Datasource local storage ignored files | |||
| /dataSources/ | |||
| /dataSources.local.xml | |||
| .idea | |||
| package-lock.json | |||
| node_modules/ | |||
| unpackage/ | |||
| .hbuilderx | |||
| .vite | |||
| @ -0,0 +1,23 @@ | |||
| <script> | |||
| export default { | |||
| onLaunch: function() { | |||
| }, | |||
| onShow: function() { | |||
| // this.$store.commit('initConfig') | |||
| }, | |||
| onHide: function() { | |||
| } | |||
| } | |||
| </script> | |||
| <style> | |||
| @import url("common.scss"); | |||
| /*每个页面公共css */ | |||
| body{ | |||
| background-color: #f7f7f7; | |||
| font-size: 30rpx; | |||
| } | |||
| .page{ | |||
| padding-top: var(--window-top); | |||
| } | |||
| </style> | |||
| @ -0,0 +1,36 @@ | |||
| # uniapp项目开发模板 | |||
| #### Description | |||
| {**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} | |||
| #### Software Architecture | |||
| Software architecture description | |||
| #### Installation | |||
| 1. xxxx | |||
| 2. xxxx | |||
| 3. xxxx | |||
| #### Instructions | |||
| 1. xxxx | |||
| 2. xxxx | |||
| 3. xxxx | |||
| #### Contribution | |||
| 1. Fork the repository | |||
| 2. Create Feat_xxx branch | |||
| 3. Commit your code | |||
| 4. Create Pull Request | |||
| #### Gitee Feature | |||
| 1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md | |||
| 2. Gitee blog [blog.gitee.com](https://blog.gitee.com) | |||
| 3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) | |||
| 4. The most valuable open source project [GVP](https://gitee.com/gvp) | |||
| 5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) | |||
| 6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) | |||
| @ -0,0 +1,411 @@ | |||
| # 商城项目文档 | |||
| ## 项目概述 | |||
| 本项目是一个基于uni-app开发的商城小程序,采用Vue框架开发,集成了完整的商城功能模块。 | |||
| ## 目录结构 | |||
| ``` | |||
| ├── api # API接口目录 | |||
| │ ├── api.js # API统一出口 | |||
| │ ├── http.js # HTTP请求封装 | |||
| │ └── model # 业务模块API | |||
| ├── components # 公共组件 | |||
| ├── mixins # 混入文件 | |||
| ├── pages # 页面文件 | |||
| ├── static # 静态资源 | |||
| ├── store # Vuex状态管理 | |||
| ├── utils # 工具函数 | |||
| └── uni_modules # uni-app插件模块 | |||
| ``` | |||
| ## 分包结构说明 | |||
| ### pages_order分包 | |||
| 分包是小程序优化加载性能的重要手段,pages_order作为独立分包,包含以下模块: | |||
| ``` | |||
| ├── auth # 认证相关页面 | |||
| │ ├── loginAndRegisterAndForgetPassword.vue # 登录注册 | |||
| │ ├── wxLogin.vue # 微信登录 | |||
| │ └── wxUserInfo.vue # 微信用户信息 | |||
| ├── components # 分包内公共组件 | |||
| │ ├── address/ # 地址选择组件 | |||
| │ ├── areaSelector/ # 区域选择器 | |||
| │ └── product/ # 商品相关组件 | |||
| ├── home # 首页相关 | |||
| │ ├── addEnterprise.vue # 添加企业 | |||
| │ ├── contact.vue # 联系我们 | |||
| │ ├── introduce.vue # 介绍页面 | |||
| │ ├── journalism.vue # 新闻资讯 | |||
| │ └── notice.vue # 公告 | |||
| ├── mine # 我的模块 | |||
| │ ├── address.vue # 收货地址 | |||
| │ ├── balance.vue # 余额 | |||
| │ ├── commission.vue # 佣金 | |||
| │ ├── coupon.vue # 优惠券 | |||
| │ ├── memberCenter.vue # 会员中心 | |||
| │ └── more... # 更多功能页面 | |||
| ├── order # 订单模块 | |||
| │ ├── createOrder.vue # 创建订单 | |||
| │ ├── orderDetail.vue # 订单详情 | |||
| │ └── giftList.vue # 礼品列表 | |||
| ├── product # 商品模块 | |||
| │ └── productDetail.vue # 商品详情 | |||
| └── static # 分包静态资源 | |||
| ├── address/ # 地址相关图片 | |||
| ├── auth/ # 认证相关图片 | |||
| ├── coupon/ # 优惠券图片 | |||
| └── more... # 其他静态资源 | |||
| ``` | |||
| **分包特点:** | |||
| - 静态资源就近原则:分包相关的图片等静态资源存放在分包目录下,避免主包体积过大 | |||
| - 模块化组织:按功能模块划分目录,便于维护和管理 | |||
| - 组件复用:分包内的通用组件集中管理,提高代码复用性 | |||
| ## 配置文件说明 | |||
| ### config.js | |||
| 项目核心配置文件,包含以下配置: | |||
| **1. 环境配置** | |||
| ```javascript | |||
| // 当前环境 | |||
| const type = 'prod' | |||
| // 环境配置 | |||
| const config = { | |||
| dev: { | |||
| baseUrl: 'http://h5.xzaiyp.top/jewelry-admin', | |||
| }, | |||
| prod: { | |||
| baseUrl: 'https://jewelry-admin.hhlm1688.com/jewelry-admin', | |||
| } | |||
| } | |||
| ``` | |||
| **2. 默认配置** | |||
| ```javascript | |||
| const defaultConfig = { | |||
| // 腾讯地图Key | |||
| mapKey: 'XMBBZ-BCPCV-SXPPQ-5Y7MY-PHZXK-YFFVU', | |||
| // 阿里云OSS配置 | |||
| aliOss: { | |||
| url: 'https://image.hhlm1688.com/', | |||
| config: { | |||
| region: 'oss-cn-guangzhou', | |||
| accessKeyId: '***', | |||
| accessKeySecret: '***', | |||
| bucket: 'hanhaiimage', | |||
| endpoint: 'oss-cn-shenzhen.aliyuncs.com', | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| **3. UI框架配置** | |||
| ```javascript | |||
| uni.$uv.setConfig({ | |||
| config: { | |||
| unit: 'rpx' // 设置默认单位 | |||
| }, | |||
| }) | |||
| // UI文档地址 https://www.uvui.cn/ | |||
| ``` | |||
| ## 核心模块详解 | |||
| ### 1. Mixins 混入 | |||
| #### 1.1 list.js - 列表数据加载混入 | |||
| 提供列表数据的加载、分页、下拉刷新、上拉加载更多等功能。 | |||
| **主要功能:** | |||
| - 统一的分页参数处理 | |||
| - 下拉刷新和上拉加载更多 | |||
| - 数据加载状态管理 | |||
| **使用示例:** | |||
| ```javascript | |||
| // 在页面中使用list混入 | |||
| import listMixin from '@/mixins/list.js' | |||
| export default { | |||
| mixins: [listMixin], | |||
| data() { | |||
| return { | |||
| // 指定API接口 | |||
| mixinsListApi: 'productList' | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| #### 1.2 configList.js - 全局配置混入 | |||
| 已全局引入的配置管理混入,无需手动引入即可使用。 | |||
| **主要功能:** | |||
| - 统一的分享配置 | |||
| - 全局配置管理 | |||
| - 用户信息关联 | |||
| **配置参数:** | |||
| ```javascript | |||
| // 分享配置示例 | |||
| this.Gshare.title = '分享标题' | |||
| this.Gshare.path = '分享路径' | |||
| ``` | |||
| ### 2. API 模块 | |||
| #### 2.1 http.js - 请求封装 | |||
| 统一的HTTP请求处理,包含: | |||
| - 请求拦截器 | |||
| - 响应拦截器 | |||
| - 统一的错误处理 | |||
| - Token管理 | |||
| #### 2.2 api.js - 接口管理 | |||
| 统一管理API接口,支持模块化组织。API模块采用分层结构,便于维护和扩展。 | |||
| **目录结构:** | |||
| ``` | |||
| api/ | |||
| ├── api.js # API统一出口 | |||
| ├── http.js # HTTP请求封装 | |||
| └── model/ # 业务模块API | |||
| ├── product.js # 商品相关接口 | |||
| ├── order.js # 订单相关接口 | |||
| └── user.js # 用户相关接口 | |||
| ``` | |||
| **接口定义示例:** | |||
| ```javascript | |||
| // api/model/product.js | |||
| export default { | |||
| // GET请求示例 | |||
| list: { | |||
| url: '/api/product/list', | |||
| method: 'GET', | |||
| loading: true // 显示加载提示 | |||
| }, | |||
| // POST请求示例 | |||
| create: { | |||
| url: '/api/product/create', | |||
| method: 'POST', | |||
| loading: true // 显示加载提示 | |||
| auth : true,//效验登录 | |||
| debounce : 1000,//接口防抖,1s | |||
| limit : 500,//接口限流,0.5s | |||
| }, | |||
| } | |||
| ``` | |||
| **调用接口示例:** | |||
| ```javascript | |||
| // 第一种写法:callback方式处理响应 | |||
| this.$api('product.list', { | |||
| pageNo: 1, | |||
| pageSize: 10, | |||
| categoryId: '123' | |||
| }, res => { | |||
| // 处理列表数据 | |||
| }) | |||
| // 第二种写法:Promise方式处理响应 | |||
| this.$api('product.create', { | |||
| name: '商品名称', | |||
| price: 99.99, | |||
| description: '商品描述' | |||
| }).then(res => { | |||
| if (res.code === 200) { | |||
| // 创建成功 | |||
| uni.showToast({ title: '创建成功' }) | |||
| } | |||
| }) | |||
| ``` | |||
| ### 3. 公共代码 | |||
| #### 3.1 工具函数 (utils) | |||
| - authorize.js: 授权处理 | |||
| - pay.js: 微信网页支付相关 | |||
| - utils.js: 通用工具函数 | |||
| - timeUtils.js: 时间处理 | |||
| - position.js: 定位与位置计算 | |||
| - oss-upload: 阿里云OSS上传模块 | |||
| **使用示例:** | |||
| ```javascript | |||
| // 授权处理 | |||
| async preservationImg(img) { | |||
| await this.$authorize('scope.writePhotosAlbum') | |||
| //在执行$authorize之后,await下面的代码都是确保授权完成的情况下执行 | |||
| }, | |||
| // 时间格式化 | |||
| const formattedTime = this.$timeUtils.formatTime(new Date()) | |||
| // 项目中在Vue集成了dayjs >>,可以直接使用 | |||
| // 在utils/index中Vue.prototype.$dayjs | |||
| this.$dayjs() | |||
| // 微信网页支付调用 | |||
| import { wxPay } from '@/utils/pay' | |||
| wxPay(orderData) | |||
| ``` | |||
| #### 3.2 公共组件 | |||
| - navbar.vue: 自定义导航栏 | |||
| - tabbar.vue: 底部导航栏 | |||
| **使用示例:** | |||
| ```html | |||
| <template> | |||
| <view> | |||
| <navbar title="商品列表" /> | |||
| </view> | |||
| </template> | |||
| ``` | |||
| #### 3.3 OSS上传模块 | |||
| **配置说明:** | |||
| 项目使用阿里云OSS进行文件存储,相关配置位于config.js中: | |||
| **使用示例:** | |||
| 1. 单文件上传 | |||
| ```javascript | |||
| export default { | |||
| methods: { | |||
| onUpload(file) { | |||
| this.$Oss.ossUpload(file.path).then(url => { | |||
| this.filePath = url | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| 2. 在uv-upload组件中使用 | |||
| ```html | |||
| <template> | |||
| <uv-upload | |||
| :fileList="fileList" | |||
| @afterRead="afterRead" | |||
| @delete="deleteImage" | |||
| name="1" | |||
| multiple | |||
| :maxCount="maxCount" | |||
| ></uv-upload> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| fileList: [], | |||
| maxCount: 9 | |||
| } | |||
| }, | |||
| methods: { | |||
| // 新增图片 | |||
| afterRead(e) { | |||
| e.file.forEach(file => { | |||
| this.$Oss.ossUpload(file.url).then(url => { | |||
| this.fileList.push({ | |||
| url | |||
| }) | |||
| }) | |||
| }) | |||
| }, | |||
| // 删除图片 | |||
| deleteImage(e) { | |||
| this.fileList.splice(e.index, 1) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| ``` | |||
| **注意事项:** | |||
| 1. 上传前请确保OSS配置正确 | |||
| 2. 建议对上传文件大小进行限制 | |||
| 3. 支持的文件类型:图片、视频、文档等 | |||
| 4. 上传失败时会抛出异常,请做好错误处理 | |||
| ## 最佳实践 | |||
| ### 1. 列表页面开发 | |||
| ```javascript | |||
| // pages/product/list.vue | |||
| import listMixin from '@/mixins/list.js' | |||
| export default { | |||
| mixins: [listMixin], | |||
| data() { | |||
| return { | |||
| mixinsListApi: 'productList', | |||
| } | |||
| }, | |||
| methods: { | |||
| // 分类切换 | |||
| onCategoryChange(categoryId) { | |||
| this.queryParams.categoryId = categoryId | |||
| this.getData() | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| ### 2. 详情页面开发 | |||
| ```javascript | |||
| // pages/product/detail.vue | |||
| import configMixin from '@/mixins/configList.js' | |||
| export default { | |||
| mixins: [configMixin], | |||
| data() { | |||
| return { | |||
| productId: '', | |||
| detail: {} | |||
| } | |||
| }, | |||
| onLoad(options) { | |||
| this.productId = options.id | |||
| this.getDetail() | |||
| }, | |||
| methods: { | |||
| getDetail() { | |||
| this.$api('productDetail', { | |||
| id: this.productId | |||
| }, res => { | |||
| this.detail = res.result | |||
| // 设置分享信息 | |||
| this.Gshare.title = this.detail.name | |||
| this.Gshare.path = `/pages/product/detail?id=${this.productId}` | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| ``` | |||
| ## 注意事项 | |||
| 1. 使用mixins时注意命名冲突 | |||
| 2. API调用建议统一使用this.$api方式 | |||
| 3. 页面开发建议继承相应的混入来复用通用功能 | |||
| ## 常见问题 | |||
| 1. 列表加载失败 | |||
| - 检查mixinsListApi是否正确配置 | |||
| - 确认网络请求是否正常 | |||
| - 查看请求参数格式是否正确 | |||
| @ -0,0 +1,105 @@ | |||
| import http from './http.js' | |||
| import utils from '../utils/utils.js' | |||
| let limit = {} | |||
| let debounce = {} | |||
| const models = ['login', 'index', 'vip', 'info'] | |||
| const config = { | |||
| // 示例 | |||
| // wxLogin : {url : '/api/wxLogin', method : 'POST', | |||
| // auth : false, showLoading : true, loadingTitle : '加载中...', | |||
| // limit : 1000 | |||
| // }, | |||
| getConfig : {url : '/config_common/getConfig', method : 'GET', limit : 500}, | |||
| } | |||
| export function api(key, data, callback, loadingTitle) { | |||
| let req = config[key] | |||
| if (!req) { | |||
| console.error('无效key' + key); | |||
| return Promise.reject() | |||
| } | |||
| if (typeof callback == 'string') { | |||
| loadingTitle = callback | |||
| } | |||
| if (typeof data == 'function') { | |||
| callback = data | |||
| data = {} | |||
| } | |||
| // 接口限流 | |||
| if (req.limit) { | |||
| let storageKey = req.url | |||
| let storage = limit[storageKey] | |||
| if (storage && new Date().getTime() - storage < req.limit) { | |||
| return Promise.reject() | |||
| } | |||
| limit[storageKey] = new Date().getTime() | |||
| } | |||
| //必须登录 | |||
| if (req.auth) { | |||
| if (!uni.getStorageSync('token')) { | |||
| utils.toLogin() | |||
| console.error('需要登录', req.url) | |||
| return Promise.reject() | |||
| } | |||
| } | |||
| // 接口防抖 | |||
| if(req.debounce){ | |||
| let storageKey = req.url | |||
| let storage = debounce[storageKey] | |||
| if (storage) { | |||
| clearTimeout(storage) | |||
| } | |||
| debounce[storageKey] = setTimeout(() => { | |||
| clearTimeout(storage) | |||
| delete debounce[storageKey] | |||
| http.http(req.url, data, callback, req.method, | |||
| loadingTitle || req.showLoading, loadingTitle || req.loadingTitle) | |||
| }, req.debounce) | |||
| return Promise.reject() | |||
| } | |||
| return http.http(req.url, data, callback, req.method, | |||
| loadingTitle || req.showLoading, loadingTitle || req.loadingTitle) | |||
| } | |||
| function addApiModel(model, key){ | |||
| for(let k in model){ | |||
| if(config[`${k}`]){ | |||
| console.error(`重名api------model=${key},key=${k}`); | |||
| uni.showModal({ | |||
| title: `重名api`, | |||
| content: `model=${key},key=${k}` | |||
| }) | |||
| continue | |||
| } | |||
| config[`${k}`] = model[k] | |||
| // config[`${key}_${k}`] = model[k] | |||
| } | |||
| } | |||
| models.forEach(key => { | |||
| addApiModel(require(`./model/${key}.js`).default, key) | |||
| }) | |||
| export default api | |||
| @ -0,0 +1,77 @@ | |||
| import Vue from 'vue' | |||
| import utils from '../utils/utils.js' | |||
| import store from '../store/store.js' | |||
| function http(uri, data, callback, method = 'GET', showLoading, title) { | |||
| if(showLoading){ | |||
| uni.showLoading({ | |||
| title: title || '加载中...' | |||
| }); | |||
| } | |||
| let reject, resolve; | |||
| let promise = new Promise((res, rej) => { | |||
| reject = rej | |||
| resolve = res | |||
| }) | |||
| uni.request({ | |||
| url: Vue.prototype.$config.baseUrl + uri, | |||
| data, | |||
| method: method, | |||
| header: { | |||
| 'X-Access-Token': uni.getStorageSync('token'), | |||
| 'Content-Type' : 'application/x-www-form-urlencoded' | |||
| }, | |||
| success: (res) => { | |||
| // console.log(res,'res') | |||
| if(showLoading){ | |||
| uni.hideLoading(); | |||
| } | |||
| if(res.statusCode == 401 || | |||
| res.data.message == '操作失败,token非法无效!' || | |||
| res.data.message == '操作失败,用户不存在!'){ | |||
| store.commit('logout') | |||
| console.error('登录过期'); | |||
| utils.toLogin() | |||
| } | |||
| if(res.statusCode == 200 && res.data.code != 200 | |||
| && res.data.code != 902){ | |||
| uni.showToast({ | |||
| mask: true, | |||
| duration: 1000, | |||
| title: res.data.message, | |||
| icon:'none' | |||
| }); | |||
| } | |||
| callback && callback(res.data) | |||
| resolve(res.data) | |||
| }, | |||
| fail: () => { | |||
| reject('api fail') | |||
| uni.showLoading({}) | |||
| setTimeout(()=>{ | |||
| uni.hideLoading() | |||
| uni.showToast({icon:"none", title:"网络异常"}) | |||
| }, 3000) | |||
| if(showLoading){ | |||
| uni.hideLoading(); | |||
| } | |||
| } | |||
| }); | |||
| return promise | |||
| } | |||
| export default { | |||
| http: http, | |||
| } | |||
| @ -0,0 +1,215 @@ | |||
| // 首页相关接口 | |||
| const api = { | |||
| // 获取首页轮播图 | |||
| getRiceBanner: { | |||
| url: '/index_common/getRiceBanner', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页常规产品【废弃】 | |||
| // getRiceCommonProductList: { | |||
| // url: '/index_common/getRiceCommonProductList', | |||
| // method: 'GET', | |||
| // }, | |||
| // 获取首页跳转图标 | |||
| getRiceIconList: { | |||
| url: '/index_common/getRiceIconList', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页新闻详情 | |||
| getRiceNewsDetail: { | |||
| url: '/index_common/getCommonNewsDetail', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页新闻列表 | |||
| getRiceNewsList: { | |||
| url: '/index_common/getRiceNewsList', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页公告列表 | |||
| getRiceNoticeList: { | |||
| url: '/index_common/getRiceNoticeList', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页商品详情 | |||
| getRiceProductDetail: { | |||
| url: '/index_common/getRiceProductDetail', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页体验产品 | |||
| getRiceProductList: { | |||
| url: '/index_common/getRiceProductList', | |||
| method: 'GET', | |||
| }, | |||
| // 查询分类接口 | |||
| getCategoryList: { | |||
| url: '/index_common/getCategoryList', | |||
| method: 'GET', | |||
| }, | |||
| // 新查询分类以及商品数据接口 | |||
| getCategoryPidList: { | |||
| url: '/index_common/getCategoryPidList', | |||
| method: 'GET', | |||
| debounce : 250, | |||
| }, | |||
| // 查询一级分类接口 | |||
| getPidList: { | |||
| url: '/index_common/getCategoryPidList', | |||
| method: 'GET', | |||
| }, | |||
| // 获取分类分页商品列表接口 | |||
| getClassShopPageList: { | |||
| url: '/index_common/getClassShopPageList', | |||
| method: 'GET', | |||
| }, | |||
| // 加入购物车 | |||
| addCart: { | |||
| url: '/index_common/addCart', | |||
| method: 'GET', | |||
| auth: true, | |||
| showLoading: true, | |||
| limit : 500, | |||
| }, | |||
| // 删除购物车信息 | |||
| deleteCart: { | |||
| url: '/index_common/deleteCart', | |||
| method: 'DELETE', | |||
| auth: true, | |||
| showLoading: true, | |||
| }, | |||
| // 修改购物车信息数量 | |||
| updateCartNum: { | |||
| url: '/index_common/updateCartNum', | |||
| method: 'POST', | |||
| auth: true, | |||
| debounce: 300, | |||
| }, | |||
| // 创建订单 | |||
| createOrder: { | |||
| url: '/index_common/createOrder', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 创建订单-再次支付 | |||
| createOrderTwo: { | |||
| url: '/index_common/createOrderTwo', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 多商品创建订单 | |||
| createSumOrder: { | |||
| url: '/index_common/createSumOrder', | |||
| method: 'POST', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 多商品订单再次支付 | |||
| createSumOrderAgain: { | |||
| url: '/index_common/createSumOrderAgain', | |||
| method: 'POST', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 确认收货 | |||
| confirmOrder: { | |||
| url: '/index_common/confirmOrder', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 取消订单 | |||
| cancelOrder: { | |||
| url: '/index_common/cancelOrder', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 获取首页广告列表 | |||
| getRiceProductList: { | |||
| url: '/index_common/getRiceAdList', | |||
| method: 'GET', | |||
| }, | |||
| // 获取首页广告列表 | |||
| getRiceAdDetail: { | |||
| url: '/index_common/getRiceAdDetail', | |||
| method: 'GET', | |||
| }, | |||
| //获取优惠券信息 | |||
| getRiceCouponList: { | |||
| url: '/info_common/getRiceCouponList', | |||
| method: 'GET', | |||
| }, | |||
| //增加或者修改合伙人申请信息 | |||
| addOrUpdateCommonUser: { | |||
| url: '/index_common/addOrUpdateCommonUser', | |||
| method: 'POST', | |||
| }, | |||
| //根据用户查询渠合伙人申请信息表单 | |||
| getCommonUser: { | |||
| url: '/index_common/getCommonUser', | |||
| method: 'GET' | |||
| }, | |||
| //提交反馈信息 | |||
| addFeedback: { | |||
| url: '/info_common/addFeedback', | |||
| method: 'POST' | |||
| }, | |||
| // 获取我的直接推荐间接推荐用户列表带分页 | |||
| getHanHaiMemberUser: { | |||
| url: '/info_common/getHanHaiMemberUser', | |||
| method: 'GET' | |||
| }, | |||
| // 获取祝福背景图 | |||
| getRiceBlessing: { | |||
| url: '/index_common/getRiceBlessing', | |||
| method: 'GET' | |||
| }, | |||
| // 随机获取祝福语 | |||
| getRiceBlessingWords: { | |||
| url: '/index_common/getRiceBlessingWords', | |||
| method: 'GET' | |||
| }, | |||
| // 根据订单标识修改订单祝福语背景 | |||
| updateOrderBlessing: { | |||
| url: '/index_common/updateOrderBlessing', | |||
| method: 'POST', | |||
| auth : true, | |||
| limit : 1000, | |||
| }, | |||
| // 1.收礼流程 =》点击收礼 | |||
| getGiveShop: { | |||
| url: '/index_common/getGiveShop', | |||
| method: 'GET', | |||
| auth : true, | |||
| limit : 1000, | |||
| }, | |||
| // 2.点击抽奖 =》抽奖 | |||
| getGiveShopLottery: { | |||
| url: '/index_common/getGiveShopLottery', | |||
| method: 'GET', | |||
| auth : true, | |||
| limit : 1000, | |||
| }, | |||
| // 获取我的礼品订单 | |||
| getMyGiftOrder: { | |||
| url: '/index_common/getMyGiftOrder', | |||
| method: 'GET', | |||
| auth : true, | |||
| }, | |||
| // 获取我的礼品订单详情 | |||
| getMyGiftOrderDetail: { | |||
| url: '/index_common/getMyGiftOrderDetail', | |||
| method: 'GET', | |||
| auth : true, | |||
| }, | |||
| } | |||
| export default api | |||
| @ -0,0 +1,115 @@ | |||
| // 个人相关接口 | |||
| const api = { | |||
| // 充值 | |||
| recharge: { | |||
| url: '/info_common/withdraw', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 提现 | |||
| withdraw: { | |||
| url: '/info_common/withdraw', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| showLoading: true, | |||
| }, | |||
| // 获取地址列表带分页 | |||
| getAddressPageList: { | |||
| url: '/info_common/getAddressPageList', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 增加或修改地址信息 | |||
| addOrUpdateAddress: { | |||
| url: '/info_common/addOrUpdateAddress', | |||
| method: 'POST', | |||
| limit: 500, | |||
| auth: true, | |||
| showLoading: true, | |||
| }, | |||
| // 删除地址 | |||
| deleteAddress: { | |||
| url: '/info_common/deleteAddress', | |||
| method: 'GET', | |||
| limit: 500, | |||
| auth: true, | |||
| showLoading: true, | |||
| }, | |||
| // 修改默认地址 | |||
| updateDefaultAddress: { | |||
| url: '/info_common/updateDefaultAddress', | |||
| method: 'GET', | |||
| auth: true, | |||
| limit: 1000, | |||
| }, | |||
| // 获取粉丝列表带分页 | |||
| getFansPageList: { | |||
| url: '/info_common/getFansPageList', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取相关介绍 | |||
| getInfoIntroduce: { | |||
| url: '/info_common/getInfoIntroduce', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取个人邀请码 | |||
| getInviteCode: { | |||
| url: '/info_common/getInviteCode', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取订单列表带分页 | |||
| getOrderPageList: { | |||
| url: '/info_common/getOrderPageList', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取订单详情 | |||
| getOrderDetail: { | |||
| url: '/info_common/getOrderDetail', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取流水记录带分页 | |||
| getWaterPageList: { | |||
| url: '/info_common/getWaterPageList', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 获取相关介绍 | |||
| getInfoIntroduce: { | |||
| url: '/info_common/getInfoIntroduce', | |||
| method: 'GET', | |||
| }, | |||
| // 获取相关介绍详情 | |||
| getInfoIntroduceDetail: { | |||
| url: '/info_common/getRiceNewsDetail', | |||
| method: 'GET', | |||
| }, | |||
| // 查询个人信息相关 | |||
| getRiceInfo: { | |||
| url: '/info_common/getRiceInfo', | |||
| method: 'GET', | |||
| limit: 500, | |||
| }, | |||
| // 获取购物车信息列表带分页 | |||
| getCartPageList: { | |||
| url: '/info_common/getCartPageList', | |||
| method: 'GET', | |||
| }, | |||
| // 领取新人优惠券 | |||
| getRiceCoupon: { | |||
| url: '/info_common/getRiceCoupon', | |||
| method: 'GET', | |||
| limit: 500, | |||
| auth: true, | |||
| }, | |||
| } | |||
| export default api | |||
| @ -0,0 +1,35 @@ | |||
| // 登录相关接口 | |||
| const api = { | |||
| // 微信登录接口 | |||
| wxLogin: { | |||
| url: '/login_common/appletLogin', | |||
| method: 'GET', | |||
| limit : 500, | |||
| showLoading : true, | |||
| }, | |||
| // 获取绑定手机号码 | |||
| bindPhone: { | |||
| url: '/login_common/bindPhone', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| // 修改个人信息接口 | |||
| updateInfo: { | |||
| url: '/info_common/updateInfo', | |||
| method: 'POST', | |||
| auth: true, | |||
| limit : 500, | |||
| showLoading : true, | |||
| }, | |||
| // 获取个人信息 | |||
| getInfo: { | |||
| url: '/info_common/getInfo', | |||
| method: 'GET', | |||
| auth: true, | |||
| }, | |||
| } | |||
| export default api | |||
| @ -0,0 +1,20 @@ | |||
| // vip相关接口 | |||
| const api = { | |||
| // 获取会员权益列表 | |||
| getRiceVipList: { | |||
| url: '/index_common/getVipInfoList', | |||
| method: 'GET', | |||
| }, | |||
| // 申请成为会员 | |||
| applyRiceVip: { | |||
| url: '/rice_vip/applyRiceVip', | |||
| method: 'POST', | |||
| limit : 500, | |||
| auth : true, | |||
| showLoading : true, | |||
| }, | |||
| } | |||
| export default api | |||
| @ -0,0 +1,40 @@ | |||
| // 文字益处处理 | |||
| .text-ellipsis{ | |||
| overflow:hidden; //超出的文本隐藏 | |||
| text-overflow:ellipsis; //溢出用省略号显示 | |||
| white-space:nowrap; //溢出不换行 | |||
| } | |||
| .text-ellipsis-2{ | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| display:-webkit-box; //作为弹性伸缩盒子模型显示。 | |||
| -webkit-box-orient:vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列 | |||
| -webkit-line-clamp:2; //显示的行 | |||
| } | |||
| .text-ellipsis-3{ | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| display:-webkit-box; //作为弹性伸缩盒子模型显示。 | |||
| -webkit-box-orient:vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列 | |||
| -webkit-line-clamp:3; //显示的行 | |||
| } | |||
| .share{ | |||
| padding: 0; | |||
| margin: 0; | |||
| background-color: #fff; | |||
| display: flex !important; | |||
| flex-direction: column !important; | |||
| justify-content: center !important; | |||
| align-items: center !important; | |||
| font-size: 26rpx; | |||
| } | |||
| .share::after{ | |||
| border: none; | |||
| padding: 0; | |||
| margin: 0; | |||
| width: 0; | |||
| height: 0; | |||
| } | |||
| @ -0,0 +1,143 @@ | |||
| <template> | |||
| <!-- <view class="navbar" | |||
| :style="{backgroundColor : bgColor}"> --> | |||
| <view class="title" | |||
| :style="{backgroundColor : bgColor,color}"> | |||
| <view class="left"> | |||
| <uv-icon name="home" | |||
| v-if="leftClick && length == 1" | |||
| @click="toHome" | |||
| :color="color" size="46rpx"></uv-icon> | |||
| <uv-icon name="arrow-left" | |||
| v-else-if="leftClick" | |||
| @click="$emit('leftClick')" | |||
| :color="color" size="46rpx"></uv-icon> | |||
| </view> | |||
| <view>{{ title }}</view> | |||
| <view class="icon"> | |||
| <uv-icon name="search" | |||
| v-if="isSearch" | |||
| :color="color" size="58rpx"></uv-icon> | |||
| <uv-icon name="plus-circle" :color="color" | |||
| v-if="isPlus" | |||
| @click="plusCircleShow = true" | |||
| size="46rpx" style="margin-left: 30rpx;"></uv-icon> | |||
| <view v-if="moreClick" style="margin-left: 30rpx;"> | |||
| <uv-icon name="more-dot-fill" :color="color" | |||
| v-if="!moreText" | |||
| @click="moreClick()" | |||
| size="46rpx"></uv-icon> | |||
| <view v-else @click="moreClick" | |||
| style="font-weight: 400;font-size: 30rpx;"> | |||
| {{ moreText }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- </view> --> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name:"navbar", | |||
| props : { | |||
| title : { | |||
| type : String, | |||
| default : '' | |||
| }, | |||
| leftClick : { | |||
| type : Boolean, | |||
| }, | |||
| moreClick : { | |||
| type : Function, | |||
| }, | |||
| isSearch : { | |||
| type : Boolean, | |||
| default : false, | |||
| }, | |||
| isPlus : { | |||
| type : Boolean, | |||
| default : false, | |||
| }, | |||
| moreText : { | |||
| }, | |||
| bgColor : { | |||
| default : '#fff' | |||
| }, | |||
| color : { | |||
| default : '#333' | |||
| } | |||
| }, | |||
| created() { | |||
| }, | |||
| beforeDestroy() { | |||
| }, | |||
| data() { | |||
| return { | |||
| length : getCurrentPages().length | |||
| }; | |||
| }, | |||
| methods : { | |||
| toHome(){ | |||
| if(this.length != 1){ | |||
| return | |||
| } | |||
| uni.reLaunch({ | |||
| url: '/pages/index/index' | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| // .navbar{ | |||
| // width: 100%; | |||
| // height: 120rpx; | |||
| // padding-top: var(--status-bar-height); | |||
| // } | |||
| .title{ | |||
| position: sticky; | |||
| top: 0; | |||
| left: 0; | |||
| padding-top: calc(var(--status-bar-height) + 20rpx); | |||
| width: 100%; | |||
| height: 100rpx; | |||
| background-color: #fff; | |||
| display: flex; | |||
| justify-content: center; | |||
| font-size: 32rpx; | |||
| align-items: center; | |||
| z-index: 999; | |||
| .left{ | |||
| position: absolute; | |||
| left: 40rpx; | |||
| display: flex; | |||
| justify-content: flex-start; | |||
| } | |||
| .icon{ | |||
| position: absolute; | |||
| right: 40rpx; | |||
| display: flex; | |||
| justify-content: flex-end; | |||
| } | |||
| } | |||
| @keyframes fade-in { | |||
| 0% { | |||
| opacity: 0; | |||
| } | |||
| 100% { | |||
| opacity: 1; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,134 @@ | |||
| <template> | |||
| <view class="tabbar-box"> | |||
| <view class="tabbar"> | |||
| <view :class="{ 'tabbar-active' : select == item.key}" v-for="(item, index) in list" :key="index" | |||
| v-if="!item.isNotShop || !userShop" @click="toPath(item, index)" class="tabbar-item"> | |||
| <view class="tabbar-icon"> | |||
| <image :src="select == item.key ? | |||
| item.selectedIconPath : | |||
| item.iconPath" class="tabbar-icon-image" mode="aspectFill"></image> | |||
| </view> | |||
| <view class="tabbar-title"> | |||
| {{ item.title }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import { | |||
| mapGetters | |||
| } from 'vuex' | |||
| export default { | |||
| name: "tabbar", | |||
| props: ['select'], | |||
| computed: { | |||
| ...mapGetters(['userShop']), | |||
| }, | |||
| data() { | |||
| return { | |||
| list: [{ | |||
| "selectedIconPath": "/static/image/tabbar/home-a.png", | |||
| "iconPath": "/static/image/tabbar/home.png", | |||
| "pagePath": "/pages/index/index", | |||
| "title": "首页", | |||
| key: 'home', | |||
| }, | |||
| { | |||
| "selectedIconPath": "/static/image/tabbar/category-a.png", | |||
| "iconPath": "/static/image/tabbar/category.png", | |||
| "pagePath": "/pages/index/category", | |||
| "title": "商品列表", | |||
| key: 'category', | |||
| }, | |||
| { | |||
| "selectedIconPath": "/static/image/tabbar/order-a.png", | |||
| "iconPath": "/static/image/tabbar/order.png", | |||
| "pagePath": "/pages/index/order", | |||
| "title": "订单", | |||
| key: 'order', | |||
| }, | |||
| { | |||
| "selectedIconPath": "/static/image/tabbar/cart-a.png", | |||
| "iconPath": "/static/image/tabbar/cart.png", | |||
| "pagePath": "/pages/index/cart", | |||
| "title": "购物车", | |||
| key: 'cart', | |||
| }, | |||
| { | |||
| "selectedIconPath": "/static/image/tabbar/center-a.png", | |||
| "iconPath": "/static/image/tabbar/center.png", | |||
| "pagePath": "/pages/index/center", | |||
| "title": "我的", | |||
| key: 'center', | |||
| } | |||
| ] | |||
| }; | |||
| }, | |||
| methods: { | |||
| toPath(item, index) { | |||
| if (item.key == this.select) { | |||
| return | |||
| } | |||
| uni.reLaunch({ | |||
| url: item.pagePath | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .tabbar-box { | |||
| height: 120rpx; | |||
| padding-bottom: env(safe-area-inset-bottom); | |||
| .tabbar { | |||
| position: fixed; | |||
| width: 750rpx; | |||
| background-color: #fff; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| flex-direction: row; | |||
| height: 120rpx; | |||
| padding-bottom: env(safe-area-inset-bottom); | |||
| z-index: 999999; | |||
| bottom: 0; | |||
| left: 0; | |||
| color: #BCBCBC; | |||
| .tabbar-item { | |||
| flex: 1; | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: center; | |||
| align-items: center; | |||
| .tabbar-icon { | |||
| width: 54rpx; | |||
| height: 54rpx; | |||
| .tabbar-icon-image { | |||
| width: 54rpx; | |||
| height: 54rpx; | |||
| } | |||
| } | |||
| .tabbar-title { | |||
| overflow: hidden; | |||
| white-space: nowrap; | |||
| text-overflow: ellipsis; | |||
| -o-text-overflow: ellipsis; | |||
| font-size: 23rpx; | |||
| line-height: 35rpx; | |||
| } | |||
| } | |||
| .tabbar-active { | |||
| color: $uni-color !important; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,169 @@ | |||
| <template> | |||
| <uv-popup ref="popup" z-index="99999" :closeOnClickOverlay="false" :customStyle="{ backgroundColor: 'transparent' }"> | |||
| <view class="privacyPopup"> | |||
| <view class="icon"> | |||
| <image src="/static/image/PrivacyAgreementPoup/icon.png" | |||
| mode=""></image> | |||
| </view> | |||
| <view class="title"> | |||
| <view>协议与隐私政策</view> | |||
| </view> | |||
| <view class="content_pri"> | |||
| <view class="text"> | |||
| 欢迎来到酒店布草!我们根据最新的法律法规、监管政策要求,更新了《用户协议》和《隐私政策》,请您认真阅读。 | |||
| </view> | |||
| </view> | |||
| <view class="config"> | |||
| <uv-checkbox-group v-model="checkboxValue" shape="circle"> | |||
| <view class="content"> | |||
| <view style="display: flex;"> | |||
| <!-- <uv-checkbox size="30rpx" :name="1"></uv-checkbox> --> | |||
| 同意<text @click="goToPrivacy">《酒店布草隐私政策》</text> | |||
| </view> | |||
| <view class=""> | |||
| 以及<text @click="goToPrivacy">《用户协议》</text> | |||
| </view> | |||
| </view> | |||
| </uv-checkbox-group> | |||
| </view> | |||
| <view class="pri_btn"> | |||
| <button class="confuse_btn" @click="confusePrivacy">拒绝</button> | |||
| <button | |||
| class="confirm_btn" id="agree-btn" | |||
| open-type="agreePrivacyAuthorization" | |||
| @agreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button> | |||
| </view> | |||
| </view> | |||
| </uv-popup> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'PrivacyAgreementPoup', | |||
| data() { | |||
| return { | |||
| resolvePrivacyAuthorization: {}, | |||
| checkboxValue : false | |||
| } | |||
| }, | |||
| mounted() { | |||
| if(wx.getPrivacySetting){ | |||
| wx.getPrivacySetting({ | |||
| success: res => { | |||
| console.log(res) | |||
| if (res.needAuthorization) { | |||
| // 需要弹出隐私协议 | |||
| this.init() | |||
| } | |||
| }, | |||
| fail: () => {} | |||
| }) | |||
| } | |||
| }, | |||
| methods: { | |||
| //初始化 | |||
| init(resolve) { | |||
| this.$refs.popup.open('center') | |||
| this.resolvePrivacyAuthorization = resolve | |||
| }, | |||
| // 打开隐私协议 | |||
| goToPrivacy() { | |||
| wx.openPrivacyContract({ | |||
| success: () => { | |||
| console.log('打开成功'); | |||
| }, // 打开成功 | |||
| fail: () => { | |||
| uni.showToast({ | |||
| title: '打开失败,稍后重试', | |||
| icon: 'none' | |||
| }) | |||
| } // 打开失败 | |||
| }) | |||
| }, | |||
| // 拒绝 | |||
| confusePrivacy() { | |||
| this.$refs.popup.close() | |||
| // this.resolvePrivacyAuthorization({ | |||
| // event: 'disagree' | |||
| // }) | |||
| }, | |||
| // 同意 | |||
| handleAgreePrivacyAuthorization() { | |||
| // 告知平台用户已经同意,参数传同意按钮的id | |||
| // this.resolvePrivacyAuthorization({ | |||
| // buttonId: 'agree-btn', | |||
| // event: 'agree' | |||
| // }) | |||
| this.$refs.popup.close() | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .privacyPopup { | |||
| width: 90%; | |||
| margin: 0rpx auto; | |||
| background: white; | |||
| border-radius: 20rpx; | |||
| box-sizing: border-box; | |||
| padding: 40rpx 30rpx; | |||
| .icon{ | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| padding-bottom: 30rpx; | |||
| image{ | |||
| width: 90rpx; | |||
| height: 90rpx; | |||
| } | |||
| } | |||
| .title { | |||
| text-align: center; | |||
| font-size: 36rpx; | |||
| } | |||
| .content_pri { | |||
| padding: 30rpx 0rpx; | |||
| font-size: 28rpx; | |||
| } | |||
| .config { | |||
| font-size: 28rpx; | |||
| text-align: center; | |||
| line-height: 40rpx; | |||
| margin-bottom: 30rpx; | |||
| text { | |||
| color: $uni-color; | |||
| } | |||
| .content{ | |||
| display: flex; | |||
| } | |||
| } | |||
| .pri_btn { | |||
| display: flex; | |||
| .confuse_btn{ | |||
| background-color: #F2F2F2; | |||
| color: #BDBDBD; | |||
| } | |||
| button { | |||
| margin: 10rpx; | |||
| flex: 1; | |||
| background: $uni-color; | |||
| outline: none; | |||
| color: white; | |||
| font-size: 30rpx; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,48 @@ | |||
| <template> | |||
| <view class="configPopup"> | |||
| <uv-popup ref="popup" :round="30" :customStyle="{height: '50vh'}"> | |||
| <view class="content"> | |||
| <uv-parse :content="content"></uv-parse> | |||
| </view> | |||
| </uv-popup> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import { mapState } from 'vuex' | |||
| export default { | |||
| name: 'configPoup', | |||
| data() { | |||
| return { | |||
| content : '' | |||
| } | |||
| }, | |||
| onShow(){ | |||
| }, | |||
| methods: { | |||
| //打开配置信息菜单 | |||
| open(key){ | |||
| this.content = this.configList[key] | |||
| this.$refs.popup.open('bottom'); | |||
| } | |||
| }, | |||
| computed : { | |||
| ...mapState(['configList']) | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .configPopup { | |||
| .content{ | |||
| padding: 30rpx 20rpx; | |||
| overflow: scroll; | |||
| height: 100%; | |||
| box-sizing: border-box; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,122 @@ | |||
| <template> | |||
| <!-- 联系客服弹框 --> | |||
| <uv-popup ref="popup" | |||
| :safeAreaInsetBottom="false" | |||
| :round="30"> | |||
| <view class="warp"> | |||
| <view class="rect" @tap.stop> | |||
| <view class="title">联系{{ bTitle || title }}</view> | |||
| <view class="center">确定拨打{{ bTitle || title }}电话?</view> | |||
| <view class="bottom"> | |||
| <view class="btn1" | |||
| @click="close"> | |||
| 取消 | |||
| </view> | |||
| <view class="btn2" | |||
| @click="confirm"> | |||
| 确定 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </uv-popup> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| phone:'', | |||
| title : '客服', | |||
| bPhone : '', | |||
| bTitle : '', | |||
| } | |||
| }, | |||
| mounted() { | |||
| this.getCustomPhone() | |||
| }, | |||
| methods: { | |||
| getCustomPhone(){ | |||
| this.$api('customUser', {}, res => { | |||
| this.phone = res.result.phone | |||
| }) | |||
| }, | |||
| open(phone, title) { | |||
| this.bPhone = phone || this.phone | |||
| this.bTitle = title || this.title | |||
| this.$refs.popup.open() | |||
| }, | |||
| close() { | |||
| this.$refs.popup.close() | |||
| }, | |||
| // 拨打电话 | |||
| confirm() { | |||
| this.$refs.popup.close() | |||
| uni.makePhoneCall({ | |||
| phoneNumber: this.bPhone || this.phone, | |||
| success() { | |||
| console.log('安卓拨打成功'); | |||
| }, | |||
| fail() { | |||
| console.log('安卓拨打失败'); | |||
| } | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .warp { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| height: 100%; | |||
| } | |||
| .rect { | |||
| width: 600rpx; | |||
| height: 300rpx; | |||
| background-color: #fff; | |||
| border-radius: 20rpx; | |||
| overflow: hidden; | |||
| .title { | |||
| padding: 10rpx 0 0 15rpx; | |||
| background-color: $uni-color; | |||
| color: #FFF; | |||
| text-align: left; | |||
| width: 100%; | |||
| height: 18%; | |||
| font-size: 36rpx; | |||
| } | |||
| .center { | |||
| height: 40%; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| font-size: 36rpx; | |||
| } | |||
| .bottom { | |||
| display: flex; | |||
| justify-content: center; | |||
| gap: 50rpx; | |||
| view{ | |||
| height: 60rpx; | |||
| line-height: 60rpx; | |||
| padding: 0 50rpx; | |||
| border-radius: 30rpx; | |||
| } | |||
| .btn1{ | |||
| background-color: #fff; | |||
| } | |||
| .btn2{ | |||
| background-color: $uni-color; | |||
| color: #fff; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,112 @@ | |||
| <template> | |||
| <view class="list"> | |||
| <view class="item" | |||
| v-for="(item, index) in 10" | |||
| @click="$utils.navigateTo('/pages_order/product/productDetail?id=123')" | |||
| :key="index"> | |||
| <image | |||
| class="image" | |||
| src="https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg" mode=""></image> | |||
| <view class="info"> | |||
| <view class="title"> | |||
| 桌布租赁 | |||
| </view> | |||
| <view class="price"> | |||
| <text>¥58</text>元/起 | |||
| </view> | |||
| <view class="favorable"> | |||
| <view class="t"> | |||
| 限时优惠 | |||
| </view> | |||
| <view class="p"> | |||
| ¥48 | |||
| </view> | |||
| </view> | |||
| <view class="num"> | |||
| 已售卖5000+件 | |||
| </view> | |||
| </view> | |||
| <view class="btn"> | |||
| <uv-icon name="shopping-cart" | |||
| color="#fff"></uv-icon> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name:"productList", | |||
| data() { | |||
| return { | |||
| }; | |||
| }, | |||
| methods : { | |||
| }, | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .list{ | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| .item{ | |||
| position: relative; | |||
| width: 300rpx; | |||
| padding: 20rpx; | |||
| background-color: #fff; | |||
| border-radius: 20rpx; | |||
| margin-top: 20rpx; | |||
| &:nth-child(odd){ | |||
| margin-right: 20rpx; | |||
| } | |||
| .image{ | |||
| width: 300rpx; | |||
| height: 250rpx; | |||
| border-radius: 20rpx; | |||
| } | |||
| .info{ | |||
| font-size: 26rpx; | |||
| .title{ | |||
| font-size: 30rpx; | |||
| } | |||
| .price{ | |||
| color: #D03F25; | |||
| margin-top: 6rpx; | |||
| text{ | |||
| font-size: 34rpx; | |||
| font-weight: 900; | |||
| } | |||
| } | |||
| .favorable{ | |||
| display: flex; | |||
| background-image: url(/static/image/product/favorable.png); | |||
| background-size: 100% 100%; | |||
| width: fit-content; | |||
| padding: 5rpx 10rpx; | |||
| font-size: 18rpx; | |||
| margin-top: 6rpx; | |||
| .p{ | |||
| color: #fff; | |||
| margin-left: 10rpx; | |||
| } | |||
| } | |||
| .num{ | |||
| margin-top: 6rpx; | |||
| font-size: 22rpx; | |||
| color: #888; | |||
| } | |||
| } | |||
| .btn{ | |||
| position: absolute; | |||
| right: 20rpx; | |||
| bottom: 20rpx; | |||
| padding: 10rpx; | |||
| border-radius: 50%; | |||
| background-color: $uni-color; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,130 @@ | |||
| <template> | |||
| <view class="commission"> | |||
| <image src="/static/image/center/10.png" mode=""></image> | |||
| <view class="price"> | |||
| <view class="title"> | |||
| 总佣金(元) | |||
| </view> | |||
| <view class="num"> | |||
| 7890.34元 | |||
| </view> | |||
| </view> | |||
| <view class="font-menu" | |||
| v-if="purse"> | |||
| <view @click="toRunningWater(index)" | |||
| v-for="(item, index) in list" | |||
| :key="index">{{ item.name }}</view> | |||
| </view> | |||
| <view class="btn" | |||
| v-if="!purse" | |||
| @click="toPurse"> | |||
| 提现 | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: "userShopCommission", | |||
| props : { | |||
| purse : { | |||
| default : false, | |||
| }, | |||
| }, | |||
| data() { | |||
| return { | |||
| list : [ | |||
| { | |||
| name : '余额记录', | |||
| }, | |||
| { | |||
| name : '提现记录', | |||
| }, | |||
| { | |||
| name : '佣金记录', | |||
| }, | |||
| ], | |||
| }; | |||
| }, | |||
| methods : { | |||
| // 跳转到钱包提现 | |||
| toPurse(){ | |||
| uni.navigateTo({ | |||
| url:'/pages_order/mine/purse' | |||
| }) | |||
| }, | |||
| // 跳转到记录页面 | |||
| toRunningWater(index){ | |||
| uni.navigateTo({ | |||
| url:'/pages_order/mine/runningWater?status=' + index | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .commission { | |||
| width: 700rpx; | |||
| height: 300rpx; | |||
| position: relative; | |||
| margin: 20rpx auto; | |||
| color: #fff; | |||
| image { | |||
| width: 700rpx; | |||
| height: 300rpx; | |||
| position: absolute; | |||
| border-radius: 20rpx; | |||
| } | |||
| .price { | |||
| position: absolute; | |||
| left: 50rpx; | |||
| top: 80rpx; | |||
| font-weight: 900; | |||
| .title { | |||
| font-size: 32rpx; | |||
| } | |||
| .num { | |||
| font-size: 44rpx; | |||
| margin-top: 20rpx; | |||
| } | |||
| } | |||
| .font-menu { | |||
| font-size: 24rpx; | |||
| font-family: PingFang SC, PingFang SC-Regular; | |||
| font-weight: 500; | |||
| text-align: center; | |||
| color: #ffffff; | |||
| line-height: 24rpx; | |||
| width: 710rpx; | |||
| position: absolute; | |||
| left: 0; | |||
| bottom: 25rpx; | |||
| display: flex; | |||
| view{ | |||
| width: 160rpx; | |||
| } | |||
| } | |||
| .btn { | |||
| position: absolute; | |||
| right: 50rpx; | |||
| bottom: 50rpx; | |||
| background-color: #FDC440; | |||
| width: 160rpx; | |||
| height: 60rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| border-radius: 30rpx; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,56 @@ | |||
| import Vue from 'vue' | |||
| import api from '@/api/api.js' | |||
| import utils from './utils/utils.js' | |||
| import uvUI from '@/uni_modules/uv-ui-tools' | |||
| Vue.use(uvUI); | |||
| // 当前环境 | |||
| const type = 'dev' | |||
| // 环境配置 | |||
| const config = { | |||
| dev : { | |||
| baseUrl : 'http://www.gcosc.fun:82', | |||
| }, | |||
| prod : { | |||
| baseUrl : 'http://xxx.xxx.xxx/xxx', | |||
| } | |||
| } | |||
| // 默认配置 | |||
| const defaultConfig = { | |||
| mapKey : 'XMBBZ-BCPCV-SXPPQ-5Y7MY-PHZXK-YFFVU', | |||
| aliOss: { | |||
| url: 'https://image.hhlm1688.com/', | |||
| config: { | |||
| //桶的地址 | |||
| region: 'oss-cn-guangzhou', | |||
| //id | |||
| accessKeyId: 'LTAI5tQSs47izVy8DLVdwUU9', | |||
| //密钥 | |||
| accessKeySecret: 'qHI7C3PaXYZySr84HTToviC71AYlFq', | |||
| //桶的名字 | |||
| bucket: 'hanhaiimage', | |||
| endpoint: 'oss-cn-shenzhen.aliyuncs.com', | |||
| } | |||
| }, | |||
| } | |||
| uni.$uv.setConfig({ | |||
| // 修改$uv.config对象的属性 | |||
| config: { | |||
| // 修改默认单位为rpx,相当于执行 uni.$uv.config.unit = 'rpx' | |||
| unit: 'rpx' | |||
| }, | |||
| }) | |||
| Vue.prototype.$config = utils.deepMergeObject(defaultConfig, config[type]) | |||
| Vue.prototype.$api = api | |||
| export default Vue.prototype.$config | |||
| @ -0,0 +1,20 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8" /> | |||
| <script> | |||
| var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || | |||
| CSS.supports('top: constant(a)')) | |||
| document.write( | |||
| '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + | |||
| (coverSupport ? ', viewport-fit=cover' : '') + '" />') | |||
| </script> | |||
| <title></title> | |||
| <!--preload-links--> | |||
| <!--app-context--> | |||
| </head> | |||
| <body> | |||
| <div id="app"><!--app-html--></div> | |||
| <script type="module" src="/main.js"></script> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,45 @@ | |||
| import App from './App' | |||
| // #ifndef VUE3 | |||
| import Vue from 'vue' | |||
| import './uni.promisify.adaptor' | |||
| Vue.config.productionTip = false | |||
| App.mpType = 'app' | |||
| import store from '@/store/store' | |||
| import './config' | |||
| import './utils/index.js' | |||
| import mixinConfigList from '@/mixins/configList.js' | |||
| Vue.mixin(mixinConfigList) | |||
| //组件注册 | |||
| import configPopup from '@/components/config/configPopup.vue' | |||
| import navbar from '@/components/base/navbar.vue' | |||
| Vue.component('configPopup',configPopup) | |||
| Vue.component('navbar',navbar) | |||
| const app = new Vue({ | |||
| ...App, | |||
| store, | |||
| }) | |||
| app.$mount() | |||
| // #endif | |||
| // #ifdef VUE3 | |||
| import { | |||
| createSSRApp | |||
| } from 'vue' | |||
| export function createApp() { | |||
| const app = createSSRApp(App) | |||
| return { | |||
| app | |||
| } | |||
| } | |||
| // #endif | |||
| @ -0,0 +1,105 @@ | |||
| { | |||
| "name" : "unapp模板", | |||
| "appid" : "__UNI__197A38F", | |||
| "description" : "", | |||
| "versionName" : "1.0.0", | |||
| "versionCode" : "100", | |||
| "transformPx" : false, | |||
| /* 5+App特有相关 */ | |||
| "app-plus" : { | |||
| "usingComponents" : true, | |||
| "nvueStyleCompiler" : "uni-app", | |||
| "compilerVersion" : 3, | |||
| "splashscreen" : { | |||
| "alwaysShowBeforeRender" : true, | |||
| "waiting" : true, | |||
| "autoclose" : true, | |||
| "delay" : 0 | |||
| }, | |||
| /* 模块配置 */ | |||
| "modules" : {}, | |||
| /* 应用发布信息 */ | |||
| "distribute" : { | |||
| /* android打包配置 */ | |||
| "android" : { | |||
| "permissions" : [ | |||
| "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", | |||
| "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", | |||
| "<uses-permission android:name=\"android.permission.VIBRATE\"/>", | |||
| "<uses-permission android:name=\"android.permission.READ_LOGS\"/>", | |||
| "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", | |||
| "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", | |||
| "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", | |||
| "<uses-permission android:name=\"android.permission.CAMERA\"/>", | |||
| "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", | |||
| "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", | |||
| "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", | |||
| "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", | |||
| "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", | |||
| "<uses-feature android:name=\"android.hardware.camera\"/>", | |||
| "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" | |||
| ] | |||
| }, | |||
| /* ios打包配置 */ | |||
| "ios" : {}, | |||
| /* SDK配置 */ | |||
| "sdkConfigs" : { | |||
| "maps" : {} | |||
| } | |||
| } | |||
| }, | |||
| /* 快应用特有相关 */ | |||
| "quickapp" : {}, | |||
| /* 小程序特有相关 */ | |||
| "mp-weixin" : { | |||
| "appid" : "wxe7ae8cbe1673834c", | |||
| "setting" : { | |||
| "urlCheck" : false | |||
| }, | |||
| "usingComponents" : true, | |||
| "permission" : { | |||
| "scope.userLocation" : { | |||
| "desc" : "你的位置信息将用于小程序位置接口的效果展示" | |||
| }, | |||
| "scope.userFuzzyLocation" : { | |||
| "desc" : "你的位置信息将用于小程序位置接口的效果展示" | |||
| } | |||
| }, | |||
| "requiredPrivateInfos" : [ "chooseLocation", "getLocation" ] | |||
| }, | |||
| "mp-alipay" : { | |||
| "usingComponents" : true | |||
| }, | |||
| "mp-baidu" : { | |||
| "usingComponents" : true | |||
| }, | |||
| "mp-toutiao" : { | |||
| "usingComponents" : true | |||
| }, | |||
| "uniStatistics" : { | |||
| "enable" : false | |||
| }, | |||
| "vueVersion" : "2", | |||
| "h5" : { | |||
| "sdkConfigs" : { | |||
| "maps" : { | |||
| "qqmap" : { | |||
| "key" : "XMBBZ-BCPCV-SXPPQ-5Y7MY-PHZXK-YFFVU" | |||
| } | |||
| } | |||
| }, | |||
| "devServer" : { | |||
| "https" : false, | |||
| "proxy" : { | |||
| "/ws/geocoder/v1/" : { | |||
| "target" : "https://apis.map.qq.com", | |||
| "changeOrigin" : true | |||
| }, | |||
| "/ws/location/v1/" : { | |||
| "target" : "https://apis.map.qq.com", | |||
| "changeOrigin" : true | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,47 @@ | |||
| import { mapState } from 'vuex' | |||
| export default { | |||
| data() { | |||
| return { | |||
| // 默认的全局分享内容 | |||
| Gshare: { | |||
| // title: '三只青蛙', | |||
| path: '/pages/index/index', // 全局分享的路径,比如 首页 | |||
| // imageUrl: '/static/image/login/logo.png', // 全局分享的图片(可本地可网络) | |||
| } | |||
| } | |||
| }, | |||
| computed: { | |||
| ...mapState(['configList', 'userInfo', 'riceInfo']), | |||
| }, | |||
| // 定义全局分享 | |||
| // 1.发送给朋友 | |||
| onShareAppMessage(res) { | |||
| let o = { | |||
| title : this.configList.logo_name, | |||
| ...this.Gshare, | |||
| } | |||
| if(this.userInfo.id){ | |||
| if(this.Gshare.path.includes('?')){ | |||
| o.path += '&shareId=' + this.userInfo.id | |||
| }else{ | |||
| o.path += '?shareId=' + this.userInfo.id | |||
| } | |||
| } | |||
| return o | |||
| }, | |||
| //2.分享到朋友圈 | |||
| onShareTimeline(res) { | |||
| let o = { | |||
| ...this.Gshare, | |||
| title : this.configList.logo_name, | |||
| } | |||
| if(this.userInfo.id){ | |||
| o.path = this.Gshare.path + '?shareId=' + this.userInfo.id | |||
| } | |||
| return o | |||
| }, | |||
| methods: { | |||
| } | |||
| } | |||
| @ -0,0 +1,78 @@ | |||
| /** | |||
| * 处理查询参数 | |||
| * @param {Object} self - 组件实例 | |||
| * @param {Object} queryParams - 额外的查询参数 | |||
| * @returns {Object} 合并后的查询参数 | |||
| */ | |||
| function query(self, queryParams){ | |||
| // 深度合并对象 | |||
| return self.$utils.deepMergeObject( | |||
| self.$utils.deepMergeObject(self.queryParams, | |||
| (self.beforeGetData && self.beforeGetData()) || {}), | |||
| queryParams) | |||
| } | |||
| /** | |||
| * 列表数据加载混入 | |||
| * 提供列表数据的加载、分页、下拉刷新、上拉加载更多等功能 | |||
| */ | |||
| export default { | |||
| data() { | |||
| return { | |||
| queryParams: { | |||
| pageNo: 1, | |||
| pageSize: 10, | |||
| }, | |||
| total : 0, | |||
| list : [], | |||
| } | |||
| }, | |||
| // 下拉刷新 | |||
| onPullDownRefresh() { | |||
| this.getData() | |||
| }, | |||
| // 上拉加载更多 | |||
| onReachBottom() { | |||
| this.loadMoreData() | |||
| }, | |||
| // 页面显示时加载数据 | |||
| onShow() { | |||
| this.getData() | |||
| }, | |||
| methods: { | |||
| /** | |||
| * 获取列表数据 | |||
| * @param {Object} queryParams - 查询参数 | |||
| * @returns {Promise} 返回Promise对象 | |||
| */ | |||
| getData(queryParams){ | |||
| return new Promise((success, error) => { | |||
| if(!this.mixinsListApi){ | |||
| return console.error('mixinsListApi 缺失'); | |||
| } | |||
| this.$api(this.mixinsListApi, | |||
| query(this, queryParams), res => { | |||
| uni.stopPullDownRefresh() | |||
| if(res.code == 200){ | |||
| success(res.result) | |||
| // 更新列表数据 | |||
| this[this.mixinsListKey || 'list'] = res.result.records || res.result | |||
| // 更新总数 | |||
| this.total = res.result.total || res.result.length | |||
| // 调用数据加载完成的回调 | |||
| this.getDataThen && this.getDataThen(res.result.records, res.result.total, res.result) | |||
| } | |||
| }) | |||
| }) | |||
| }, | |||
| /** | |||
| * 加载更多数据 | |||
| */ | |||
| loadMoreData(){ | |||
| if(this.queryParams.pageSize < this.total){ | |||
| this.queryParams.pageSize += 10 | |||
| this.getData() | |||
| } | |||
| }, | |||
| } | |||
| } | |||
| @ -0,0 +1,70 @@ | |||
| export default { | |||
| data() { | |||
| return { | |||
| } | |||
| }, | |||
| computed: { | |||
| }, | |||
| methods: { | |||
| // 立即支付 | |||
| toPayOrder(item){ | |||
| let api = '' | |||
| // if([0, 1].includes(item.shopState)){ | |||
| // api = 'createOrderTwo' | |||
| // }else{ | |||
| api = 'createSumOrderAgain' | |||
| // } | |||
| this.$api(api, { | |||
| orderId : item.id, | |||
| addressId : item.addressId | |||
| }, res => { | |||
| if(res.code == 200){ | |||
| uni.requestPaymentWxPay(res) | |||
| .then(res => { | |||
| uni.showToast({ | |||
| title: '支付成功', | |||
| icon: 'none' | |||
| }) | |||
| this.getData() | |||
| }).catch(n => { | |||
| this.getData() | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| // 确认收货 | |||
| confirmOrder(item){ | |||
| uni.showModal({ | |||
| title: '您收到货了吗?', | |||
| success : e => { | |||
| if(e.confirm){ | |||
| this.$api('confirmOrder', { | |||
| orderId : item.id, | |||
| }, res => { | |||
| this.getData() | |||
| }) | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| // 取消订单 | |||
| cancelOrder(item){ | |||
| uni.showModal({ | |||
| title: '确认取消订单吗?', | |||
| success : e => { | |||
| if(e.confirm){ | |||
| this.$api('cancelOrder', { | |||
| orderId : item.id, | |||
| }, res => { | |||
| this.getData() | |||
| }) | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| @ -0,0 +1,20 @@ | |||
| { | |||
| "name": "uniapp-project-templates", | |||
| "version": "1.0.0", | |||
| "description": "{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}", | |||
| "main": "main.js", | |||
| "scripts": { | |||
| "test": "echo \"Error: no test specified\" && exit 1" | |||
| }, | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "https://gitee.com/huliyong/uniapp-project-templates.git" | |||
| }, | |||
| "keywords": [], | |||
| "author": "", | |||
| "license": "ISC", | |||
| "dependencies": { | |||
| "ali-oss": "^6.21.0", | |||
| "dayjs": "^1.11.12" | |||
| } | |||
| } | |||
| @ -0,0 +1,84 @@ | |||
| { | |||
| "pages": [{ | |||
| "path": "pages/index/index", | |||
| "style": { | |||
| "navigationBarTitleText": "" | |||
| } | |||
| }, | |||
| { | |||
| "path": "pages/index/order", | |||
| "style": { | |||
| "navigationBarTitleText": "" | |||
| } | |||
| }, | |||
| { | |||
| "path": "pages/index/category", | |||
| "style": { | |||
| "navigationBarTitleText": "" | |||
| } | |||
| }, | |||
| { | |||
| "path": "pages/index/center", | |||
| "style": { | |||
| "navigationBarTitleText": "" | |||
| } | |||
| }, | |||
| { | |||
| "path": "pages/index/cart", | |||
| "style": { | |||
| "navigationBarTitleText": "" | |||
| } | |||
| } | |||
| ], | |||
| "preloadRule": { | |||
| "pages/index/index": { | |||
| "network": "all", | |||
| "packages": ["pages_order"] | |||
| } | |||
| }, | |||
| "subPackages": [{ | |||
| "root": "pages_order", | |||
| "pages": [{ | |||
| "path": "order/orderDetail" | |||
| }, | |||
| { | |||
| "path": "mine/purse" | |||
| }, | |||
| { | |||
| "path": "mine/runningWater" | |||
| }, | |||
| { | |||
| "path": "mine/address" | |||
| }, | |||
| { | |||
| "path": "product/productDetail" | |||
| }, | |||
| { | |||
| "path": "order/refundsOrExchange" | |||
| }, | |||
| { | |||
| "path": "auth/wxLogin" | |||
| }, | |||
| { | |||
| "path": "auth/wxUserInfo" | |||
| }, | |||
| { | |||
| "path": "auth/loginAndRegisterAndForgetPassword" | |||
| }, | |||
| { | |||
| "path": "mine/help" | |||
| }, | |||
| { | |||
| "path": "mine/promotion" | |||
| } | |||
| ] | |||
| }], | |||
| "globalStyle": { | |||
| "navigationBarTextStyle": "black", | |||
| "navigationBarTitleText": "酒店桌布", | |||
| "navigationBarBackgroundColor": "#F8F8F8", | |||
| "backgroundColor": "#F8F8F8", | |||
| "navigationStyle": "custom" | |||
| }, | |||
| "uniIdRouter": {} | |||
| } | |||
| @ -0,0 +1,260 @@ | |||
| <template> | |||
| <view class="page"> | |||
| <navbar/> | |||
| <view class="user"> | |||
| <uv-checkbox-group | |||
| shape="circle" | |||
| v-model="checkboxValue"> | |||
| <uv-swipe-action> | |||
| <view | |||
| v-for="(item, index) in list" | |||
| :key="index"> | |||
| <view style="margin-top: 20rpx;"></view> | |||
| <uv-swipe-action-item | |||
| :options="options"> | |||
| <view class="item"> | |||
| <view class="checkbox"> | |||
| <uv-checkbox | |||
| :name="item.id" | |||
| activeColor="#FA5A0A" | |||
| size="40rpx" | |||
| icon-size="35rpx" | |||
| ></uv-checkbox> | |||
| </view> | |||
| <image | |||
| class="image" | |||
| src="https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg" | |||
| mode=""></image> | |||
| <view class="info"> | |||
| <view class="title"> | |||
| <view class=""> | |||
| {{ item.title }} | |||
| </view> | |||
| <view class=""> | |||
| <uv-number-box v-model="item.num" | |||
| @change="valChange"></uv-number-box> | |||
| </view> | |||
| </view> | |||
| <view class="unit"> | |||
| 规格:{{ item.unit }} | |||
| <uv-icon name="arrow-down"></uv-icon> | |||
| </view> | |||
| <view class="price"> | |||
| ¥<text>{{ item.price }}</text>元 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </uv-swipe-action-item> | |||
| </view> | |||
| </uv-swipe-action> | |||
| </uv-checkbox-group> | |||
| <view class="action"> | |||
| <view class="icon"> | |||
| <image src="/static/image/cart/1.png" mode=""></image> | |||
| <view class="num"> | |||
| {{ checkboxValue.length }} | |||
| </view> | |||
| </view> | |||
| <view class="price"> | |||
| <view class="count"> | |||
| 合计 | |||
| <view class=""> | |||
| ¥<text>{{ totalPrice }}</text> | |||
| </view> | |||
| </view> | |||
| <view class="text"> | |||
| 共{{ checkboxValue.length }}件,已享受更低优惠 | |||
| </view> | |||
| </view> | |||
| <view class="btn"> | |||
| 去结算 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <tabber select="cart" /> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import tabber from '@/components/base/tabbar.vue' | |||
| export default { | |||
| components: { | |||
| tabber, | |||
| }, | |||
| data() { | |||
| return { | |||
| value : 0, | |||
| checkboxValue : [], | |||
| options: [ | |||
| { | |||
| text: '删除', | |||
| style: { | |||
| backgroundColor: '#FA5A0A' | |||
| } | |||
| }, | |||
| ], | |||
| list : [ | |||
| { | |||
| id : 1, | |||
| title : '桌布租赁', | |||
| num : 1, | |||
| price : 299, | |||
| unit : '120*40*75【桌子尺寸】', | |||
| }, | |||
| { | |||
| id : 2, | |||
| title : '桌布租赁', | |||
| num : 1, | |||
| price : 299, | |||
| unit : '120*40*75【桌子尺寸】', | |||
| }, | |||
| ], | |||
| } | |||
| }, | |||
| computed: { | |||
| totalPrice(){ | |||
| if (!this.checkboxValue.length) { | |||
| return 0 | |||
| } | |||
| let price = 0 | |||
| this.list.forEach(n => { | |||
| if(this.checkboxValue.includes(n.id)){ | |||
| price += n.price * n.num | |||
| } | |||
| }) | |||
| return price | |||
| }, | |||
| }, | |||
| methods: { | |||
| valChange(){ | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .page { | |||
| padding-bottom: 200rpx; | |||
| /deep/ .uv-swipe-action{ | |||
| width: 100%; | |||
| } | |||
| } | |||
| .user { | |||
| .item{ | |||
| background-color: #fff; | |||
| display: flex; | |||
| padding: 30rpx; | |||
| .checkbox{ | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| .image{ | |||
| width: 200rpx; | |||
| height: 200rpx; | |||
| border-radius: 20rpx; | |||
| } | |||
| .info{ | |||
| flex: 1; | |||
| .title{ | |||
| display: flex; | |||
| padding: 10rpx 20rpx; | |||
| justify-content: space-between; | |||
| } | |||
| .unit{ | |||
| font-size: 24rpx; | |||
| padding: 10rpx 20rpx; | |||
| color: #717171; | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| .price{ | |||
| color: $uni-color; | |||
| font-size: 28rpx; | |||
| padding: 10rpx 20rpx; | |||
| text{ | |||
| font-size: 36rpx; | |||
| font-weight: 900; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .action{ | |||
| width: 700rpx; | |||
| position: fixed; | |||
| bottom: 220rpx; | |||
| left: 25rpx; | |||
| background-color: #fff; | |||
| height: 100rpx; | |||
| border-radius: 50rpx; | |||
| box-shadow: 0 0 6rpx 6rpx #00000010; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| overflow: hidden; | |||
| z-index: 999; | |||
| .icon{ | |||
| position: relative; | |||
| width: 80rpx; | |||
| height: 80rpx; | |||
| margin: 0 20rpx; | |||
| image{ | |||
| width: 80rpx; | |||
| height: 80rpx; | |||
| } | |||
| .num{ | |||
| position: absolute; | |||
| right: 10rpx; | |||
| top: 0rpx; | |||
| background-color: $uni-color; | |||
| color: #fff; | |||
| font-size: 18rpx; | |||
| border-radius: 50%; | |||
| height: 30rpx; | |||
| width: 30rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| } | |||
| .price{ | |||
| .count{ | |||
| display: flex; | |||
| font-size: 26rpx; | |||
| align-items: center; | |||
| view{ | |||
| color: $uni-color; | |||
| margin-left: 10rpx; | |||
| text{ | |||
| font-size: 32rpx; | |||
| font-weight: 900; | |||
| } | |||
| } | |||
| } | |||
| .text{ | |||
| font-size: 20rpx; | |||
| color: #717171; | |||
| } | |||
| } | |||
| .btn{ | |||
| margin-left: auto; | |||
| background-color: $uni-color; | |||
| height: 100%; | |||
| padding: 0 50rpx; | |||
| color: #fff; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,191 @@ | |||
| <template> | |||
| <view class="page"> | |||
| <navbar/> | |||
| <view class="category"> | |||
| <uv-vtabs | |||
| :chain="chain" | |||
| :list="category" | |||
| height="1000px" | |||
| :barItemBadgeStyle="{right:'20px',top:'12px'}" | |||
| @change="change"> | |||
| <uv-vtabs-item> | |||
| <view class="category-title"> | |||
| 租赁 | |||
| </view> | |||
| <view class="list"> | |||
| <view class="item" v-for="(item,index) in list" :key="index" | |||
| @click="$utils.navigateTo('/pages_order/product/productDetail?id=123')"> | |||
| <view class="item-image"> | |||
| <image | |||
| :src="item.image" | |||
| mode="aspectFill"></image> | |||
| </view> | |||
| <view class="item-unit"> | |||
| <text class="text">{{item.unit}}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </uv-vtabs-item> | |||
| </uv-vtabs> | |||
| </view> | |||
| <tabber select="category" /> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import tabber from '@/components/base/tabbar.vue' | |||
| export default { | |||
| components: { | |||
| tabber, | |||
| }, | |||
| data() { | |||
| return { | |||
| category: [ | |||
| { | |||
| name : '桌布' | |||
| }, | |||
| { | |||
| name : '桌布' | |||
| }, | |||
| { | |||
| name : '桌布' | |||
| }, | |||
| ], | |||
| list : [ | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| { | |||
| unit : '100*50*60', | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| }, | |||
| ], | |||
| chain: false, | |||
| value: 0 | |||
| } | |||
| }, | |||
| computed: { | |||
| list2() { | |||
| const _list = this.list[this.value]?.childrens; | |||
| return _list ? _list : []; | |||
| } | |||
| }, | |||
| onReady() { | |||
| }, | |||
| methods: { | |||
| change(index) { | |||
| console.log('选项改变:', index) | |||
| this.value = index; | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .page{ | |||
| /deep/ .uv-vtabs{ | |||
| height: calc(100vh - 360rpx) !important; | |||
| } | |||
| /deep/ .uv-vtabs__bar{ | |||
| height: calc(100vh - 360rpx) !important; | |||
| } | |||
| /deep/ .uv-vtabs__content{ | |||
| height: calc(100vh - 360rpx) !important; | |||
| } | |||
| } | |||
| .category { | |||
| font-size: 30rpx; | |||
| color: #333; | |||
| .category-title{ | |||
| position: relative; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| height: 120rpx; | |||
| &::before, | |||
| &::after { | |||
| position: absolute; | |||
| top: 50%; | |||
| content: ''; | |||
| width: 10%; | |||
| border-top: 2rpx solid black; | |||
| } | |||
| &::before { | |||
| left: 25%; | |||
| } | |||
| &::after { | |||
| right: 25%; | |||
| } | |||
| } | |||
| .list{ | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| margin: 0 auto; | |||
| width: 490rpx; | |||
| .item { | |||
| padding: 10rpx 20rpx; | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: center; | |||
| align-items: center; | |||
| margin-bottom: 20rpx; | |||
| .item-image { | |||
| width: 120rpx; | |||
| height: 120rpx; | |||
| image{ | |||
| height: 100%; | |||
| width: 100%; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| .item-unit { | |||
| font-size: 24rpx; | |||
| margin-top: 15rpx; | |||
| color: #555; | |||
| } | |||
| } | |||
| .gap { | |||
| padding: 0 30rpx; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,353 @@ | |||
| <template> | |||
| <view class="page"> | |||
| <navbar title="个人中心" /> | |||
| <view class="head"> | |||
| <view class="headImage"> | |||
| <image src="" mode=""></image> | |||
| </view> | |||
| <view class="info"> | |||
| <view class="name"> | |||
| 倾心. | |||
| </view> | |||
| <!-- <view class="vip"> | |||
| VIP1 | |||
| </view> --> | |||
| <view class="tips"> | |||
| 今天是您来的的第32天 | |||
| </view> | |||
| </view> | |||
| <!-- <view class="headBtn" @click="headBtn"> | |||
| 角色切换 | |||
| </view> --> | |||
| <view class="setting"> | |||
| <uv-icon name="setting" size="40rpx"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 水洗店 --> | |||
| <view class="userShop" v-if="userShop"> | |||
| <userShopCommission /> | |||
| <view class="userList"> | |||
| <view class="title"> | |||
| 我的用户 | |||
| </view> | |||
| <view class="list"> | |||
| <view class="item" v-for="(item, index) in 20" :key="index"> | |||
| <view class="name"> | |||
| 客户:王生 | |||
| </view> | |||
| <view class="num"> | |||
| 剩余水洗布:198 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 酒店 --> | |||
| <view class="user" v-else> | |||
| <view class="line"> | |||
| <view class="item"> | |||
| <view class="image"> | |||
| <image src="/static/image/center/1.png" mode=""></image> | |||
| </view> | |||
| <view class=""> | |||
| 余额¥3000 | |||
| </view> | |||
| </view> | |||
| <view class="item"> | |||
| <view class="image"> | |||
| <image src="/static/image/center/4.png" mode=""></image> | |||
| </view> | |||
| <view class=""> | |||
| 押金¥30000 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="line grid"> | |||
| <view class="title"> | |||
| 常用功能 | |||
| </view> | |||
| <uv-grid :col="4" :border="false"> | |||
| <uv-grid-item @click="$utils.navigateTo('/pages_order/mine/address')"> | |||
| <image class="image" src="/static/image/center/7.png" mode=""></image> | |||
| <text class="grid-text">地址管理</text> | |||
| </uv-grid-item> | |||
| <uv-grid-item @click="$utils.redirectTo('/index/order')"> | |||
| <image class="image" src="/static/image/center/8.png" mode=""></image> | |||
| <text class="grid-text">订单管理</text> | |||
| </uv-grid-item> | |||
| <uv-grid-item @click="$utils.navigateTo('/pages_order/order/refundsOrExchange?index='+0)"> | |||
| <image class="image" src="/static/image/center/5.png" mode=""></image> | |||
| <text class="grid-text">换货</text> | |||
| </uv-grid-item> | |||
| <uv-grid-item @click="$utils.navigateTo('/pages_order/order/refundsOrExchange?index='+1)"> | |||
| <image class="image" src="/static/image/center/7.png" mode=""></image> | |||
| <text class="grid-text">退货</text> | |||
| </uv-grid-item> | |||
| </uv-grid> | |||
| </view> | |||
| <view class="line grid"> | |||
| <uv-grid :col="4" :border="false"> | |||
| <uv-grid-item @click="contactUs"> | |||
| <image class="image" src="/static/image/center/9.png" mode=""></image> | |||
| <text class="grid-text">联系客服</text> | |||
| </uv-grid-item> | |||
| <uv-grid-item> | |||
| <image class="image" src="/static/image/center/6.png" mode=""></image> | |||
| <text class="grid-text">我的租赁</text> | |||
| </uv-grid-item> | |||
| <uv-grid-item @click="$utils.redirectTo('/index/cart')"> | |||
| <image class="image" src="/static/image/center/7.png" mode=""></image> | |||
| <text class="grid-text">租赁车</text> | |||
| </uv-grid-item> | |||
| <uv-grid-item | |||
| @click="$utils.navigateTo('/pages_order/auth/loginAndRegisterAndForgetPassword?index='+2)"> | |||
| <image class="image" src="/static/image/center/7.png" mode=""></image> | |||
| <text class="grid-text">申请成为水洗店</text> | |||
| </uv-grid-item> | |||
| </uv-grid> | |||
| </view> | |||
| </view> | |||
| <tabber select="center" /> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import tabber from '@/components/base/tabbar.vue' | |||
| import { | |||
| mapGetters | |||
| } from 'vuex' | |||
| import userShopCommission from '@/components/userShop/userShopCommission.vue' | |||
| export default { | |||
| components: { | |||
| tabber, | |||
| userShopCommission, | |||
| }, | |||
| computed: { | |||
| ...mapGetters(['userShop']), | |||
| }, | |||
| data() { | |||
| return { | |||
| } | |||
| }, | |||
| methods: { | |||
| headBtn() { | |||
| let self = this | |||
| uni.showModal({ | |||
| title: '演示切换角色之后的效果', | |||
| success(res) { | |||
| if (res.confirm) { | |||
| self.$store.state.shop = !self.$store.state.shop | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .page { | |||
| .warp { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| height: 100%; | |||
| } | |||
| .rect { | |||
| width: 600rpx; | |||
| height: 300rpx; | |||
| background-color: #fff; | |||
| border-radius: 20rpx; | |||
| overflow: hidden; | |||
| .title { | |||
| padding: 10rpx 0 0 15rpx; | |||
| background-color: #fd5100; | |||
| color: #FFF; | |||
| text-align: left; | |||
| width: 100%; | |||
| height: 18%; | |||
| font-size: 36rpx; | |||
| } | |||
| .center { | |||
| height: 40%; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| font-size: 36rpx; | |||
| } | |||
| .bottom { | |||
| display: flex; | |||
| justify-content: center; | |||
| gap: 50rpx; | |||
| } | |||
| } | |||
| } | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| .head { | |||
| display: flex; | |||
| background-color: #fff; | |||
| padding: 40rpx 20rpx; | |||
| align-items: center; | |||
| position: relative; | |||
| .headImage { | |||
| width: 120rpx; | |||
| height: 120rpx; | |||
| background-image: url(/static/image/center/3.png); | |||
| background-size: 100% 100%; | |||
| overflow: hidden; | |||
| border-radius: 50%; | |||
| margin-right: 40rpx; | |||
| } | |||
| .info { | |||
| font-size: 28rpx; | |||
| .vip { | |||
| background-color: #FCCC92; | |||
| color: #FA6239; | |||
| width: 100rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| height: 40rpx; | |||
| border-radius: 20rpx; | |||
| margin-top: 20rpx; | |||
| } | |||
| .name { | |||
| font-size: 32rpx; | |||
| } | |||
| .tips { | |||
| font-size: 26rpx; | |||
| color: #ABABAB; | |||
| } | |||
| } | |||
| .headBtn { | |||
| margin-left: auto; | |||
| padding: 15rpx 20rpx; | |||
| background-color: $uni-color; | |||
| color: #fff; | |||
| border-radius: 20rpx; | |||
| margin-top: 50rpx; | |||
| } | |||
| .setting { | |||
| position: absolute; | |||
| right: 50rpx; | |||
| top: 50rpx; | |||
| } | |||
| } | |||
| .userShop { | |||
| .userList { | |||
| .title { | |||
| font-size: 32rpx; | |||
| font-weight: 900; | |||
| padding: 20rpx; | |||
| } | |||
| .list { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| .item { | |||
| width: 270rpx; | |||
| margin: 20rpx; | |||
| display: flex; | |||
| flex-direction: column; | |||
| padding: 40rpx 30rpx; | |||
| background-color: #fff; | |||
| border-radius: 30rpx; | |||
| line-height: 60rpx; | |||
| .name {} | |||
| .num { | |||
| color: $uni-color; | |||
| font-weight: 600; | |||
| font-size: 28rpx; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .user { | |||
| .line { | |||
| display: flex; | |||
| background-color: #fff; | |||
| margin-top: 20rpx; | |||
| padding: 20rpx 0; | |||
| .item { | |||
| flex: 1; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| padding: 20rpx 0; | |||
| &:nth-child(1) { | |||
| border-right: 1px solid #00000013; | |||
| } | |||
| .image { | |||
| width: 100rpx; | |||
| height: 70rpx; | |||
| margin-right: 20rpx; | |||
| } | |||
| } | |||
| } | |||
| .grid { | |||
| flex-direction: column; | |||
| font-size: 26rpx; | |||
| padding: 20rpx; | |||
| .title { | |||
| margin-bottom: 30rpx; | |||
| font-size: 28rpx; | |||
| font-weight: 600; | |||
| } | |||
| .image { | |||
| width: 70rpx; | |||
| height: 70rpx; | |||
| margin-bottom: 10rpx; | |||
| } | |||
| text { | |||
| text-align: center; | |||
| width: 120rpx; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,412 @@ | |||
| <template> | |||
| <view class="page"> | |||
| <navbar/> | |||
| <view class="search"> | |||
| <view @click="showSelectArea" class="left-area"> | |||
| <image src="@/static/image/home/address-icon.png"></image> | |||
| <view class="area">{{ area }}</view> | |||
| <image src="@/static/image/home/arrow-icon.png" mode="aspectFit"></image> | |||
| <view class="parting-line">|</view> | |||
| </view> | |||
| <view class="center-area"> | |||
| <image | |||
| style="margin-right: 20rpx;" | |||
| src="@/static/image/home/search-icon.png"></image> | |||
| <input v-model="queryParams.title" | |||
| placeholder="桌布租赁" /> | |||
| </view> | |||
| <!-- <view class="right-area"> | |||
| <view @click="searchAddress" class="search-button"> | |||
| 搜索 | |||
| </view> | |||
| </view> --> | |||
| </view> | |||
| <view class="swipe"> | |||
| <uv-swiper | |||
| :list="bannerList" | |||
| indicator | |||
| height="320rpx" | |||
| keyName="url"></uv-swiper> | |||
| </view> | |||
| <!-- 水洗店 --> | |||
| <view class="userShop" | |||
| v-if="userShop"> | |||
| <view class="list"> | |||
| <view class="item" | |||
| v-for="(item, index) in 4" | |||
| :key="index"> | |||
| <view class=""> | |||
| <view class=""> | |||
| 我的客户 | |||
| </view> | |||
| <view class="num"> | |||
| {{ 30 }} | |||
| </view> | |||
| </view> | |||
| <view class=""> | |||
| <image :src="`/static/image/home/${index}.png`" mode=""></image> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 酒店 --> | |||
| <view class="user" | |||
| v-else> | |||
| <uv-notice-bar | |||
| fontSize="28rpx" | |||
| :text="text"></uv-notice-bar> | |||
| <view class="shop"> | |||
| <image | |||
| class="image" | |||
| src="https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg" | |||
| mode=""></image> | |||
| <view class="shopInfo"> | |||
| <view class="title"> | |||
| HOUS水洗店 | |||
| </view> | |||
| <view class="tags"> | |||
| <view class="tag"> | |||
| 桌布水洗 | |||
| </view> | |||
| <view class="tag"> | |||
| 桌布租赁 | |||
| </view> | |||
| </view> | |||
| <view class="time"> | |||
| 9:00-18:00 | |||
| </view> | |||
| <view class="address"> | |||
| 长沙市天心区桂花坪街道231号 | |||
| </view> | |||
| </view> | |||
| <view class="btns"> | |||
| <view class="btn" | |||
| @click="$utils.navigateTo('/pages_order/auth/wxUserInfo')"> | |||
| 我要水洗 | |||
| </view> | |||
| </view> | |||
| <view class="tips"> | |||
| 关联门店:主信门店 | |||
| </view> | |||
| </view> | |||
| <view class="productList"> | |||
| <productList/> | |||
| </view> | |||
| </view> | |||
| <!-- <selectArea ref="selectArea" @close="closeAreaPro" @select="selectArea"></selectArea> --> | |||
| <PrivacyAgreementPoup/> | |||
| <tabber select="home"/> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import PrivacyAgreementPoup from '@/components/config/PrivacyAgreementPoup.vue' | |||
| import Position from '@/utils/position.js' | |||
| import tabber from '@/components/base/tabbar.vue' | |||
| import productList from '@/components/user/productList.vue' | |||
| import { mapGetters } from 'vuex' | |||
| // import selectArea from '../../components/selectArea.vue'; | |||
| export default { | |||
| components : { | |||
| tabber, | |||
| productList, | |||
| PrivacyAgreementPoup, | |||
| }, | |||
| data() { | |||
| return { | |||
| area: '长沙', | |||
| text : '长沙市刘师傅在服务过程中客户投诉“服务过程中有不文明的行为”.....', | |||
| queryParams: { | |||
| pageNo: 1, | |||
| pageSize: 10, | |||
| title: '' | |||
| }, | |||
| bannerList: [ | |||
| { | |||
| url: 'https://cdn.uviewui.com/uview/swiper/swiper3.png', | |||
| }, | |||
| { | |||
| url: 'https://cdn.uviewui.com/uview/swiper/swiper2.png', | |||
| }, | |||
| { | |||
| url: 'https://cdn.uviewui.com/uview/swiper/swiper3.png', | |||
| }, | |||
| ], | |||
| productList: [], | |||
| } | |||
| }, | |||
| computed : { | |||
| ...mapGetters(['userShop']), | |||
| }, | |||
| methods: { | |||
| //显示选择地区 | |||
| showSelectArea() { | |||
| // this.$refs.selectArea.open() | |||
| }, | |||
| //搜索地址 | |||
| searchAddress() { | |||
| Position.getLocation(res => { | |||
| Position.selectAddress(res.longitude, res.latitude, success => { | |||
| let address = this.extractProvinceAndCity(success) | |||
| this.queryParams.title = address.city | |||
| }) | |||
| }) | |||
| }, | |||
| //提取用户选择的地址信息(省市县信息) | |||
| extractProvinceAndCity(res) { //提取用户选择的地址信息(省市) | |||
| if (!res.address && res.name) { //用户直接选择城市的逻辑 | |||
| return { | |||
| province: '', | |||
| city: res.name | |||
| }; | |||
| } | |||
| if (res.address) { //用户选择了详细地址,要从详细地址中提取出省市县信息 | |||
| // 使用正则表达式匹配省市县 | |||
| const regex = /(?<province>[\u4e00-\u9fa5]+?省)(?<city>[\u4e00-\u9fa5]+?(?:市|自治州|盟|地区))/; | |||
| const match = res.address.match(regex); | |||
| if (match) { // 如果匹配成功,则返回省和市的信息 | |||
| return { | |||
| province: match.groups.province, | |||
| city: match.groups.city | |||
| }; | |||
| } | |||
| } | |||
| return { //用户没选择地址就点了确定按钮 | |||
| province: '', | |||
| city: '' | |||
| } | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .search { | |||
| height: 82rpx; | |||
| width: 710rpx; | |||
| background: #FFFFFF; | |||
| margin: 20rpx auto; | |||
| border-radius: 41rpx; | |||
| box-sizing: border-box; | |||
| padding: 0 15rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| // justify-content: space-between; | |||
| .left-area, | |||
| .center-area { | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| .left-area { | |||
| max-width: 160rpx; | |||
| image { | |||
| flex-shrink: 0; | |||
| width: 26rpx; | |||
| height: 26rpx; | |||
| } | |||
| .area { | |||
| font-size: 24rpx; | |||
| display: -webkit-box; | |||
| -webkit-line-clamp: 2; | |||
| /* 限制显示两行 */ | |||
| -webkit-box-orient: vertical; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| color: #292929; | |||
| } | |||
| .parting-line { | |||
| flex-shrink: 0; | |||
| font-size: 26rpx; | |||
| color: #ccc; | |||
| margin: 0rpx 5rpx; | |||
| } | |||
| } | |||
| .center-area { | |||
| display: flex; | |||
| flex-wrap: nowrap; | |||
| align-items: center; | |||
| width: calc(100% - 290rpx); | |||
| margin-left: 30rpx; | |||
| image { | |||
| width: 26rpx; | |||
| height: 26rpx; | |||
| } | |||
| .van-field { | |||
| background-color: transparent; | |||
| box-sizing: border-box; | |||
| height: 82rpx; | |||
| line-height: 82rpx; | |||
| width: calc(100% - 30rpx); | |||
| padding: 0rpx 10rpx 0rpx 0rpx; | |||
| input { | |||
| height: 82rpx; | |||
| font-size: 60rpx; | |||
| } | |||
| } | |||
| } | |||
| .right-area { | |||
| .search-button { | |||
| background: #60BDA2; | |||
| height: 60rpx; | |||
| width: 130rpx; | |||
| font-size: 26rpx; | |||
| border-radius: 35rpx; | |||
| color: white; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| } | |||
| } | |||
| } | |||
| .swipe{ | |||
| overflow: hidden; | |||
| border-radius: 20rpx; | |||
| margin: 20rpx; | |||
| } | |||
| .page{ | |||
| & /deep/ .uv-icon__icon{ | |||
| font-size: 30rpx !important; | |||
| } | |||
| // 水洗店 | |||
| .userShop{ | |||
| .list{ | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| .item{ | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| width: 330rpx; | |||
| margin: 20rpx; | |||
| padding: 30rpx 0; | |||
| color: #FFFFFF; | |||
| line-height: 50rpx; | |||
| border-radius: 20rpx; | |||
| font-size: 28rpx; | |||
| .num{ | |||
| font-size: 38rpx; | |||
| font-weight: 900; | |||
| } | |||
| image{ | |||
| width: 110rpx; | |||
| height: 110rpx; | |||
| margin-left: 20rpx; | |||
| } | |||
| &:nth-child(1){ | |||
| background: #F07A77; | |||
| } | |||
| &:nth-child(2){ | |||
| background: #F48B4E; | |||
| } | |||
| &:nth-child(3){ | |||
| background: #6487E1; | |||
| } | |||
| &:nth-child(4){ | |||
| background: #61B7E6; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 酒店 | |||
| .user{ | |||
| padding: 20rpx; | |||
| .shop{ | |||
| position: relative; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| background-color: #fff; | |||
| margin-top: 20rpx; | |||
| border-radius: 20rpx; | |||
| padding: 20rpx; | |||
| overflow: hidden; | |||
| .image{ | |||
| width: 180rpx; | |||
| height: 180rpx; | |||
| margin-right: 20rpx; | |||
| border-radius: 20rpx; | |||
| } | |||
| .shopInfo{ | |||
| font-size: 22rpx; | |||
| .title{ | |||
| font-size: 30rpx; | |||
| } | |||
| .tags{ | |||
| display: flex; | |||
| .tag{ | |||
| padding: 4rpx 6rpx; | |||
| border: 1rpx solid #FFAC6E; | |||
| color: #FFAC6E; | |||
| margin-right: 10rpx; | |||
| margin-top: 10rpx; | |||
| font-size: 18rpx; | |||
| } | |||
| } | |||
| .time{ | |||
| margin-top: 10rpx; | |||
| display: flex; | |||
| } | |||
| .address{ | |||
| margin-top: 10rpx; | |||
| display: flex; | |||
| } | |||
| } | |||
| .btns{ | |||
| margin-left: auto; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| .btn{ | |||
| background-color: $uni-color; | |||
| color: #fff; | |||
| box-shadow: 0 0 5rpx 5rpx #FFAC6E; | |||
| padding: 10rpx 20rpx; | |||
| flex-shrink: 0; | |||
| border-radius: 35rpx; | |||
| } | |||
| } | |||
| .tips{ | |||
| position: absolute; | |||
| top: 0; | |||
| right: 0; | |||
| font-size: 24rpx; | |||
| color: #FFAC6E; | |||
| background-color: #FEF5EE; | |||
| padding: 10rpx 20rpx; | |||
| border-radius: 10rpx; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,263 @@ | |||
| <template> | |||
| <view class="page"> | |||
| <navbar | |||
| title="订单中心" | |||
| /> | |||
| <uv-tabs :list="tabs" | |||
| :activeStyle="{color : '#FD5100', fontWeight : 600}" | |||
| lineColor="#FD5100" | |||
| lineHeight="8rpx" | |||
| lineWidth="50rpx" | |||
| @click="clickTabs"></uv-tabs> | |||
| <view v-if="orderList.length > 0" class="list"> | |||
| <view class="item" | |||
| v-for="(item, index) in orderList.records" | |||
| @click="toOrderDetail(item.id)" | |||
| :key="index"> | |||
| <view class="top"> | |||
| <view class="service"> | |||
| <text>{{item.projectId_dictText}}</text> | |||
| <text>{{item.type_dictText}}</text> | |||
| </view> | |||
| <view class="status"> | |||
| <text> {{item.state_dictText}}</text> | |||
| </view> | |||
| </view> | |||
| <view class="content"> | |||
| <view class="left"> | |||
| <image mode="aspectFill" :src="item.image"></image> | |||
| </view> | |||
| <view class="right"> | |||
| <view class="text-hidden-1"> | |||
| 客户姓名:{{item.name}} | |||
| </view> | |||
| <view class="text-hidden-1"> | |||
| 产品规格:{{item.unit}} | |||
| </view> | |||
| <view class="text-hidden-1"> | |||
| 租赁地址:{{item.address}} | |||
| </view> | |||
| <!-- <view class="text-hidden-1"> | |||
| 总计时间:{{item.useTime}}分钟 | |||
| </view> --> | |||
| </view> | |||
| </view> | |||
| <view class="bottom"> | |||
| <view class="price"> | |||
| 总价格:<text class="num">{{item.money}}元</text> | |||
| </view> | |||
| <view class="b1"> | |||
| 查看物流 | |||
| </view> | |||
| <!-- <view @click.stop="toPayOrder(item)" class="b2" v-if="item.state == 0"> | |||
| 立即付款 | |||
| </view> | |||
| <view class="b1" @click.stop="moreOrder(item.projectId,toPlaceorder)" v-if="item.state == 3"> | |||
| 再来一单 | |||
| </view> | |||
| <view class="b2" @click.stop="toEvaluate(item.id,item.projectId,item.technicianId)" v-if="item.state == 3"> | |||
| 立即评价 | |||
| </view> | |||
| <view class="b2" @click.stop="moreOrder(item.projectId,toPlaceorder)" v-if="item.state == 4"> | |||
| 再来一单 | |||
| </view> --> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <tabber select="order"/> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import tabber from '@/components/base/tabbar.vue' | |||
| import { mapGetters } from 'vuex' | |||
| export default { | |||
| components : { | |||
| tabber, | |||
| }, | |||
| computed : { | |||
| ...mapGetters(['userShop']), | |||
| }, | |||
| data() { | |||
| return { | |||
| tabs: [{ | |||
| name: '全部' | |||
| }, | |||
| { | |||
| name: '租赁押金' | |||
| }, | |||
| { | |||
| name: '水洗租赁' | |||
| }, | |||
| { | |||
| name: '破损换货' | |||
| }, | |||
| { | |||
| name: '退货退款' | |||
| } | |||
| ], | |||
| queryParams: { | |||
| pageNo: 1, | |||
| pageSize: 10 | |||
| }, | |||
| // orderList: [ | |||
| // { | |||
| // money : 99.99, | |||
| // address : '广东省广州市越秀区城南故事C3栋2802', | |||
| // name : '李**', | |||
| // phone : '150*****091', | |||
| // unit : '120*40*75【桌子尺寸】', | |||
| // image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| // state_dictText : '已完成', | |||
| // } | |||
| // ], //订单列表数据 | |||
| orderList : { | |||
| records : [], | |||
| total : 0, | |||
| }, | |||
| state : -1, | |||
| } | |||
| }, | |||
| onShow() { | |||
| this.orderPage() | |||
| }, | |||
| //滚动到屏幕底部 | |||
| onReachBottom() { | |||
| if(this.queryParams.pageSize < this.orderList.total){ | |||
| this.queryParams.pageSize += 10 | |||
| this.orderPage() | |||
| } | |||
| }, | |||
| methods: { | |||
| orderPage(){ | |||
| let queryParams = { | |||
| ...this.queryParams, | |||
| } | |||
| if(this.state != -1){ | |||
| queryParams.state = this.state | |||
| } | |||
| this.$api('orderPage', queryParams, res => { | |||
| if(res.code == 200){ | |||
| this.orderList = res.result | |||
| } | |||
| }) | |||
| }, | |||
| //点击tab栏 | |||
| clickTabs(index) { | |||
| if (index == 0) { | |||
| this.state = -1; | |||
| } else { | |||
| this.state = index - 1; | |||
| } | |||
| this.queryParams.pageSize = 10 | |||
| this.orderPage() | |||
| }, | |||
| //跳转订单详情页面 | |||
| toOrderDetail(id) { | |||
| uni.navigateTo({ | |||
| url: '/pages_order/order/orderDetail?id=' + id | |||
| }) | |||
| }, | |||
| getOrderList(){ | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .page{ | |||
| } | |||
| .list { | |||
| .item { | |||
| width: calc(100% - 40rpx); | |||
| background-color: #fff; | |||
| margin: 20rpx; | |||
| box-sizing: border-box; | |||
| border-radius: 16rpx; | |||
| padding: 30rpx; | |||
| .top { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| font-size: 30rpx; | |||
| .service {} | |||
| .status { | |||
| font-size: 26rpx; | |||
| font-weight: 600; | |||
| } | |||
| } | |||
| .content { | |||
| display: flex; | |||
| margin: 10rpx 0; | |||
| .left { | |||
| width: 150rpx; | |||
| height: 150rpx; | |||
| border-radius: 10rpx; | |||
| image { | |||
| width: 150rpx; | |||
| height: 150rpx; | |||
| border-radius: 10rpx; | |||
| } | |||
| } | |||
| .right { | |||
| width: calc(100% - 160rpx); | |||
| color: #777; | |||
| font-size: 24rpx; | |||
| padding-left: 20rpx; | |||
| line-height: 40rpx; | |||
| background-color: #F8F8F8; | |||
| } | |||
| } | |||
| .bottom { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| font-size: 25rpx; | |||
| .price { | |||
| font-weight: 900; | |||
| text { | |||
| color: #ff780099; | |||
| font-size: 30rpx; | |||
| } | |||
| } | |||
| .b1 { | |||
| border: 1px solid #777; | |||
| color: #777; | |||
| box-sizing: border-box; | |||
| } | |||
| .b2 { | |||
| background: linear-gradient(178deg, #4FD3BC, #60C285); | |||
| color: #fff; | |||
| } | |||
| view { | |||
| margin: 12rpx; | |||
| border-radius: 28rpx; | |||
| padding: 8rpx 28rpx; | |||
| margin-bottom: 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,514 @@ | |||
| <template> | |||
| <view class="refundsOrExchange"> | |||
| <navbar :title="titleList[titleIndex]" leftClick | |||
| @leftClick="$utils.redirectTo('/pages/index/index')" /> | |||
| <view class="frame"> | |||
| <!-- 注册 --> | |||
| <view class='forgetPassword' v-if='titleIndex == 0'> | |||
| <!-- 标题 --> | |||
| <view class="title">{{titleList[titleIndex]}}</view> | |||
| <!-- 表单 --> | |||
| <view class="form1"> | |||
| <view class="userName"> | |||
| <uv-input v-model="form1.username" placeholder="请输入手机号" border="surround" shape='circle' | |||
| clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view class="code"> | |||
| <view class="left"> | |||
| <uv-input v-model="form1.captcha" placeholder="请输入验证码" border="surround" shape='circle' | |||
| clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view class="right"> | |||
| <view> | |||
| <uv-toast ref="toast"></uv-toast> | |||
| <uv-code :seconds="seconds" @end="end" @start="start" ref="code" | |||
| @change="codeChange"></uv-code> | |||
| <uv-button @tap="getCode" iconSize='10rpx' color='#1f1c39' | |||
| shape='circle'>{{tips}}</uv-button> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="password1"> | |||
| <uv-input v-model="form1.password" placeholder="设置您的新密码(6到50个字符)" password clearable | |||
| border="surround" shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view class="password2"> | |||
| <uv-input v-model="form1.newPassword" placeholder="重新确认密码" password clearable border="surround" | |||
| shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| </view> | |||
| <view> | |||
| <uv-checkbox-group v-model="checkboxValue" shape="circle"> | |||
| <view class="content"> | |||
| <view style="display: flex;"> | |||
| <uv-checkbox size="30rpx" :name="1"></uv-checkbox> | |||
| 请你阅读并同意我们的<span style="color: #fd5100" | |||
| @click="$refs.popup.open('getPrivacyPolicy')">《隐私条款》</span>和<span | |||
| style="color: #fd5100" | |||
| @click="$refs.popup.open('getUserAgreement')">《服务协议》</span> | |||
| </view> | |||
| </view> | |||
| </uv-checkbox-group> | |||
| </view> | |||
| </view> | |||
| <!-- 登录 --> | |||
| <view class="loginRegister" v-if='titleIndex==1'> | |||
| <!-- 标题 --> | |||
| <view class="title">{{titleList[titleIndex]}}</view> | |||
| <!-- 头像 --> | |||
| <view class="userIamge"> | |||
| <view> | |||
| <img src="/static/image/center/11.svg" alt="" style="width: 100%;height: 100%;"> | |||
| </view> | |||
| </view> | |||
| <!-- 用户名&密码&隐私条款 --> | |||
| <view class="form"> | |||
| <view> | |||
| <uv-input v-model="form.username" placeholder="请输入账号" border="surround" shape='circle' clearable | |||
| :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view> | |||
| <uv-input v-model="form.password" password placeholder="请输入密码" border="surround" shape='circle' | |||
| clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view> | |||
| <uv-checkbox-group v-model="checkboxValue" shape="circle"> | |||
| <view class="content"> | |||
| <view style="display: flex;"> | |||
| <uv-checkbox size="30rpx" :name="1"></uv-checkbox> | |||
| 请你阅读并同意我们的<span style="color: #fd5100" | |||
| @click="$refs.popup.open('yszc')">《隐私条款》</span>和<span | |||
| style="color: #fd5100" | |||
| @click="$refs.popup.open('fwxy')">《服务协议》</span> | |||
| </view> | |||
| </view> | |||
| </uv-checkbox-group> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 忘记密码 --> | |||
| <view class='forgetPassword' v-if='titleIndex == 2'> | |||
| <!-- 标题 --> | |||
| <view class="title">{{titleList[titleIndex]}}</view> | |||
| <!-- 表单 --> | |||
| <view class="form1"> | |||
| <view class="userName"> | |||
| <uv-input v-model="form1.username" placeholder="请输入手机号" border="surround" shape='circle' | |||
| clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view class="code"> | |||
| <view class="left"> | |||
| <uv-input v-model="form1.captcha" placeholder="请输入验证码" border="surround" shape='circle' | |||
| clearable :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view class="right"> | |||
| <view> | |||
| <uv-toast ref="toast"></uv-toast> | |||
| <uv-code :seconds="seconds" @end="end" @start="start" ref="code" | |||
| @change="codeChange"></uv-code> | |||
| <uv-button @tap="getCode" iconSize='10rpx' color='#1f1c39' | |||
| shape='circle'>{{tips}}</uv-button> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="password1"> | |||
| <uv-input v-model="form1.password" placeholder="设置您的新密码(6到50个字符)" password clearable | |||
| border="surround" shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| <view class="password2"> | |||
| <uv-input v-model="form1.newPassword" placeholder="重新确认密码" password clearable border="surround" | |||
| shape='circle' :customStyle="{ backgroundColor: '#f6f6f6'}"></uv-input> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 按钮 --> | |||
| <view class="btn" @click="submit"> | |||
| <button class='a'>{{titleList[titleIndex]}}</button> | |||
| </view> | |||
| <!-- tab --> | |||
| <view class="bottomTab"> | |||
| <span :class="titleIndex==0 ? 'tabbarItemActive' : 'tabbarItemNoActive'" | |||
| @click='changePage(0)'>注册账号</span> | |||
| <span style="color: #9c9fa4">|</span> | |||
| <span :class="titleIndex==1 ? 'tabbarItemActive' : 'tabbarItemNoActive'" | |||
| @click='changePage(1)'>账号登录</span> | |||
| <span style="color: #9c9fa4">|</span> | |||
| <span :class="titleIndex==2 ? 'tabbarItemActive' : 'tabbarItemNoActive'" | |||
| @click='changePage(2)'>忘记密码</span> | |||
| </view> | |||
| </view> | |||
| <configPopup ref="popup"></configPopup> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import configPopup from '@/components/config/configPopup.vue'; | |||
| export default { | |||
| components: { | |||
| configPopup | |||
| }, | |||
| onLoad(option) { | |||
| this.titleIndex = option.index || 1 | |||
| }, | |||
| data() { | |||
| return { | |||
| titleIndex: 0, | |||
| titleList: ['注册', '登录', '重置密码'], | |||
| checkboxValue: [], | |||
| form: { | |||
| username: '',//19330214982 | |||
| password: '',//1234567 | |||
| loginModel: 0, | |||
| captcha: '', | |||
| }, | |||
| form1: { | |||
| username: '', | |||
| captcha: '', | |||
| password: '', | |||
| newPassword: '', | |||
| }, | |||
| tips: '获取验证码', | |||
| seconds: 60, | |||
| } | |||
| }, | |||
| methods: { | |||
| submit() { | |||
| if (!this.checkboxValue.length && this.titleIndex != 2) { | |||
| return uni.showToast({ | |||
| title: '请先同意隐私协议', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| if (this.titleIndex == 0) { | |||
| // 注册 | |||
| this.register() | |||
| } else if (this.titleIndex == 1) { | |||
| // 登录 | |||
| this.login() | |||
| } else { | |||
| // 忘记密码 | |||
| this.updatePassword() | |||
| } | |||
| }, | |||
| // 登录 | |||
| login(){ | |||
| if (this.$utils.verificationAll(this.form, { | |||
| username: '请输入账号', | |||
| password: '请输入密码', | |||
| })) { | |||
| return | |||
| } | |||
| if (!this.$utils.verificationPhone(this.form.username)) { | |||
| return uni.showToast({ | |||
| title: '请输入合法的手机号', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| // 登录 | |||
| this.$store.commit('login', this.form) | |||
| }, | |||
| // 注册 | |||
| register(){ | |||
| if (this.$utils.verificationAll(this.form1, { | |||
| username: '请输入账号', | |||
| captcha : '请输入验证码', | |||
| password: '请输入密码', | |||
| newPassword: '请确认密码', | |||
| })) { | |||
| return | |||
| } | |||
| if (!this.$utils.verificationPhone(this.form1.username)) { | |||
| return uni.showToast({ | |||
| title: '请输入合法的手机号', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| if (this.form1.password != this.form1.newPassword) { | |||
| return uni.showToast({ | |||
| title: '密码与确认密码不一致', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| this.$api('registerUser', this.form1, res => { | |||
| this.form1 = {} | |||
| if (res.code == 200) { | |||
| this.titleIndex = 1 | |||
| uni.showToast({ | |||
| title: '注册成功,请登录!', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| updatePassword(){ | |||
| if (this.$utils.verificationAll(this.form1, { | |||
| username: '请输入账号', | |||
| captcha : '请输入验证码', | |||
| password: '请输入新密码', | |||
| newPassword: '请确认密码', | |||
| })) { | |||
| return | |||
| } | |||
| if (!this.$utils.verificationPhone(this.form1.username)) { | |||
| return uni.showToast({ | |||
| title: '请输入合法的手机号', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| if (this.form1.password != this.form1.newPassword) { | |||
| return uni.showToast({ | |||
| title: '密码与确认密码不一致', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| this.$api('newPassword', this.form1, res => { | |||
| this.form1 = {} | |||
| if (res.code == 200) { | |||
| this.titleIndex = 1 | |||
| uni.showToast({ | |||
| title: '修改成功,请登录!', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| // 切换页面 | |||
| changePage(index) { | |||
| this.titleIndex = index | |||
| }, | |||
| confirm() { | |||
| }, | |||
| codeChange(text) { | |||
| this.tips = text; | |||
| }, | |||
| getCode() { | |||
| if (this.$refs.code.canGetCode) { | |||
| if (!this.$utils.verificationPhone(this.form1.username)) { | |||
| return uni.showToast({ | |||
| title: '请输入合法的手机号', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| uni.showLoading({ | |||
| title: '正在获取验证码' | |||
| }) | |||
| this.$api('sendSms', { | |||
| username: this.form1.username, | |||
| }, res => { | |||
| if (res.code == 200) { | |||
| uni.hideLoading(); | |||
| // 这里此提示会被this.start()方法中的提示覆盖 | |||
| uni.$uv.toast('验证码已发送'); | |||
| // 通知验证码组件内部开始倒计时 | |||
| this.$refs.code.start(); | |||
| } | |||
| }) | |||
| } else { | |||
| uni.$uv.toast('请勿重复发送'); | |||
| } | |||
| }, | |||
| end() { | |||
| // uni.$uv.toast('倒计时结束'); | |||
| }, | |||
| start() { | |||
| // uni.$uv.toast('倒计时开始'); | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| * { | |||
| box-sizing: border-box; | |||
| } | |||
| .content{ | |||
| font-size: 22rpx; | |||
| margin: 0 auto; | |||
| } | |||
| .refundsOrExchange { | |||
| background-color: #FFF; | |||
| height: 100vh; | |||
| .frame { | |||
| background-color: #FFF; | |||
| .loginRegister { | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 40rpx; | |||
| padding-bottom: 50rpx; | |||
| .title { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: flex-end; | |||
| height: 10vh; | |||
| color: #000; | |||
| font-size: 40rpx; | |||
| font-weight: 700; | |||
| } | |||
| .userIamge { | |||
| display: flex; | |||
| justify-content: center; | |||
| height: 10vh; | |||
| >view:nth-of-type(1) { | |||
| width: 25%; | |||
| height: 100%; | |||
| border-radius: 50%; | |||
| overflow: hidden; | |||
| } | |||
| } | |||
| .form { | |||
| height: 12vh; | |||
| >view:nth-of-type(1) { | |||
| padding: 20rpx 100rpx; | |||
| } | |||
| >view:nth-of-type(2) { | |||
| padding: 0 100rpx; | |||
| } | |||
| >view:nth-of-type(3) { | |||
| display: flex; | |||
| padding: 30rpx 100rpx 0 100rpx; | |||
| font-size: 22rpx; | |||
| } | |||
| } | |||
| } | |||
| .btn { | |||
| // height: 5vh; | |||
| display: flex; | |||
| justify-content: center; | |||
| margin: 90rpx 0 0 0; | |||
| .a { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| width: 70%; | |||
| height: 80rpx; | |||
| color: #FFF; | |||
| background-color: $uni-color; | |||
| box-shadow: 0 0 4rpx 4rpx rgba($uni-color, 0.2); | |||
| border-radius: 100rpx; | |||
| font-size: 30rpx; | |||
| } | |||
| } | |||
| .bottomTab { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| height: 10vh; | |||
| padding: 0 80rpx; | |||
| margin-top: 30rpx; | |||
| .tabbarItemActive { | |||
| color: $uni-color; | |||
| } | |||
| .tabbarItemNoActive { | |||
| color: #9c9fa4; | |||
| } | |||
| } | |||
| .forgetPassword { | |||
| padding: 100rpx 40rpx 0 40rpx; | |||
| .title { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: flex-end; | |||
| height: 10vh; | |||
| color: #000; | |||
| font-size: 40rpx; | |||
| font-weight: 700; | |||
| } | |||
| .form1 { | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 30rpx; | |||
| margin-top: 20rpx; | |||
| padding: 20rpx 80rpx; | |||
| .userName { | |||
| // padding: 20rpx 100 rpx; | |||
| } | |||
| .code { | |||
| display: flex; | |||
| width: 100%; | |||
| .left { | |||
| width: 55%; | |||
| } | |||
| .right { | |||
| width: 45%; | |||
| height: 100%; | |||
| >view:nth-of-type(1) { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| width: 100%; | |||
| } | |||
| } | |||
| } | |||
| .password1 {} | |||
| .password2 {} | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,155 @@ | |||
| <template> | |||
| <view class="login"> | |||
| <view class="logo"> | |||
| <!-- <image src="/static/image/login/logo.png" mode=""></image> --> | |||
| </view> | |||
| <view class="title"> | |||
| 欢迎使用酒店桌布租赁平台 | |||
| </view> | |||
| <view class="btn mt" | |||
| @click="wxLogin"> | |||
| <view class="icon"> | |||
| <image src="../static/auth/wx.png" mode=""></image> | |||
| </view> | |||
| <view class=""> | |||
| 微信授权登录 | |||
| </view> | |||
| </view> | |||
| <!-- <view class="btn b2"> | |||
| 使用短信验证登录 | |||
| </view> --> | |||
| <view class="btn b2" | |||
| @click="qux"> | |||
| 取消登录 | |||
| </view> | |||
| <view class="config"> | |||
| <uv-checkbox-group | |||
| v-model="checkboxValue" | |||
| shape="circle"> | |||
| <view class="content"> | |||
| <view | |||
| style="display: flex;"> | |||
| <uv-checkbox | |||
| size="40rpx" | |||
| icon-size="30rpx" | |||
| activeColor="#FD5100" | |||
| :name="1" | |||
| ></uv-checkbox> | |||
| 阅读并同意我们的<text @click="$refs.popup.open('getPrivacyPolicy')">“服务协议与隐私条款”</text> | |||
| </view> | |||
| <view class=""> | |||
| 以及<text @click="$refs.popup.open('getUserAgreement')">个人信息保护指引</text> | |||
| </view> | |||
| </view> | |||
| </uv-checkbox-group> | |||
| </view> | |||
| <configPopup ref="popup"></configPopup> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name : 'Login', | |||
| data() { | |||
| return { | |||
| checkboxValue : [] | |||
| } | |||
| }, | |||
| methods: { | |||
| wxLogin(){ | |||
| if(!this.checkboxValue.length){ | |||
| return uni.showToast({ | |||
| title: '请先同意隐私协议', | |||
| icon:'none' | |||
| }) | |||
| } | |||
| this.$store.commit('login') | |||
| }, | |||
| qux(){ | |||
| uni.reLaunch({ | |||
| url: '/pages/index/index' | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .login{ | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| height: 80vh; | |||
| flex-direction: column; | |||
| position: relative; | |||
| .logo{ | |||
| height: 140rpx; | |||
| width: 140rpx; | |||
| background-color: #ddd; | |||
| border-radius: 30rpx; | |||
| image{ | |||
| height: 140rpx; | |||
| width: 140rpx; | |||
| border-radius: 30rpx; | |||
| } | |||
| margin-bottom: 20rpx; | |||
| } | |||
| .title{ | |||
| position: relative; | |||
| font-weight: 900; | |||
| font-size: 45rpx; | |||
| &::after{ | |||
| content: ''; | |||
| position: absolute; | |||
| left: 0; | |||
| top: 100%; | |||
| display: block; | |||
| height: 8rpx; | |||
| width: 210rpx; | |||
| background: linear-gradient(to right,$uni-color, #fff); | |||
| } | |||
| } | |||
| .btn{ | |||
| width: 80%; | |||
| height: 100rpx; | |||
| background-color: $uni-color; | |||
| color: #fff; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| margin: 20rpx 0; | |||
| border-radius: 20rpx; | |||
| .icon{ | |||
| margin-right: 10rpx; | |||
| image{ | |||
| width: 40rpx; | |||
| height: 35rpx; | |||
| } | |||
| } | |||
| } | |||
| .b2{ | |||
| background-color: rgba($uni-color, 0.2); | |||
| color: $uni-color; | |||
| } | |||
| .mt{ | |||
| margin-top: 200rpx; | |||
| } | |||
| .config{ | |||
| position: absolute; | |||
| bottom: 0; | |||
| font-size: 24rpx; | |||
| text-align: center; | |||
| line-height: 40rpx; | |||
| text{ | |||
| color: $uni-color; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,133 @@ | |||
| <template> | |||
| <view class="login"> | |||
| <view class="title"> | |||
| 酒店桌布租赁平台 | |||
| </view> | |||
| <view class="title"> | |||
| 申请获取你的头像、昵称 | |||
| </view> | |||
| <button class="chooseAvatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"> | |||
| <view class="line"> | |||
| <view class=""> | |||
| 头像 | |||
| </view> | |||
| <view class=""> | |||
| <image :src="userInfo.headImage" v-if="userInfo.headImage" style="width: 60rpx;height: 60rpx;" | |||
| mode=""></image> | |||
| <image src="../static/auth/headImage.png" v-else style="width: 50rpx;height: 50rpx;" mode=""></image> | |||
| </view> | |||
| </view> | |||
| </button> | |||
| <view class="line"> | |||
| <view class=""> | |||
| 昵称 | |||
| </view> | |||
| <view class=""> | |||
| <input type="nickname" placeholder="请输入昵称" style="text-align: right;" id="nickName" | |||
| v-model="userInfo.nickName" /> | |||
| </view> | |||
| </view> | |||
| <view class="btn" @click="submit"> | |||
| 确认 | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| userInfo: { | |||
| headImage: '', | |||
| nickName: '', | |||
| } | |||
| }; | |||
| }, | |||
| onShow() {}, | |||
| computed: {}, | |||
| methods: { | |||
| onChooseAvatar(res) { | |||
| let self = this | |||
| self.$Oss.ossUpload(res.target.avatarUrl) | |||
| .then(url => { | |||
| self.userInfo.headImage = url | |||
| }) | |||
| }, | |||
| submit() { | |||
| let self = this | |||
| uni.createSelectorQuery().in(this) | |||
| .select("#nickName") | |||
| .fields({ | |||
| properties: ["value"], | |||
| }) | |||
| .exec((res) => { | |||
| const nickName = res?.[0]?.value | |||
| self.userInfo.nickName = nickName | |||
| if (self.$utils.verificationAll(self.userInfo, { | |||
| headImage: '请选择头像', | |||
| nickName: '请填写昵称', | |||
| })) { | |||
| return | |||
| } | |||
| self.$api('updateInfo', self.userInfo, res => { | |||
| if (res.code == 200) { | |||
| uni.switchTab({ | |||
| url:'/pages/index/index' | |||
| }) | |||
| } | |||
| }) | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .login { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: center; | |||
| align-items: center; | |||
| height: 80vh; | |||
| .title { | |||
| line-height: 45rpx; | |||
| font-weight: 900; | |||
| } | |||
| .line { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| width: 80%; | |||
| border-bottom: 1px solid #00000023; | |||
| padding: 30rpx 0; | |||
| margin: 0 auto; | |||
| } | |||
| .chooseAvatar { | |||
| width: 100%; | |||
| padding: 0; | |||
| margin: 0; | |||
| margin-top: 10vh; | |||
| border: none; | |||
| } | |||
| .btn { | |||
| // background: $uni-linear-gradient-btn-color; | |||
| background: $uni-color; | |||
| color: #fff; | |||
| width: 80%; | |||
| padding: 20rpx 0; | |||
| text-align: center; | |||
| border-radius: 15rpx; | |||
| margin-top: 10vh; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,244 @@ | |||
| <template> | |||
| <scroll-view | |||
| scroll-y="true" | |||
| :style="{height: height}" | |||
| @scrolltolower="moreAddress"> | |||
| <uv-radio-group v-model="selectAddress" | |||
| @change="editDefault" | |||
| v-if="addressList.length > 0"> | |||
| <view v-for="item in addressList" :key="item.id" class="address-item"> | |||
| <view class="address-item-top" | |||
| @click="select(item)"> | |||
| <view class="img-box"> | |||
| <image src="../../static/address/icon.png" mode="aspectFill"></image> | |||
| </view> | |||
| <view class="address-info"> | |||
| <view class="user-info"> | |||
| <text class="user-name">{{ item.name }}</text> | |||
| <text class="user-phone">{{ item.phone }}</text> | |||
| <text v-if="item.defaultFlag == 1" class="is-default">默认</text> | |||
| </view> | |||
| <view class="address-detail"> | |||
| {{ item.address + " " + item.addressDetail }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="controls" | |||
| v-if="controls"> | |||
| <view class="default-checkbox"> | |||
| <uv-radio | |||
| :name="item.id" | |||
| label-disabled | |||
| size="30rpx" | |||
| icon-size="30rpx"> | |||
| 默认地址 | |||
| </uv-radio> | |||
| </view> | |||
| <view class="edit-btn"> | |||
| <uv-icon name="edit-pen"></uv-icon> | |||
| <text @click="editAddress(item)" class="control-title">编辑</text> | |||
| </view> | |||
| <view class="del-btn"> | |||
| <uv-icon name="trash"></uv-icon> | |||
| <text class="control-title" @click="deleteAddress(item.id)">删除</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </uv-radio-group> | |||
| <view | |||
| style="padding: 100rpx 0;" | |||
| v-else> | |||
| <uv-empty | |||
| mode="history" | |||
| textSize="28rpx" | |||
| iconSize="100rpx"/> | |||
| </view> | |||
| </scroll-view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| props : { | |||
| controls : { | |||
| default : false, | |||
| type : Boolean, | |||
| }, | |||
| height : { | |||
| default : 'calc(90vh - 180rpx)' | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| selectAddress : 0, | |||
| queryParams: { | |||
| pageNo: 1, | |||
| pageSize: 10, | |||
| }, | |||
| addressList: [], | |||
| total : 0, | |||
| } | |||
| }, | |||
| methods: { | |||
| //获取地址列表 | |||
| getAddressList() { | |||
| return new Promise((success, fail) => { | |||
| this.$api('addressPage', this.queryParams, res => { | |||
| if (res.code == 200) { | |||
| this.addressList = res.result.records || []; | |||
| this.total = res.result.total || 0; | |||
| res.result.records.forEach(n => { //筛选默认地址 | |||
| if (n.defaultFlag == 1) { | |||
| this.selectAddress = n.id | |||
| } | |||
| }) | |||
| success(res.result) | |||
| } | |||
| }) | |||
| }) | |||
| }, | |||
| // 加载更多 | |||
| moreAddress(){ | |||
| if(this.queryParams.pageSize > this.total){ | |||
| return | |||
| } | |||
| this.queryParams.pageSize += 10 | |||
| this.getAddressList() | |||
| }, | |||
| // 删除地址 | |||
| deleteAddress(e){ | |||
| this.$emit('deleteAddress', e) | |||
| }, | |||
| // 修改地址 | |||
| editAddress(e){ | |||
| this.$emit('editAddress', e) | |||
| }, | |||
| // 切换默认地址 | |||
| editDefault(e){ | |||
| this.$emit('editDefault', e) | |||
| }, | |||
| // 选择了地址 | |||
| select(e){ | |||
| this.$emit('select', e) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .address-item { | |||
| background: white; | |||
| border-radius: 20rpx; | |||
| overflow: hidden; | |||
| margin-bottom: 20rpx; | |||
| padding: 15rpx 15rpx 0rpx 15rpx; | |||
| width: 680rpx; | |||
| .address-item-top { | |||
| border-bottom: 1px dashed #D3D1D1; | |||
| display: flex; | |||
| align-items: center; | |||
| padding: 0rpx 0rpx 15rpx 0rpx; | |||
| .img-box { | |||
| width: 120rpx; | |||
| height: 120rpx; | |||
| image { | |||
| width: 75%; | |||
| height: 75%; | |||
| display: block; | |||
| margin: 12.5% auto; | |||
| } | |||
| } | |||
| .address-info { | |||
| width: calc(100% - 120rpx); | |||
| height: 100%; | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-between; | |||
| .user-info { | |||
| display: flex; | |||
| align-items: center; | |||
| text { | |||
| display: block; | |||
| line-height: 40rpx; | |||
| margin-right: 20rpx; | |||
| } | |||
| .user-name, | |||
| .user-phone { | |||
| font-size: 30rpx; | |||
| } | |||
| .is-default { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| background: #FEB773; | |||
| color: white; | |||
| width: 80rpx; | |||
| height: 35rpx; | |||
| border-radius: 20rpx; | |||
| font-size: 22rpx; | |||
| } | |||
| } | |||
| .address-detail { | |||
| color: #4a4a4a; | |||
| font-size: 26rpx; | |||
| overflow: hidden; | |||
| display: -webkit-box; | |||
| -webkit-box-orient: vertical; | |||
| -webkit-line-clamp: 2; | |||
| text-overflow: ellipsis; | |||
| } | |||
| } | |||
| } | |||
| .controls { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| font-size: 26rpx; | |||
| padding: 15rpx 15rpx 25rpx 15rpx; | |||
| .default-checkbox { | |||
| display: flex; | |||
| text { | |||
| margin-left: 8rpx; | |||
| } | |||
| } | |||
| .control-title { | |||
| height: 30rpx; | |||
| line-height: 30rpx; | |||
| color: #666666; | |||
| } | |||
| view { | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| image { | |||
| width: 23rpx; | |||
| height: 23rpx; | |||
| vertical-align: middle; | |||
| margin-right: 8rpx; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,220 @@ | |||
| <template> | |||
| <uv-popup round="40rpx" ref="addressPopup" :customStyle="{ height: 'auto' , width : '100%' , padding : '20rpx'}"> | |||
| <view class="redact-address"> | |||
| <view class="redact-address-title">{{title}}</view> | |||
| <uv-form label-width="210rpx" :model="addressDetail" ref="form"> | |||
| <uv-form-item label="联系人" prop="name"> | |||
| <uv-input v-model="addressDetail.name" placeholder="请输入联系人姓名" border="none"> | |||
| </uv-input> | |||
| </uv-form-item> | |||
| <uv-form-item label="手机号" prop="phone"> | |||
| <uv-input v-model="addressDetail.phone" placeholder="请输入手机号" border="none"> | |||
| </uv-input> | |||
| </uv-form-item> | |||
| <uv-form-item label="所在地区" prop="address"> | |||
| <uv-input v-model="addressDetail.address" placeholder="请选择所在地区" border="none"> | |||
| </uv-input> | |||
| <template #right> | |||
| <view style="padding-right: 40rpx;color: #FBAB32;" @click.stop="selectAddr"> | |||
| <image src="../../static/address/selectIcon.png" mode="aspectFit"></image>定位 | |||
| </view> | |||
| </template> | |||
| </uv-form-item> | |||
| <uv-form-item label="详细地址" prop="addressDetail"> | |||
| <uv-input v-model="addressDetail.addressDetail" placeholder="请输入详细地址" border="none"> | |||
| </uv-input> | |||
| </uv-form-item> | |||
| </uv-form> | |||
| <view @click="onSubmit" class="save">{{ addressDetail.id ? '修改地址' : '新增地址'}}</view> | |||
| </view> | |||
| </uv-popup> | |||
| </template> | |||
| <script> | |||
| import Position from '@/utils/position.js' | |||
| export default { | |||
| data() { | |||
| return { | |||
| addressDetail: {} | |||
| } | |||
| }, | |||
| props: { | |||
| title: { | |||
| type: String, | |||
| default: '新增地址' | |||
| } | |||
| }, | |||
| methods: { | |||
| open(addressDetail) { | |||
| this.addressDetail = addressDetail | |||
| this.$refs.addressPopup.open('bottom') | |||
| }, | |||
| close(){ | |||
| this.$refs.addressPopup.close() | |||
| }, | |||
| //新增和修改地址 | |||
| onSubmit() { | |||
| let isOk = this.parameterVerification(this.addressDetail) | |||
| if (isOk && !isOk.auth) { | |||
| return uni.showToast({ | |||
| icon: 'none', | |||
| title: isOk.title, | |||
| 'zIndex': 10000 | |||
| }) | |||
| } | |||
| this.$emit('saveOrUpdate', this.addressDetail) | |||
| }, | |||
| //验证用户参数合法性 | |||
| parameterVerification(addressDetaila) { | |||
| let { | |||
| name, | |||
| phone, | |||
| address, | |||
| addressDetail | |||
| } = addressDetaila | |||
| if (name.trim() == '') { | |||
| return { | |||
| title: '请填写联系人', | |||
| auth: false | |||
| } | |||
| } else if (phone.trim() == '') { | |||
| return { | |||
| title: '请填写手机号', | |||
| auth: false | |||
| } | |||
| } else if (address.trim() == '') { | |||
| return { | |||
| title: '请填写所在地区', | |||
| auth: false | |||
| } | |||
| } else if (addressDetail.trim() == '') { | |||
| return { | |||
| title: '请填写详细地址', | |||
| auth: false | |||
| } | |||
| } else if (phone.trim() != '') { | |||
| if (!this.$utils.verificationPhone(phone)) { | |||
| return { | |||
| title: '手机号格式不合法', | |||
| auth: false | |||
| } | |||
| } | |||
| } | |||
| return { | |||
| title: '验证通过', | |||
| auth: true | |||
| } | |||
| }, | |||
| //地图上选择地址 | |||
| selectAddr() { | |||
| Position.getLocation(res => { | |||
| Position.selectAddress(res.longitude, res.latitude, success => { | |||
| this.setAddress(success) | |||
| }) | |||
| }) | |||
| }, | |||
| //提取用户选择的地址信息复制给表单数据 | |||
| setAddress(res) { | |||
| //经纬度信息 | |||
| this.addressDetail.latitude = res.latitude | |||
| this.addressDetail.longitude = res.longitude | |||
| if (!res.address && res.name) { //用户直接选择城市的逻辑 | |||
| return this.addressDetail.address = res.name | |||
| } | |||
| if (res.address || res.name) { | |||
| return this.addressDetail.address = res.address + res.name | |||
| } | |||
| this.addressDetail.address = '' //用户啥都没选就点击勾选 | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .redact-address { | |||
| box-sizing: border-box; | |||
| .redact-address-title { | |||
| height: 80rpx; | |||
| line-height: 80rpx; | |||
| font-size: 30rpx; | |||
| color: #333333; | |||
| font-weight: 600; | |||
| } | |||
| .save { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| width: 90%; | |||
| height: 80rpx; | |||
| border-radius: 40rpx; | |||
| color: white; | |||
| font-size: 28rpx; | |||
| margin: 0rpx auto; | |||
| background: $uni-color; | |||
| margin-top: 150rpx; | |||
| } | |||
| image { | |||
| width: 25rpx; | |||
| height: 25rpx; | |||
| } | |||
| //修改组件默认样式 | |||
| .uv-form { | |||
| padding: 30rpx 0rpx; | |||
| } | |||
| &::v-deep .uv-cell { | |||
| padding: 0rpx 0rpx; | |||
| font-size: 26rpx; | |||
| &::after { | |||
| border: none !important; | |||
| } | |||
| .uv-field__label { | |||
| display: flex; | |||
| align-items: center; | |||
| height: 80rpx; | |||
| } | |||
| .uv-field__control, | |||
| .uv-field__right-icon { | |||
| height: 80rpx; | |||
| font-size: 26rpx; | |||
| border-bottom: 2rpx solid #cbc8c8; | |||
| } | |||
| .uv-field__right-icon { | |||
| display: flex; | |||
| align-items: center; | |||
| height: 78rpx; | |||
| color: #5FCC9F; | |||
| } | |||
| .uv-cell__value { | |||
| height: 120rpx; | |||
| } | |||
| } | |||
| &::v-deep .uv-field__error-message { | |||
| color: #5AC796; | |||
| font-size: 20rpx; | |||
| margin-top: 10rpx; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,77 @@ | |||
| <template> | |||
| <view class="submit"> | |||
| <view class="" | |||
| @click="$emit('share')"> | |||
| <uv-icon | |||
| size="40rpx" | |||
| name="share-square"></uv-icon> | |||
| <view class=""> | |||
| 分享 | |||
| </view> | |||
| </view> | |||
| <view class="" | |||
| @click="$utils.navigateTo('/index/cart')"> | |||
| <uv-icon | |||
| size="40rpx" | |||
| name="shopping-cart"></uv-icon> | |||
| <view class=""> | |||
| 购物车 | |||
| </view> | |||
| </view> | |||
| <view class="btn" | |||
| @click="$emit('submit')"> | |||
| {{ submiitTitle }} | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name:"submit", | |||
| props : { | |||
| submiitTitle : { | |||
| default : '立即租赁', | |||
| type : String, | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| } | |||
| }, | |||
| methods: { | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .submit{ | |||
| position: fixed; | |||
| bottom: 0; | |||
| left: 0; | |||
| width: 100vw; | |||
| background-color: #fff; | |||
| height: 100rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| font-size: 24rpx; | |||
| .btn{ | |||
| background: $uni-color; | |||
| width: 600rpx; | |||
| height: 80rpx; | |||
| color: #fff; | |||
| border-radius: 40rpx; | |||
| font-size: 28rpx; | |||
| } | |||
| view{ | |||
| width: 100rpx; | |||
| margin: 0 10rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| flex-direction: column; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,367 @@ | |||
| <template> | |||
| <uv-popup ref="popup" | |||
| :round="30" | |||
| bgColor="#f7f7f7"> | |||
| <view class="content"> | |||
| <!-- 地址 --> | |||
| <view class="address" | |||
| @click="openAddress"> | |||
| <image src="../../static/address/selectIcon.png" mode=""></image> | |||
| <view class=""> | |||
| {{ address.name }} | |||
| </view> | |||
| <view class=""> | |||
| {{ address.addressDetail }} | |||
| </view> | |||
| <view class="icon"> | |||
| <uv-icon | |||
| size="30rpx" | |||
| name="arrow-right"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 商品信息和数量 --> | |||
| <view class="submit-info"> | |||
| <view class="title"> | |||
| 桌布租赁 | |||
| </view> | |||
| <view class="box"> | |||
| <image | |||
| class="image" | |||
| :src="unit.pic" | |||
| mode=""></image> | |||
| <view class="info"> | |||
| <view class="price"> | |||
| ¥<text>{{ unit.depositPrice }}</text>元 | |||
| </view> | |||
| <view class="unit"> | |||
| 请选择规格 | |||
| </view> | |||
| <view class=""> | |||
| <uv-number-box v-model="num"></uv-number-box> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 规格 --> | |||
| <view class="submit-unit"> | |||
| <view class="title"> | |||
| 规格选择 | |||
| </view> | |||
| <view class="list"> | |||
| <view :class="{act : unitIndex == index}" | |||
| v-for="(item, index) in detail.hotelGoodsSkuList" | |||
| @click="selectUnit(item, index)" | |||
| :key="index"> | |||
| {{ item.title }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 费用明细 --> | |||
| <view class="expense-detail"> | |||
| <view class="title"> | |||
| 费用明细 | |||
| </view> | |||
| <view class="detail"> | |||
| 押金:¥{{ unit.depositPrice }} | |||
| </view> | |||
| </view> | |||
| <!-- 提交按钮 --> | |||
| <view class="submit-btn"> | |||
| <view class="l" | |||
| @click="addCart"> | |||
| 加入租赁车 | |||
| </view> | |||
| <view class="r" | |||
| @click="orderPay"> | |||
| {{ submiitTitle }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <uv-popup ref="addressPopup" :round="30"> | |||
| <addressList | |||
| ref="addressList" | |||
| height="60vh" | |||
| @select="selectAddress" | |||
| /> | |||
| </uv-popup> | |||
| </uv-popup> | |||
| </template> | |||
| <script> | |||
| import addressList from '../address/addressList.vue' | |||
| export default { | |||
| components : { | |||
| addressList, | |||
| }, | |||
| props : { | |||
| submiitTitle : { | |||
| default : '立即租赁', | |||
| type : String, | |||
| }, | |||
| detail : { | |||
| default : {} | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| unitIndex : 0, | |||
| address : { | |||
| name : '请选择联系人', | |||
| addressDetail : '', | |||
| }, | |||
| num : 1, | |||
| unit : {}, | |||
| addressTotal : 0, | |||
| } | |||
| }, | |||
| methods: { | |||
| // 打开 | |||
| open(){ | |||
| this.$refs.popup.open('bottom') | |||
| if(!this.unit.id){ | |||
| this.selectUnit(this.detail.hotelGoodsSkuList[0], 0) | |||
| } | |||
| // 获取地址列表 | |||
| this.$refs.addressList.getAddressList().then(res => { | |||
| this.addressTotal = res.total | |||
| if(this.addressTotal != 0){ | |||
| this.address = res.records[0] | |||
| } | |||
| }) | |||
| }, | |||
| // 关闭 | |||
| close(){ | |||
| this.$refs.popup.close() | |||
| }, | |||
| // 打开选择地址 | |||
| openAddress(){ | |||
| if (this.addressTotal == 0) { | |||
| this.$refs.popup.close() | |||
| return uni.navigateTo({ | |||
| url: '/pages_order/mine/address?type=back' | |||
| }) | |||
| } | |||
| this.$refs.addressPopup.open('bottom') | |||
| }, | |||
| // 选择地址 | |||
| selectAddress(e){ | |||
| this.address = e | |||
| this.$refs.addressPopup.close() | |||
| }, | |||
| // 选择规格 | |||
| selectUnit(item, index){ | |||
| this.unit = item | |||
| this.unitIndex = index | |||
| }, | |||
| addCart(){ | |||
| this.$api('cartAdd', { | |||
| id : this.detail.id, | |||
| skuId : this.unit.id, | |||
| }, res => { | |||
| if(res.code == 200){ | |||
| uni.showToast({ | |||
| title: '添加成功', | |||
| }); | |||
| this.$refs.popup.close() | |||
| } | |||
| }) | |||
| }, | |||
| orderPay(){ | |||
| let data = { | |||
| id : this.detail.id,//商品id | |||
| skuId : this.unit.id,//规格id | |||
| addressId : this.address.id,//地址id | |||
| sku : this.unit.title,//规格 | |||
| num : this.num, | |||
| } | |||
| if(this.$utils.verificationAll(data, { | |||
| skuId : '请选择规格', | |||
| addressId : '请选择地址', | |||
| })){ | |||
| return | |||
| } | |||
| this.$api('orderPay', data, res => { | |||
| if(res.code == 200){ | |||
| uni.redirectTo({ | |||
| url: '/pages/index/order' | |||
| }) | |||
| // uni.requestPayment({ | |||
| // provider: 'wxpay', // 服务提提供商 | |||
| // timeStamp: res.result.timeStamp, // 时间戳 | |||
| // nonceStr: res.result.nonceStr, // 随机字符串 | |||
| // package: res.result.packageValue, | |||
| // signType: res.result.signType, // 签名算法 | |||
| // paySign: res.result.paySign, // 签名 | |||
| // success: function (res) { | |||
| // console.log('支付成功',res); | |||
| // uni.redirectTo({ | |||
| // url: '/pages/index/order' | |||
| // }) | |||
| // }, | |||
| // fail: function (err) { | |||
| // console.log('支付失败',err); | |||
| // uni.showToast({ | |||
| // icon:'none', | |||
| // title:"支付失败" | |||
| // }) | |||
| // } | |||
| // }); | |||
| } | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .content{ | |||
| max-height: 80vh; | |||
| overflow: hidden; | |||
| overflow-y: auto; | |||
| .address{ | |||
| display: flex; | |||
| padding: 20rpx; | |||
| background-color: #fff; | |||
| image{ | |||
| width: 30rpx; | |||
| height: 30rpx; | |||
| margin: 20rpx; | |||
| } | |||
| view{ | |||
| margin: 20rpx; | |||
| overflow:hidden; //超出的文本隐藏 | |||
| text-overflow:ellipsis; //溢出用省略号显示 | |||
| white-space:nowrap; //溢出不换行 | |||
| } | |||
| .icon{ | |||
| margin-left: auto; | |||
| } | |||
| } | |||
| .submit-info{ | |||
| background-color: #fff; | |||
| padding: 30rpx; | |||
| margin-top: 20rpx; | |||
| .title{ | |||
| font-size: 30rpx; | |||
| padding: 10rpx; | |||
| font-weight: 600; | |||
| } | |||
| .box{ | |||
| display: flex; | |||
| margin-top: 10rpx; | |||
| .image{ | |||
| width: 200rpx; | |||
| height: 200rpx; | |||
| border-radius: 20rpx; | |||
| margin-right: 20rpx; | |||
| } | |||
| .info{ | |||
| flex: 1; | |||
| .unit{ | |||
| font-size: 24rpx; | |||
| padding: 10rpx 20rpx; | |||
| color: #717171; | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| .price{ | |||
| color: $uni-color; | |||
| font-size: 28rpx; | |||
| padding: 10rpx 20rpx; | |||
| text{ | |||
| font-size: 36rpx; | |||
| font-weight: 900; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .submit-unit{ | |||
| padding: 30rpx; | |||
| background-color: #fff; | |||
| .title{ | |||
| font-size: 28rpx; | |||
| font-weight: 600; | |||
| } | |||
| .list{ | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| font-size: 22rpx; | |||
| .act{ | |||
| color: $uni-color; | |||
| border: 1px solid $uni-color; | |||
| background-color: #F9E7DE; | |||
| } | |||
| view{ | |||
| border-radius: 15rpx; | |||
| width: 320rpx; | |||
| background-color: #F3F3F3; | |||
| border: 1px solid #F3F3F3; | |||
| margin: 10rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| padding: 15rpx 0; | |||
| } | |||
| } | |||
| } | |||
| .expense-detail{ | |||
| padding: 30rpx; | |||
| background-color: #fff; | |||
| font-size: 28rpx; | |||
| .title{ | |||
| font-weight: 600; | |||
| } | |||
| .detail{ | |||
| background-color: #F6F6F6; | |||
| color: #717171; | |||
| margin: 10rpx 0; | |||
| padding: 10rpx 20rpx; | |||
| } | |||
| } | |||
| .submit-btn{ | |||
| width: 600rpx; | |||
| height: 80rpx; | |||
| color: #fff; | |||
| border-radius: 40rpx; | |||
| font-size: 28rpx; | |||
| margin: 20rpx auto; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| border: 1rpx solid $uni-color; | |||
| overflow: hidden; | |||
| .l{ | |||
| flex: 1; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| color: $uni-color; | |||
| } | |||
| .r{ | |||
| background: $uni-color; | |||
| flex: 1; | |||
| height: 100%; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,213 @@ | |||
| <template> | |||
| <view class="address"> | |||
| <navbar title="地址管理" leftClick @leftClick="leftClick" /> | |||
| <view class="address-list"> | |||
| <addressList | |||
| controls | |||
| ref="addressList" | |||
| @deleteAddress="deleteAddress" | |||
| @editAddress="editAddress" | |||
| @editDefault="editDefault"/> | |||
| </view> | |||
| <redactAddress | |||
| ref="addressPopup" | |||
| :addressDetail="addressDetail" | |||
| @saveOrUpdate="saveOrUpdate" | |||
| :title="title"></redactAddress> | |||
| <view class="add-btn"> | |||
| <view @click="addBtn" class="btn"> | |||
| 新增地址 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import redactAddress from '../components/address/redactAddress.vue' | |||
| import addressList from '../components/address/addressList.vue' | |||
| export default { | |||
| components: { | |||
| redactAddress, | |||
| addressList | |||
| }, | |||
| data() { | |||
| return { | |||
| title: '新增地址', | |||
| type : '', | |||
| } | |||
| }, | |||
| onLoad(args) { | |||
| this.type = args.type | |||
| if(this.type == 'back'){ | |||
| this.addBtn() | |||
| } | |||
| }, | |||
| onShow() { | |||
| this.getAddressList() | |||
| }, | |||
| methods: { | |||
| //获取地址列表 | |||
| getAddressList() { | |||
| this.$refs.addressList.getAddressList() | |||
| }, | |||
| //获取地址详情 | |||
| editAddress(address) { | |||
| this.$refs.addressPopup.open({...address}) | |||
| }, | |||
| //返回个人中心 | |||
| leftClick() { | |||
| uni.navigateBack(-1) | |||
| }, | |||
| //添加和修改地址 | |||
| saveOrUpdate(addressDetail) { | |||
| let data = { | |||
| name: addressDetail.name, | |||
| phone: addressDetail.phone, | |||
| address: addressDetail.address, | |||
| addressDetail: addressDetail.addressDetail, | |||
| defaultId: addressDetail.defaultId || '0', | |||
| latitude: addressDetail.latitude, | |||
| longitude: addressDetail.longitude | |||
| } | |||
| if (addressDetail.id) { | |||
| data.id = addressDetail.id | |||
| } | |||
| this.$api(data.id ? 'addressEdit' : 'addressAdd', data, res => { | |||
| if (res.code == 200) { | |||
| this.$refs.addressPopup.close() | |||
| this.getAddressList() | |||
| if(this.type == 'back'){ | |||
| uni.navigateBack(-1) | |||
| } | |||
| uni.showToast({ | |||
| title: '操作成功', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| //修改默认地址 | |||
| editDefault(id) { | |||
| this.$api('addressDefault', { | |||
| id: id, | |||
| }, res => { | |||
| if (res.code == 200) { | |||
| this.$refs.addressPopup.close() | |||
| uni.showToast({ | |||
| title: '操作成功', | |||
| icon: 'none' | |||
| }) | |||
| this.getAddressList() | |||
| } | |||
| }) | |||
| }, | |||
| //删除地址 | |||
| deleteAddress(id) { | |||
| let self = this | |||
| uni.showModal({ | |||
| title: '删除地址', | |||
| content: '确认删除此地址?删除后数据不可恢复', | |||
| success(e) { | |||
| if(e.confirm){ | |||
| self.$api('addressDelete', { | |||
| id | |||
| }, res => { | |||
| if (res.code == 200) { | |||
| uni.showToast({ | |||
| title: '删除成功', | |||
| icon: 'none' | |||
| }) | |||
| self.getAddressList() | |||
| } | |||
| }) | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| //点击新增按钮 | |||
| addBtn() { | |||
| this.title = '新增地址' | |||
| this.$refs.addressPopup.open({ //初始化数据 | |||
| name: '', | |||
| phone: '', | |||
| address: '', | |||
| addressDetail: '', | |||
| defaultId: '', | |||
| latitude: '', | |||
| longitude: '' | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .address { | |||
| width: 750rpx; | |||
| margin: 0rpx auto; | |||
| background: #F5F5F5; | |||
| box-sizing: border-box; | |||
| min-height: 100vh; | |||
| .address-list { | |||
| padding: 40rpx 20rpx 120rpx 20rpx; | |||
| } | |||
| .add-btn { | |||
| position: fixed; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| left: 0; | |||
| bottom: 0; | |||
| width: 750rpx; | |||
| height: 100rpx; | |||
| background: white; | |||
| .btn { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| width: 85%; | |||
| height: 80rpx; | |||
| border-radius: 40rpx; | |||
| color: white; | |||
| text-align: center; | |||
| font-size: 28rpx; | |||
| background: $uni-color; | |||
| } | |||
| } | |||
| } | |||
| @media all and (min-width: 961px) { | |||
| .add-btn { | |||
| left: 50% !important; | |||
| transform: translateX(-50%); | |||
| } | |||
| } | |||
| //选择位置地图样式 | |||
| :deep(.uni-system-choose-location) { | |||
| z-index: 99999 !important; | |||
| } | |||
| </style> | |||
| @ -0,0 +1,172 @@ | |||
| <template> | |||
| <!-- 帮助与反馈 --> | |||
| <view class="help"> | |||
| <navbar title="帮助与反馈" leftClick @leftClick="$utils.navigateBack" /> | |||
| <view class="help-box"> | |||
| <view> | |||
| <view class="help-issue"> | |||
| <text>问题和意见</text> | |||
| <text style="color: #BD3624;">*</text> | |||
| </view> | |||
| <uv-textarea v-model="form.question" :count="true" border="none" height="400" | |||
| placeholder="请把发现的问题提交给我们,感谢您的参与(必填)" | |||
| :text-style="{color:'#BCB7B7',fontSize:'28rpx'}" /> | |||
| </view> | |||
| <view> | |||
| <view class="help-issue"> | |||
| <text>问题截图</text> | |||
| <!-- <text style="color: #BD3624;">*</text> --> | |||
| </view> | |||
| <view class="help-screenshot"> | |||
| <uv-upload :fileList="fileList" multiple :maxCount="3" width="180rpx" | |||
| height="180rpx" multiple @afterRead="afterRead" @delete="deleteImage"> | |||
| <image src="../static/help/uploading.png" mode="aspectFill" | |||
| style="width: 180rpx;height: 180rpx;" /> | |||
| </uv-upload> | |||
| </view> | |||
| </view> | |||
| <view> | |||
| <view class="help-issue"> | |||
| <text>联系方式</text> | |||
| <text style="color: #BD3624;">*</text> | |||
| </view> | |||
| <view class="form-sheet-cell"> | |||
| <view> | |||
| 联系姓名 | |||
| </view> | |||
| <input placeholder="请输入联系姓名" v-model="form.name" /> | |||
| </view> | |||
| <view class="form-sheet-cell"> | |||
| <view> | |||
| 联系电话 | |||
| </view> | |||
| <input placeholder="请输入联系电话" v-model="form.phone" /> | |||
| </view> | |||
| </view> | |||
| <view class="help-button"> | |||
| <!-- <view>历史提交</view> --> | |||
| <view @click="submit">确认</view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| form : { | |||
| question : '', | |||
| phone : '', | |||
| name : '', | |||
| image : '', | |||
| }, | |||
| fileList: [] | |||
| } | |||
| }, | |||
| onLoad(args) { | |||
| }, | |||
| methods: { | |||
| deleteImage(e){ | |||
| this.fileList.splice(e.index, 1) | |||
| }, | |||
| afterRead(e){ | |||
| let self = this | |||
| e.file.forEach(file => { | |||
| self.$Oss.ossUpload(file.url).then(url => { | |||
| self.fileList.push({ | |||
| url | |||
| }) | |||
| }) | |||
| }) | |||
| }, | |||
| submit(){ | |||
| let data = JSON.parse(JSON.stringify(this.form)) | |||
| if(this.$utils.verificationAll(this.form, { | |||
| question : '请输入你的问题和意见',//问题和意见 | |||
| // image : '请上传截图',// | |||
| name : '请输入姓名',// | |||
| phone : '请输入手机号码',//手机号码 | |||
| })){ | |||
| return | |||
| } | |||
| data.image = this.fileList.map((item) => item.url).join(",") | |||
| this.$api('addAdvice', data, res => { | |||
| if(res.code == 200){ | |||
| uni.showToast({ | |||
| title: res.message, | |||
| icon:'none' | |||
| }) | |||
| setTimeout(uni.navigateBack, 800, -1) | |||
| } | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .help { | |||
| .help-box { | |||
| width: 92%; | |||
| margin-left: 4%; | |||
| .help-issue { | |||
| margin: 20rpx; | |||
| font-size: 28rpx; | |||
| font-weight: 600; | |||
| color: #333333; | |||
| } | |||
| .help-screenshot { | |||
| display: flex; | |||
| align-items: center; | |||
| background-color: #fff; | |||
| padding: 20rpx; | |||
| } | |||
| .form-sheet-cell{ | |||
| display: flex; | |||
| background-color: #fff; | |||
| padding: 20rpx 30rpx; | |||
| font-size: 24rpx; | |||
| align-items: center; | |||
| view{ | |||
| width: 150rpx; | |||
| } | |||
| } | |||
| .help-button { | |||
| display: flex; | |||
| justify-content: center; | |||
| font-size: 24rpx; | |||
| flex-shrink: 0; | |||
| margin-top: 60rpx; | |||
| view { | |||
| padding: 14rpx 120rpx; | |||
| border-radius: 38rpx; | |||
| } | |||
| view:nth-child(1) { | |||
| background: $uni-color; | |||
| color: #fff; | |||
| } | |||
| view:nth-child(2) { | |||
| color: #FFFDF6; | |||
| background-color: #C83741; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,283 @@ | |||
| <template> | |||
| <view class="promotion"> | |||
| <navbar title="二维码" | |||
| bgColor="#A3D250" | |||
| color="#fff" | |||
| leftClick @leftClick="$utils.navigateBack" /> | |||
| <view class="promotion-card"> | |||
| <!-- <view class="user-info"> --> | |||
| <!-- <image class="image" :src="userInfo.headImage" mode="widthFix"></image> --> | |||
| <!-- <image class="image" src="../../static/logo.png" mode="widthFix"></image> --> | |||
| <!-- <view class="user-name">{{ userInfo.nickName }}</view> --> | |||
| <!-- <view class="user-name">湖南第一深情</view> --> | |||
| <!-- </view> --> | |||
| <!-- <view class="invitation-code-img"> | |||
| <image | |||
| style="width: 400rpx;" | |||
| :src="imagePath" mode="widthFix"></image> | |||
| </view> --> | |||
| <image style="width: 100%;" :src="imagePath" mode="widthFix"></image> | |||
| <!-- <view class="invitation-code">加油站: {{ title }}</view> --> | |||
| <canvas id="myCanvas" type="2d" canvas-id="firstCanvas1"></canvas> | |||
| </view> | |||
| <view class="btns"> | |||
| <view class="btn" | |||
| @click="preservationImg(imagePath)">保存</view> | |||
| <!-- <view class="btn">立即邀请</view> --> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import { mapState } from 'vuex' | |||
| export default { | |||
| name: 'Promotion', | |||
| computed: { | |||
| ...mapState(['userInfo']), | |||
| }, | |||
| data() { | |||
| return { | |||
| url: '', | |||
| title: '123123', | |||
| baseUrl: 'https://dianpin-img.xzaiyp.top/', | |||
| canvas: {}, | |||
| imagePath: '', | |||
| } | |||
| }, | |||
| onShow() { | |||
| this.getQrCode() | |||
| this.$store.commit('getUserInfo') | |||
| }, | |||
| methods: { | |||
| getQrCode() { | |||
| this.$api('getInviteCode', res => { | |||
| if (res.code == 200) { | |||
| this.url = res.result.url | |||
| this.title = res.result.name | |||
| this.draw() | |||
| } | |||
| }) | |||
| }, | |||
| draw() { | |||
| uni.showLoading({ | |||
| title: "拼命绘画中..." | |||
| }) | |||
| wx.createSelectorQuery() | |||
| .select('#myCanvas') // 绘制的canvas的id | |||
| .fields({ | |||
| node: true, | |||
| size: true | |||
| }) | |||
| .exec((res) => { | |||
| const canvas = res[0].node | |||
| // 渲染上下文 | |||
| const ctx = canvas.getContext('2d') | |||
| // Canvas 画布的实际绘制宽高 | |||
| const width = res[0].width | |||
| const height = res[0].height | |||
| // 初始化画布大小 | |||
| const dpr = wx.getWindowInfo().pixelRatio | |||
| //根据dpr调整 | |||
| // dpr 2 4 | |||
| // 3 6 | |||
| let Ratio = dpr * 2 | |||
| console.log("bug", dpr) | |||
| canvas.width = width * dpr | |||
| canvas.height = height * dpr | |||
| this.canvas = canvas | |||
| ctx.scale(dpr, dpr) | |||
| ctx.clearRect(0, 0, width, height) | |||
| ctx.fillStyle = '#fff' | |||
| ctx.fillRect(0, 0, canvas.width, canvas.height) | |||
| //用户图片 | |||
| // const image = canvas.createImage() | |||
| // image.onload = () => { | |||
| // ctx.drawImage(image, 30, 18, 40, 40) | |||
| // } | |||
| // image.src = '/public/img/wechar_1.png' | |||
| // image.src = this.userInfo.headImage | |||
| ctx.fillStyle = 'black' | |||
| ctx.font = '22px PingFangSC-regular'; | |||
| let s = this.title || '加油站' | |||
| ctx.fillText(s, canvas.width / Ratio - s.length * 11, 50); | |||
| //二维码图片 | |||
| const coderImage = canvas.createImage() | |||
| coderImage.src = this.baseUrl + this.url | |||
| coderImage.onload = () => { | |||
| ctx.drawImage(coderImage, | |||
| canvas.width / Ratio - 240 / 2, 100, 240, 240) | |||
| } | |||
| // 绘制完成后存储路径 | |||
| setTimeout(() => { | |||
| wx.canvasToTempFilePath({ | |||
| x: 0, | |||
| y: 0, | |||
| width: this.canvas.width, | |||
| height: this.canvas.height, | |||
| canvas, | |||
| success: (res) => { | |||
| var tempFilePath = res.tempFilePath; | |||
| this.imagePath = tempFilePath | |||
| uni.hideLoading() | |||
| } | |||
| }); | |||
| }, 600); | |||
| }) | |||
| }, | |||
| back() { | |||
| uni.navigateBack(-1) | |||
| }, | |||
| preservationImg(img) { | |||
| let that = this | |||
| uni.authorize({ | |||
| /* scope.writePhotosAlbum 类型是保存到相册 */ | |||
| scope: 'scope.writePhotosAlbum', | |||
| success() { | |||
| /* 已授权进入 */ | |||
| /* 保存图片到相册方法方法 */ | |||
| that.imgApi(img); | |||
| }, | |||
| complete(res) { | |||
| /* 判断如果没有授权就打开设置选项让用户重新授权 */ | |||
| uni.getSetting({ | |||
| success(res) { | |||
| if (!res.authSetting['scope.writePhotosAlbum']) { | |||
| /* 打开设置的方法 */ | |||
| that.openInstall(); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| }); | |||
| }, | |||
| imgApi(image) { | |||
| /* 获取图片的信息 */ | |||
| uni.getImageInfo({ | |||
| src: image, | |||
| success: function(image) { | |||
| /* 保存图片到手机相册 */ | |||
| uni.saveImageToPhotosAlbum({ | |||
| filePath: image.path, | |||
| success: function() { | |||
| uni.showModal({ | |||
| title: '保存成功', | |||
| content: '图片已成功保存到相册', | |||
| showCancel: false | |||
| }); | |||
| }, | |||
| complete(res) { | |||
| console.log(res); | |||
| } | |||
| }); | |||
| } | |||
| }); | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .promotion { | |||
| width: 100%; | |||
| height: 100vh; | |||
| background-color: $uni-color; | |||
| .promotion-card { | |||
| width: 90%; | |||
| margin: 100rpx auto 0rpx auto; | |||
| box-shadow: 0rpx 0rpx 15rpx rgba(0, 0, 0, .2); | |||
| border-radius: 15rpx; | |||
| padding: 40rpx 30rpx; | |||
| box-sizing: border-box; | |||
| background-color: #fff; | |||
| .user-info { | |||
| display: flex; | |||
| align-items: center; | |||
| .image { | |||
| width: 80rpx; | |||
| height: 80rpx; | |||
| border-radius: 50%; | |||
| margin-right: 10rpx; | |||
| } | |||
| .user-name { | |||
| font-size: 30rpx; | |||
| } | |||
| } | |||
| .invitation-code-img { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| margin: 100rpx 0rpx; | |||
| .image { | |||
| width: 30%; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| .invitation-code { | |||
| text-align: center; | |||
| color: #818181; | |||
| font-size: 28rpx; | |||
| } | |||
| } | |||
| .btns { | |||
| position: fixed; | |||
| left: 0; | |||
| bottom: 0; | |||
| width: 100%; | |||
| height: 120rpx; | |||
| display: flex; | |||
| background: #fff; | |||
| font-size: 28rpx; | |||
| color: $uni-color; | |||
| .btn { | |||
| flex: 1; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| &:nth-child(2) { | |||
| background: orange; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #myCanvas { | |||
| position: fixed; | |||
| left: 100%; | |||
| /* visibility: hidden */ | |||
| /* visibility: hidden; */ | |||
| /* margin-top: 100rpx; */ | |||
| margin: 68rpx auto; | |||
| width: 750rpx; | |||
| height: 750rpx; | |||
| /* line-height: 20px; */ | |||
| background-color: rgba(255, 255, 255, 1); | |||
| text-align: center; | |||
| } | |||
| </style> | |||
| @ -0,0 +1,109 @@ | |||
| <template> | |||
| <view class="purse"> | |||
| <navbar title="立即提现" leftClick @leftClick="$utils.navigateBack" /> | |||
| <!-- 水洗店 --> | |||
| <view class="userShop"> | |||
| <userShopCommission purse /> | |||
| </view> | |||
| <view class="from-body"> | |||
| <view>我要提现</view> | |||
| <view class="from-line"> | |||
| <input placeholder="请输入提现金额" /> | |||
| </view> | |||
| <view class="from-line"> | |||
| <input placeholder="请输入姓名" /> | |||
| </view> | |||
| <view class="from-line"> | |||
| <input placeholder="请输入开户行" /> | |||
| </view> | |||
| <view class="from-line"> | |||
| <input placeholder="请输入银行卡卡号" /> | |||
| </view> | |||
| <view class="mt56">提现说明</view> | |||
| <view style="line-height: 45rpx; font-size: 24rpx;color: #666666;" v-html="notice"> | |||
| </view> | |||
| <!-- <p>1、本次提现必须通过银行卡提现,暂不支持其他途径。</p> | |||
| <p>2、如若遇到24小时提现未到账,请联系客服。</p> --> | |||
| </view> | |||
| <view class="b-fiexd"> | |||
| <view class="button-submit">提交</view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import userShopCommission from '@/components/userShop/userShopCommission.vue' | |||
| export default { | |||
| components: { | |||
| userShopCommission, | |||
| }, | |||
| data() { | |||
| return { | |||
| notice : '' | |||
| } | |||
| }, | |||
| methods: { | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .purse{ | |||
| min-height: 100vh; | |||
| background-color: #ffffff; | |||
| .from-body { | |||
| padding: 40rpx 20rpx; | |||
| font-size: 28rpx; | |||
| font-family: PingFang SC, PingFang SC-Bold; | |||
| font-weight: 700; | |||
| text-align: left; | |||
| color: #333333; | |||
| line-height: 40px; | |||
| padding-bottom: 160rpx; | |||
| .from-line { | |||
| margin-top: 40rpx; | |||
| } | |||
| input { | |||
| width: 612rpx; | |||
| height: 90rpx; | |||
| line-height: 90rpx; | |||
| background: #F5F5F5; | |||
| border-radius: 46rpx; | |||
| padding: 0 50rpx; | |||
| font-size: 28rpx; | |||
| font-family: PingFang SC, PingFang SC-Regular; | |||
| font-weight: 400; | |||
| text-align: left; | |||
| color: #333; | |||
| } | |||
| } | |||
| .button-submit { | |||
| width: 596rpx; | |||
| height: 90rpx; | |||
| line-height: 90rpx; | |||
| background: $uni-color; | |||
| border-radius: 46rpx; | |||
| margin: 20rpx auto; | |||
| font-size: 28rpx; | |||
| font-family: PingFang SC, PingFang SC-Regular; | |||
| font-weight: 400; | |||
| text-align: center; | |||
| color: #ffffff; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,88 @@ | |||
| <template> | |||
| <view class="running-water"> | |||
| <navbar :title="title[status]" leftClick @leftClick="leftClick" /> | |||
| <view class="tab-box"> | |||
| <view class="tab-box1" v-if="agentFlow && agentFlow.total"> | |||
| <uv-cell center border :title="item.title" | |||
| v-for="(item, index) in agentFlow.records" | |||
| :value="x[item.type] + item.money" :label="item.createTime" /> | |||
| </view> | |||
| <view | |||
| style="padding: 100rpx 0;" | |||
| v-else> | |||
| <uv-empty | |||
| mode="history" | |||
| textSize="28rpx" | |||
| iconSize="100rpx"/> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| title : ['余额记录','提现记录','佣金记录'], | |||
| agentFlow : { | |||
| total : 0, | |||
| records : [ | |||
| { | |||
| type : 0, | |||
| money : 100, | |||
| createTime : '2024-04-02 20:00', | |||
| title : "佣金提现", | |||
| }, | |||
| { | |||
| type : 0, | |||
| money : 100, | |||
| createTime : '2024-04-02 20:00', | |||
| title : "佣金提现", | |||
| }, | |||
| { | |||
| type : 0, | |||
| money : 100, | |||
| createTime : '2024-04-02 20:00', | |||
| title : "佣金提现", | |||
| }, | |||
| ] | |||
| }, | |||
| x : ['+', '-' , '-' , '+'], | |||
| status : 0, | |||
| } | |||
| }, | |||
| onLoad(e) { | |||
| this.status = e.status | |||
| }, | |||
| methods: { | |||
| leftClick() { //返回钱包 | |||
| uni.navigateBack(-1) | |||
| }, | |||
| getAgentFlow(){ //获取流水记录 | |||
| let type = this.status; | |||
| this.$api('getAgentFlow', { type }, res => { | |||
| if(res.code == 200){ | |||
| this.agentFlow = res.result | |||
| } | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .running-water{ | |||
| width: 750rpx; | |||
| background: #F5F5F5; | |||
| margin: 0 auto; | |||
| min-height: 100vh; | |||
| .tab-box{ | |||
| margin: 20rpx; | |||
| background-color: #fff; | |||
| border-radius: 20rpx; | |||
| overflow: hidden; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,567 @@ | |||
| <template> | |||
| <view> | |||
| <navbar | |||
| title="订单详情" | |||
| leftClick | |||
| @leftClick="$utils.navigateBack" | |||
| /> | |||
| <!-- 水洗店 --> | |||
| <view class="" | |||
| v-if="userShop"> | |||
| <view class="controls"> | |||
| <view class="title"> | |||
| <image src="../static/order/icon.png" mode=""></image> | |||
| 服务完成 | |||
| </view> | |||
| <view class="tips"> | |||
| 待送回 | |||
| </view> | |||
| <view class="btns"> | |||
| <view class="btn1"> | |||
| 快递寄回 | |||
| </view> | |||
| <view class="btn2"> | |||
| 线下配送 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="steps"> | |||
| <uv-steps | |||
| activeColor="#FD5100" | |||
| :current="stepsCurrent" dot> | |||
| <uv-steps-item :title="item" | |||
| :key="index" | |||
| v-for="(item, index) in steps"></uv-steps-item> | |||
| </uv-steps> | |||
| </view> | |||
| </view> | |||
| <!-- 酒店和水洗店 --> | |||
| <view class="info"> | |||
| <view class="flex" | |||
| style="display: flex;"> | |||
| <view style="width: 8rpx;height: 30rpx; | |||
| background: #FD5100;border-radius: 6rpx;" /> | |||
| <view class="head-title">服务项目</view> | |||
| </view> | |||
| <view class="flex"> | |||
| <view class="server-item"> | |||
| <view class="img-box"> | |||
| <image :src="msgShop.image" mode="aspectFill"></image> | |||
| </view> | |||
| <view class="server-info"> | |||
| <view class="server-title"> | |||
| {{msgOrder.projectName}} | |||
| <!-- <view class="coupon">领券立减</view> --> | |||
| </view> | |||
| <view class="current-price"> | |||
| <text class="unit">¥</text>{{msgOrder.money}} | |||
| </view> | |||
| <view class="sales-volume" style="margin-top: 5px;"> | |||
| <view class="desc">规格:{{msgOrder.unit}}</view> | |||
| </view> | |||
| <view class="time-coupon"> | |||
| <!-- <view class="flex"> | |||
| <image src="@/static/home/time-icon.png"></image> | |||
| <view class="time">{{msgOrder.useTime}}分钟</view> | |||
| </view> --> | |||
| <!-- <view class="sales-volume"> | |||
| <image src="@/static/icons/icon1.png"></image> | |||
| <view class="desc">已售出{{msgShop.payNum}}+单</view> | |||
| </view> --> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- <view class="line min_tips"> | |||
| <view class="head-div flex"> | |||
| <view style="width: 118rpx;height: 118rpx;border-radius: 50%;overflow: hidden;"> | |||
| <image style="width: 118rpx;" :src="msgTechnician.image" mode="widthFix"></image> | |||
| </view> | |||
| <view style="padding: 10rpx 34rpx;display: flex;flex-direction: column;justify-content: space-around;"> | |||
| <view class="nickname"> | |||
| {{msgTechnician.title}} | |||
| <view v-if="msgTechnician.isVip" class="tag"> | |||
| <image src="@/static/order/s.png" mode="aspectFit"></image> | |||
| <view class="auth">官方认证</view> | |||
| </view> | |||
| </view> | |||
| <view class="days"> | |||
| <van-rate v-model="msgTechnician.score" :size="10" readonly color="#ffb54c" void-icon="star" | |||
| void-color="#eee" /> | |||
| <view class=""> | |||
| 好评{{msgTechnician.pinNum}} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view @click="gototechnicianDetail(msgTechnician)" class="btn-x"> | |||
| 服务技师 | |||
| </view> | |||
| </view> --> | |||
| <view class="line address"> | |||
| <view class="address-top"> | |||
| <!-- <view class=""> | |||
| 服务地址 | |||
| </view> --> | |||
| <view class="copy"> | |||
| <image @click="copy(msgOrder.name + ' ' + msgOrder.phone + ' ' + msgOrder.address)" src="/static/order/copy.png"></image> | |||
| </view> | |||
| </view> | |||
| <view class="addressDetail"> | |||
| <view class="">{{msgOrder.name}} {{msgOrder.phone}}</view> | |||
| <view class="">{{msgOrder.address}}</view> | |||
| </view> | |||
| </view> | |||
| <view class="line"> | |||
| <view class="t min_tips"> | |||
| <view class=""> | |||
| 实付款 | |||
| </view> | |||
| <view class="current-price"> | |||
| ¥{{ msgOrder.money }} | |||
| </view> | |||
| </view> | |||
| <view class="min_tips"> | |||
| <view class=""> | |||
| 租赁费用 | |||
| </view> | |||
| <view class=""> | |||
| ¥{{ msgOrder.price }} | |||
| </view> | |||
| </view> | |||
| <view class="min_tips"> | |||
| <view class=""> | |||
| 水洗费用 | |||
| </view> | |||
| <view class=""> | |||
| ¥{{ msgOrder.price}} | |||
| </view> | |||
| </view> | |||
| <view class="min_tips"> | |||
| <view class=""> | |||
| 押金 | |||
| </view> | |||
| <view class=""> | |||
| ¥{{ msgOrder.price }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 订单信息 --> | |||
| <view class="line"> | |||
| <view class="t min_tips"> | |||
| <view class=""> | |||
| 订单信息 | |||
| </view> | |||
| </view> | |||
| <view class="min_tips"> | |||
| <view class=""> | |||
| 订单编号 | |||
| </view> | |||
| <view class=""> | |||
| {{msgOrder.id}} | |||
| </view> | |||
| </view> | |||
| <view class="min_tips"> | |||
| <view class=""> | |||
| 下单时间 | |||
| </view> | |||
| <view class=""> | |||
| {{msgOrder.createTime}} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 下单须知 --> | |||
| <view class="line"> | |||
| <view class="t min_tips"> | |||
| <view class=""> | |||
| 下单须知 | |||
| </view> | |||
| </view> | |||
| <view class="min_tips" style="line-height: 40rpx;"> | |||
| {{msgShop.projectExplain}} | |||
| </view> | |||
| <view class="btns"> | |||
| <view @click="clickService" class="btn"> | |||
| 联系客服 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import { mapGetters } from 'vuex' | |||
| export default { | |||
| computed : { | |||
| ...mapGetters(['userShop']), | |||
| }, | |||
| data() { | |||
| return { | |||
| stepsCurrent : 0, | |||
| steps : [ | |||
| '接单', | |||
| '检查', | |||
| '开始清洗', | |||
| '服务完成', | |||
| ], | |||
| msgShop : { | |||
| money : 99.99, | |||
| image : 'https://img95.699pic.com/photo/50058/1378.jpg_wh860.jpg', | |||
| projectExplain : '1.xxxxxxxxxx xxxxxxxxxx。2.xxxxxx xxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxx xxxxxxxxxxxxxxxx。3.。', | |||
| }, | |||
| msgOrder : { | |||
| money : 99.99, | |||
| address : '广东省广州市越秀区城南故事C3栋2802', | |||
| name : '李**', | |||
| phone : '150*****091', | |||
| unit : '120*40*75【桌子尺寸】', | |||
| state_dictText : '已完成', | |||
| price : 199.99, | |||
| id : '020644568964457', | |||
| createTime : '2024-01-18 15:39', | |||
| projectName : '桌布租赁' | |||
| }, | |||
| } | |||
| }, | |||
| methods: { | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .order { | |||
| background: linear-gradient(#4899a6, #6fc6ad, #6fc6ad); | |||
| padding-bottom: 10px; | |||
| } | |||
| .controls{ | |||
| margin: 20rpx; | |||
| background-color: #fff; | |||
| height: 400rpx; | |||
| display: flex; | |||
| flex-direction: column; | |||
| width: 710rpx; | |||
| border-radius: 20rpx; | |||
| justify-content: center; | |||
| align-items: center; | |||
| .title{ | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| font-size: 40rpx; | |||
| image{ | |||
| width: 100rpx; | |||
| height: 100rpx; | |||
| margin-right: 20rpx; | |||
| } | |||
| } | |||
| .tips{ | |||
| font-size: 26rpx; | |||
| color: #FD5100; | |||
| margin-top: 10rpx; | |||
| } | |||
| .btns{ | |||
| margin-top: 50rpx; | |||
| display: flex; | |||
| view{ | |||
| margin: 0 20rpx; | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| color: #fff; | |||
| background-color: $uni-color; | |||
| padding: 15rpx 40rpx; | |||
| border-radius: 40rpx; | |||
| } | |||
| .btn2{ | |||
| background-color: #FFFFFF; | |||
| border: 1px solid #A7A7A7; | |||
| color: #A7A7A7; | |||
| } | |||
| } | |||
| } | |||
| .steps{ | |||
| margin: 20rpx; | |||
| background-color: #fff; | |||
| display: flex; | |||
| flex-direction: column; | |||
| width: 710rpx; | |||
| border-radius: 20rpx; | |||
| padding: 70rpx 0; | |||
| /deep/ .uv-text__value{ | |||
| font-size: 22rpx !important; | |||
| } | |||
| } | |||
| .box { | |||
| padding: 20px; | |||
| .btns { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| margin-top: 10px; | |||
| .btn { | |||
| color: #fff; | |||
| padding: 10rpx 50rpx; | |||
| background-color: #ffb300; | |||
| border-radius: 30rpx; | |||
| font-size: 25rpx; | |||
| margin-right: 10rpx; | |||
| } | |||
| .btc{ | |||
| background: #ccc; | |||
| } | |||
| } | |||
| } | |||
| .info { | |||
| margin: 10px; | |||
| padding: 20rpx; | |||
| background-color: #fff; | |||
| width: calc(100% - 40px); | |||
| border-radius: 10px; | |||
| .head-title { | |||
| font-family: PingFang SC, PingFang SC-Bold; | |||
| color: #2f2e2e; | |||
| line-height: 30rpx; | |||
| margin-left: 10rpx; | |||
| } | |||
| .server-item { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| background: white; | |||
| border-radius: 15rpx; | |||
| box-sizing: border-box; | |||
| margin: 20rpx 0rpx; | |||
| width: 100%; | |||
| .img-box { | |||
| width: 150rpx; | |||
| height: 150rpx; | |||
| border-radius: 10rpx; | |||
| overflow: hidden; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| .server-info { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-around; | |||
| width: calc(100% - 180rpx); | |||
| box-sizing: border-box; | |||
| padding: 10rpx 15rpx; | |||
| .server-title { | |||
| display: flex; | |||
| margin-bottom: 10rpx; | |||
| } | |||
| .coupon { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| background: #F29E45; | |||
| color: white; | |||
| width: 120rpx; | |||
| height: 40rpx; | |||
| border-radius: 10rpx; | |||
| margin-left: 10rpx; | |||
| font-size: 22rpx; | |||
| } | |||
| .time-coupon, | |||
| .price { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| align-items: center; | |||
| } | |||
| .time-coupon { | |||
| margin: 10rpx 0rpx; | |||
| font-size: 26rpx; | |||
| justify-content: space-between; | |||
| width: 100%; | |||
| .flex { | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| image { | |||
| width: 25rpx; | |||
| height: 25rpx; | |||
| } | |||
| .time { | |||
| color: #B8B8B8; | |||
| margin-left: 6rpx; | |||
| } | |||
| } | |||
| .sales-volume { | |||
| display: flex; | |||
| align-items: center; | |||
| color: #B8B8B8; | |||
| font-size: 24rpx; | |||
| image { | |||
| width: 25rpx; | |||
| height: 25rpx; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .address { | |||
| .address-top{ | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| image{ | |||
| width: 30rpx; | |||
| height: 30rpx; | |||
| } | |||
| } | |||
| .addressDetail { | |||
| color: #777; | |||
| font-size: 22rpx; | |||
| padding: 5px 0; | |||
| } | |||
| text { | |||
| background-color: #F29E45; | |||
| padding: 8rpx 10rpx; | |||
| color: #fff; | |||
| font-size: 20rpx; | |||
| margin-left: 10px; | |||
| border-radius: 5px; | |||
| } | |||
| } | |||
| .min_tips { | |||
| font-size: 22rpx; | |||
| color: #777; | |||
| display: flex; | |||
| justify-content: space-between; | |||
| padding: 5px 0; | |||
| align-items: center; | |||
| } | |||
| .current-price { | |||
| font-size: 30rpx; | |||
| color: #FD5100; | |||
| } | |||
| .line { | |||
| border-top: 2px dotted #00000011; | |||
| padding: 20rpx 0; | |||
| .t { | |||
| padding: 5px 0; | |||
| color: #000; | |||
| font-size: 26rpx; | |||
| } | |||
| } | |||
| .head-div { | |||
| .nickname { | |||
| font-size: 30rpx; | |||
| font-weight: 600; | |||
| text-align: left; | |||
| line-height: 42rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| .tag { | |||
| position: relative; | |||
| display: flex; | |||
| align-items: center; | |||
| image { | |||
| height: 45rpx; | |||
| width: 90rpx; | |||
| vertical-align: middle; | |||
| } | |||
| .auth { | |||
| position: absolute; | |||
| white-space: nowrap; | |||
| color: #FF6200; | |||
| left: 23rpx; | |||
| font-size: 17rpx; | |||
| } | |||
| } | |||
| } | |||
| .days { | |||
| font-size: 20rpx; | |||
| font-weight: 400; | |||
| text-align: left; | |||
| line-height: 56rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| view { | |||
| padding-left: 5px; | |||
| } | |||
| } | |||
| } | |||
| .btn-x { | |||
| color: #6fc6ad; | |||
| border: 1px solid #6fc6ad; | |||
| padding: 10rpx 20rpx; | |||
| border-radius: 30rpx; | |||
| } | |||
| .btns { | |||
| display: flex; | |||
| justify-content: center; | |||
| .btn { | |||
| color: #6fc6ad; | |||
| border: 1px solid #6fc6ad; | |||
| padding: 10rpx 20rpx; | |||
| border-radius: 30rpx; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,353 @@ | |||
| <template> | |||
| <view class="refundsOrExchange"> | |||
| <navbar :title="title[titleIndex]" leftClick @leftClick="$utils.navigateBack" /> | |||
| <view class="frame"> | |||
| <!-- 商品简介 --> | |||
| <view class="itme1" @click="openSpPopup"> | |||
| <view class="left"> | |||
| <img src="../../static/image/center/1.png" alt="" style="width: 100%;height: 100%;"> | |||
| </view> | |||
| <view class="center"> | |||
| <view>{{ commodity.title }}</view> | |||
| <view>{{ commodity.smallTitle }}</view> | |||
| </view> | |||
| <view class="right">×{{ commodity.total }}</view> | |||
| </view> | |||
| <!--<commoditySelect ></commoditySelect>--> | |||
| <!-- 申请类型&申请原因 --> | |||
| <view class="item2"> | |||
| <view class="type"> | |||
| <span>申请类型</span> | |||
| <span>退货退款</span> | |||
| </view> | |||
| <uv-line></uv-line> | |||
| <view class="reason"> | |||
| <view>申请原因</view> | |||
| <view> | |||
| <uv-input placeholder="请输入申请原因" border="none" clearable></uv-input> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 退货数量&申请金额--> | |||
| <view class="item3"> | |||
| <view class="type"> | |||
| <span>{{ titleIndex == 0 ? '退货数量' : '换货数量' }}</span> | |||
| <span> | |||
| <uv-number-box :min="1" :max="100"></uv-number-box> | |||
| </span> | |||
| </view> | |||
| <uv-line v-if='titleIndex == 0 ? true :false'></uv-line> | |||
| <view class="reason" v-if='titleIndex == 0 ? true :false'> | |||
| <view>申请原因</view> | |||
| <view> | |||
| <uv-input disabled placeholder="$" border="none" clearable></uv-input> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 申请说明 --> | |||
| <view class="item4"> | |||
| <view>申请说明(选填)</view> | |||
| <view> | |||
| <uv-input placeholder="请您详细填写申请说明" border="none" clearable></uv-input> | |||
| </view> | |||
| <view> | |||
| <uv-upload :fileList="fileList" :maxCount="5" multiple width="150rpx" height="150rpx" | |||
| @delete="deleteImage" @afterRead="afterRead" :previewFullImage="true"></uv-upload> | |||
| </view> | |||
| </view> | |||
| <!-- 联系电话 --> | |||
| <view class="item5"> | |||
| <view class="phone"> | |||
| <view>联系电话</view> | |||
| <view> | |||
| <uv-input placeholder="请输入联系电话" border="none" clearable></uv-input> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 底部按钮 --> | |||
| <!--商品选择--> | |||
| <uv-popup ref="spPopup" :round="30"> | |||
| </uv-popup> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| onLoad(option) { | |||
| this.titleIndex = option.index | |||
| }, | |||
| components: { | |||
| }, | |||
| data() { | |||
| return { | |||
| titleIndex: 0, | |||
| title: ['申请换货', '申请退货'], | |||
| fileList: [], | |||
| bottomBtnStyle: { | |||
| color: '#FFF', | |||
| backgroundColor: '#fd5100', | |||
| fontSize: '34rpx', | |||
| text: '提交申请', | |||
| width: '400rpx', | |||
| height: '80rpx', | |||
| borderRadius: '100rpx', | |||
| bottom: '40rpx' | |||
| }, | |||
| commodityList: [{ | |||
| title: '商品名称', | |||
| smallTitle: '产品规格:120*4*75【桌子尺寸】', | |||
| total: 1, | |||
| }, | |||
| { | |||
| title: '商品名称1', | |||
| smallTitle: '产品规格:120*4*75【桌子尺寸】', | |||
| total: 1, | |||
| }, | |||
| { | |||
| title: '商品名称2', | |||
| smallTitle: '产品规格:120*4*75【桌子尺寸】', | |||
| total: 1, | |||
| } | |||
| ], | |||
| commodity: { | |||
| title: '商品名称', | |||
| smallTitle: '产品规格:120*4*75【桌子尺寸】', | |||
| total: 1, | |||
| }, | |||
| } | |||
| }, | |||
| mounted() { | |||
| }, | |||
| methods: { | |||
| openSpPopup() { | |||
| this.$refs.spPopup.open('bottom'); | |||
| }, | |||
| // 选择退换货商品回调 | |||
| selectCommodity(e) { | |||
| console.log(e, "selectCommodity--e") | |||
| this.commodity = e | |||
| this.$refs.spPopup.close() | |||
| }, | |||
| confirm() { | |||
| console.log("==="); | |||
| }, | |||
| deleteImage(e) { | |||
| this.fileList.splice(e.index, 1) | |||
| }, | |||
| afterRead(e) { | |||
| let self = this | |||
| e.file.forEach(file => { | |||
| self.$Oss.ossUpload(file.url).then(url => { | |||
| self.fileList.push({ | |||
| url | |||
| }) | |||
| }) | |||
| }) | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| * { | |||
| box-sizing: border-box; | |||
| } | |||
| .refundsOrExchange { | |||
| .frame { | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 30rpx; | |||
| width: 100%; | |||
| padding-top: 40rpx; | |||
| background-color: #f5f5f5; | |||
| .itme1 { | |||
| display: flex; | |||
| height: 200rpx; | |||
| background-color: #ffffff; | |||
| .left { | |||
| padding: 40rpx; | |||
| width: 20%; | |||
| border-radius: 10rpx; | |||
| background-color: #ffffff; | |||
| } | |||
| .center { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: center; | |||
| gap: 20rpx; | |||
| width: 60%; | |||
| padding: 0rpx 0 0 20rpx; | |||
| background-color: #ffffff; | |||
| // 给第一个 view 设置样式 | |||
| >view:first-of-type { | |||
| font-size: 36rpx; | |||
| color: #333; | |||
| } | |||
| // 给第二个 view 设置样式 | |||
| >view:nth-of-type(2) { | |||
| font-size: 28rpx; | |||
| color: #666666; | |||
| } | |||
| } | |||
| .right { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| width: 10%; | |||
| color: #666666; | |||
| background-color: #ffffff; | |||
| } | |||
| } | |||
| .item2 { | |||
| width: 100vw; | |||
| .type { | |||
| display: flex; | |||
| align-items: center; | |||
| background-color: #FFF; | |||
| height: 80rpx; | |||
| padding: 0 0 0 20rpx; | |||
| >span:nth-of-type(1) { | |||
| width: 30%; | |||
| } | |||
| >span:nth-of-type(2) { | |||
| width: 70%; | |||
| } | |||
| } | |||
| .reason { | |||
| display: flex; | |||
| align-items: center; | |||
| background-color: #FFF; | |||
| height: 80rpx; | |||
| // margin: 10rpx 0 0 0; | |||
| padding: 10rpx 0 0 20rpx; | |||
| >view:nth-of-type(1) { | |||
| width: 30%; | |||
| } | |||
| >view:nth-of-type(2) { | |||
| width: 70%; | |||
| padding: 0 20rpx 0 0; | |||
| } | |||
| } | |||
| } | |||
| .item3 { | |||
| width: 100vw; | |||
| .type { | |||
| display: flex; | |||
| align-items: center; | |||
| background-color: #FFF; | |||
| height: 80rpx; | |||
| padding: 0 0 0 20rpx; | |||
| >span:nth-of-type(1) { | |||
| width: 70%; | |||
| } | |||
| >span:nth-of-type(2) { | |||
| width: 30%; | |||
| } | |||
| } | |||
| .reason { | |||
| display: flex; | |||
| align-items: center; | |||
| background-color: #FFF; | |||
| height: 80rpx; | |||
| // margin: 10rpx 0 0 0; | |||
| padding: 10rpx 0 0 20rpx; | |||
| >view:nth-of-type(1) { | |||
| width: 30%; | |||
| } | |||
| >view:nth-of-type(2) { | |||
| width: 70%; | |||
| padding: 0 20rpx 0 0; | |||
| } | |||
| } | |||
| } | |||
| .item4 { | |||
| display: flex; | |||
| flex-direction: column; | |||
| padding: 10rpx 0 0 20rpx; | |||
| background-color: #FFF; | |||
| >view:nth-of-type(1) { | |||
| background-color: #FFF; | |||
| } | |||
| >view:nth-of-type(2) { | |||
| margin: 10rpx 0 10rpx 0; | |||
| background-color: #FFF; | |||
| } | |||
| } | |||
| .item5 { | |||
| display: flex; | |||
| flex-direction: column; | |||
| padding: 0 0 0 20rpx; | |||
| background-color: #FFF; | |||
| .phone { | |||
| display: flex; | |||
| align-items: center; | |||
| background-color: #FFF; | |||
| height: 80rpx; | |||
| // margin: 10rpx 0 0 0; | |||
| padding: 10rpx 0 0 20rpx; | |||
| >view:nth-of-type(1) { | |||
| width: 30%; | |||
| } | |||
| >view:nth-of-type(2) { | |||
| width: 70%; | |||
| padding: 0 20rpx 0 0; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,169 @@ | |||
| <template> | |||
| <view class="page"> | |||
| <navbar title="商品详情" leftClick @leftClick="$utils.navigateBack" /> | |||
| <view class="swipe"> | |||
| <uv-swiper | |||
| :list="productDetail.image.split(',')" | |||
| indicator | |||
| height="350rpx"></uv-swiper> | |||
| </view> | |||
| <view class="info"> | |||
| <view class="title"> | |||
| 桌布租赁 | |||
| </view> | |||
| <view class="info-line"> | |||
| <view class="price"> | |||
| ¥<text>45.9</text>起 | |||
| </view> | |||
| <view class="num"> | |||
| 已售1000+ | |||
| <image src="../static/product/like.png" mode=""></image> | |||
| </view> | |||
| </view> | |||
| <view class="tips"> | |||
| <view class="tip"> | |||
| 专业设备 | |||
| </view> | |||
| <view class="tip"> | |||
| 科学流程 | |||
| </view> | |||
| <view class="tip"> | |||
| 质量保证 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="info-unit"> | |||
| <uv-cell title="是否有桌布" isLink> | |||
| <template #icon> | |||
| <text class="text">桌布</text> | |||
| </template> | |||
| </uv-cell> | |||
| <uv-cell title="请选择规格" isLink> | |||
| <template #icon> | |||
| <text class="text">规格</text> | |||
| </template> | |||
| </uv-cell> | |||
| <uv-cell> | |||
| <template #icon> | |||
| <text>上门取件·送货上门</text> | |||
| </template> | |||
| </uv-cell> | |||
| </view> | |||
| <view class="content"> | |||
| <view class="title"> | |||
| 商品详情 | |||
| </view> | |||
| <uv-parse :content="productDetail.content"></uv-parse> | |||
| </view> | |||
| <!-- 分享和租赁按钮 --> | |||
| <submit | |||
| @submit="$refs.submitUnitSelect.open()" | |||
| @share="share"/> | |||
| <!-- 选择规格 --> | |||
| <submitUnitSelect ref="submitUnitSelect"/> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import submit from '../components/product/submit.vue' | |||
| import submitUnitSelect from '../components/product/submitUnitSelect.vue' | |||
| export default { | |||
| components : { | |||
| submit, | |||
| submitUnitSelect | |||
| }, | |||
| data() { | |||
| return { | |||
| productDetail : { | |||
| image : 'https://cdn.uviewui.com/uview/swiper/swiper3.png,https://cdn.uviewui.com/uview/swiper/swiper2.png', | |||
| content : '', | |||
| } | |||
| } | |||
| }, | |||
| onLoad(args) { | |||
| console.log(args); | |||
| }, | |||
| methods: { | |||
| // 分享商品 | |||
| share(){ | |||
| }, | |||
| // 选择完成规格立即租赁下单 | |||
| submit(){ | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .page{ | |||
| .swipe{ | |||
| } | |||
| .info{ | |||
| padding: 30rpx; | |||
| background-color: #fff; | |||
| .title{ | |||
| font-size: 34rpx; | |||
| font-weight: 900; | |||
| } | |||
| .info-line{ | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| margin-top: 30rpx; | |||
| .price{ | |||
| font-size: 28rpx; | |||
| color: $uni-color; | |||
| text{ | |||
| font-size: 34rpx; | |||
| } | |||
| } | |||
| .num{ | |||
| font-size: 24rpx; | |||
| image{ | |||
| width: 24rpx; | |||
| height: 24rpx; | |||
| } | |||
| } | |||
| } | |||
| .tips{ | |||
| display: flex; | |||
| font-size: 20rpx; | |||
| margin-top: 30rpx; | |||
| .tip{ | |||
| margin-right: 40rpx; | |||
| } | |||
| } | |||
| } | |||
| .info-unit{ | |||
| margin-top: 20rpx; | |||
| padding: 30rpx; | |||
| background-color: #fff; | |||
| /deep/ text{ | |||
| font-size: 26rpx; | |||
| } | |||
| /deep/ .text{ | |||
| color: #7C7C7C; | |||
| margin-right: 20rpx; | |||
| font-size: 26rpx; | |||
| } | |||
| } | |||
| .content{ | |||
| background-color: #fff; | |||
| margin-top: 20rpx; | |||
| .title{ | |||
| padding: 30rpx; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1 @@ | |||
| <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1726157567630" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6220" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M513.536 628.6336c101.6832 0 280.8832 38.7072 310.8864 193.7408 77.5168-77.5168 124.928-185.9584 124.928-305.0496 0-241.152-194.6624-435.8144-435.8144-435.8144S77.7216 277.0944 77.7216 517.2224c0 119.0912 47.4112 227.6352 124.928 306.0736 30.0032-154.9312 209.2032-194.6624 310.8864-194.6624z m0-439.7056c112.3328 0 204.3904 91.0336 204.3904 204.3904 0 112.3328-91.0336 204.3904-204.3904 204.3904a203.776 203.776 0 0 1-204.3904-204.3904c0.1024-112.4352 92.0576-204.3904 204.3904-204.3904z m0 0" fill="#cdcdcd" p-id="6221"></path><path d="M515.4816 1006.8992c-65.8432 0-129.8432-12.9024-189.952-38.4-58.1632-24.576-110.2848-59.8016-155.136-104.5504A485.56032 485.56032 0 0 1 65.8432 708.8128c-25.6-60.2112-38.5024-124.1088-38.5024-189.952 0-65.8432 12.9024-129.8432 38.4-189.952 24.576-58.1632 59.8016-110.2848 104.5504-155.136 44.8512-44.8512 96.9728-79.9744 155.136-104.5504C385.6384 43.6224 449.536 30.72 515.4816 30.72c65.8432 0 129.8432 12.9024 189.952 38.4 58.1632 24.576 110.2848 59.8016 155.136 104.5504 44.8512 44.8512 79.9744 96.9728 104.5504 155.136C990.6176 389.0176 1003.52 452.9152 1003.52 518.8608c0 65.8432-12.9024 129.8432-38.4 189.952-24.576 58.1632-59.8016 110.2848-104.5504 155.136a485.56032 485.56032 0 0 1-155.136 104.5504 484.39296 484.39296 0 0 1-189.952 38.4z m0-936.8576c-60.6208 0-119.3984 11.8784-174.6944 35.2256a447.76448 447.76448 0 0 0-142.6432 96.1536A444.42624 444.42624 0 0 0 101.9904 344.064a446.70976 446.70976 0 0 0-35.2256 174.6944c0 60.6208 11.8784 119.3984 35.2256 174.6944 22.6304 53.4528 54.9888 101.4784 96.1536 142.6432 41.1648 41.2672 89.1904 73.6256 142.6432 96.1536 55.296 23.3472 114.0736 35.2256 174.6944 35.2256 60.6208 0 119.3984-11.8784 174.6944-35.2256 53.4528-22.6304 101.4784-54.9888 142.6432-96.1536 41.2672-41.1648 73.6256-89.1904 96.1536-142.6432 23.3472-55.296 35.2256-114.0736 35.2256-174.6944 0-60.6208-11.8784-119.3984-35.2256-174.6944a447.76448 447.76448 0 0 0-96.1536-142.6432 444.42624 444.42624 0 0 0-142.6432-96.1536 447.44704 447.44704 0 0 0-174.6944-35.2256z m0 0" fill="#cdcdcd" p-id="6222"></path></svg> | |||
| @ -0,0 +1,110 @@ | |||
| import Vue from 'vue' | |||
| import Vuex from 'vuex' | |||
| Vue.use(Vuex); //vue的插件机制 | |||
| import api from '@/api/api.js' | |||
| //Vuex.Store 构造器选项 | |||
| const store = new Vuex.Store({ | |||
| state: { | |||
| configList: {}, //配置列表 | |||
| shop : false,//身份判断如果不需要,可以删除 | |||
| userInfo : {}, //用户信息 | |||
| }, | |||
| getters: { | |||
| // 角色 true为水洗店 false为酒店 : 身份判断如果不需要,可以删除 | |||
| userShop(state){ | |||
| return state.shop | |||
| } | |||
| }, | |||
| mutations: { | |||
| // 初始化配置 | |||
| initConfig(state){ | |||
| api('getConfig', res => { | |||
| const configList = { | |||
| ...state.configList, | |||
| } | |||
| if (res.code == 200) { | |||
| res.result.forEach(n => { | |||
| configList[n.keyName] = n.keyContent; | |||
| configList[n.keyName + '_keyValue'] = n.keyValue; | |||
| }); | |||
| } | |||
| state.configList = configList | |||
| uni.$emit('initConfig', state.configList) | |||
| }) | |||
| // let config = ['getPrivacyPolicy', 'getUserAgreement'] | |||
| // config.forEach(k => { | |||
| // api(k, res => { | |||
| // if (res.code == 200) { | |||
| // state.configList[k] = res.result | |||
| // } | |||
| // }) | |||
| // }) | |||
| }, | |||
| // 微信登录 | |||
| login(state){ | |||
| uni.showLoading({ | |||
| title: '登录中...' | |||
| }) | |||
| uni.login({ | |||
| success(res) { | |||
| if(res.errMsg != "login:ok"){ | |||
| return | |||
| } | |||
| api('wxLogin', { | |||
| code : res.code | |||
| }, res => { | |||
| uni.hideLoading() | |||
| if(res.code != 200){ | |||
| return | |||
| } | |||
| state.userInfo = res.result.userInfo | |||
| uni.setStorageSync('token', res.result.token) | |||
| if(!state.userInfo.nickName || !state.userInfo.headImage){ | |||
| uni.navigateTo({ | |||
| url: '/pages_order/auth/wxUserInfo' | |||
| }) | |||
| }else{ | |||
| uni.navigateBack(-1) | |||
| } | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| // 获取用户个人信息 | |||
| getUserInfo(state){ | |||
| api('getInfo', res => { | |||
| if(res.code == 200){ | |||
| state.userInfo = res.result | |||
| } | |||
| }) | |||
| }, | |||
| // 退出登录 | |||
| logout(state){ | |||
| uni.showModal({ | |||
| title: '确认退出登录吗', | |||
| success(r) { | |||
| if(r.confirm){ | |||
| state.userInfo = {} | |||
| state.role = false | |||
| uni.removeStorageSync('token') | |||
| uni.reLaunch({ | |||
| url: '/pages/index/index' | |||
| }) | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| }, | |||
| actions: {}, | |||
| }) | |||
| export default store | |||
| @ -0,0 +1,10 @@ | |||
| uni.addInterceptor({ | |||
| returnValue (res) { | |||
| if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { | |||
| return res; | |||
| } | |||
| return new Promise((resolve, reject) => { | |||
| res.then((res) => res[0] ? reject(res[0]) : resolve(res[1])); | |||
| }); | |||
| }, | |||
| }); | |||
| @ -0,0 +1,96 @@ | |||
| /** | |||
| * 这里是uni-app内置的常用样式变量 | |||
| * | |||
| * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 | |||
| * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App | |||
| * | |||
| */ | |||
| /** | |||
| * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 | |||
| * | |||
| * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 | |||
| */ | |||
| /* 颜色变量 */ | |||
| $uni-color: #FD5100; | |||
| /* 行为相关颜色 */ | |||
| $uni-color-primary: #007aff; | |||
| $uni-color-success: #4cd964; | |||
| $uni-color-warning: #f0ad4e; | |||
| $uni-color-error: #dd524d; | |||
| /* 文字基本颜色 */ | |||
| $uni-text-color:#333;//基本色 | |||
| $uni-text-color-inverse:#fff;//反色 | |||
| $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 | |||
| $uni-text-color-placeholder: #808080; | |||
| $uni-text-color-disable:#c0c0c0; | |||
| /* 背景颜色 */ | |||
| $uni-bg-color:#ffffff; | |||
| $uni-bg-color-grey:#f8f8f8; | |||
| $uni-bg-color-hover:#f1f1f1;//点击状态颜色 | |||
| $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 | |||
| /* 边框颜色 */ | |||
| $uni-border-color:#c8c7cc; | |||
| /* 尺寸变量 */ | |||
| /* 文字尺寸 */ | |||
| $uni-font-size-sm:12px; | |||
| $uni-font-size-base:14px; | |||
| $uni-font-size-lg:16px; | |||
| /* 图片尺寸 */ | |||
| $uni-img-size-sm:20px; | |||
| $uni-img-size-base:26px; | |||
| $uni-img-size-lg:40px; | |||
| /* Border Radius */ | |||
| $uni-border-radius-sm: 2px; | |||
| $uni-border-radius-base: 3px; | |||
| $uni-border-radius-lg: 6px; | |||
| $uni-border-radius-circle: 50%; | |||
| /* 水平间距 */ | |||
| $uni-spacing-row-sm: 5px; | |||
| $uni-spacing-row-base: 10px; | |||
| $uni-spacing-row-lg: 15px; | |||
| /* 垂直间距 */ | |||
| $uni-spacing-col-sm: 4px; | |||
| $uni-spacing-col-base: 8px; | |||
| $uni-spacing-col-lg: 12px; | |||
| /* 透明度 */ | |||
| $uni-opacity-disabled: 0.3; // 组件禁用态的透明度 | |||
| /* 文章场景相关 */ | |||
| $uni-color-title: #2C405A; // 文章标题颜色 | |||
| $uni-font-size-title:20px; | |||
| $uni-color-subtitle: #555555; // 二级标题颜色 | |||
| $uni-font-size-subtitle:26px; | |||
| $uni-color-paragraph: #3F536E; // 文章段落颜色 | |||
| $uni-font-size-paragraph:15px; | |||
| .uni-color-btn{ | |||
| border-radius: 40rpx; | |||
| padding: 20rpx; | |||
| margin: 40rpx; | |||
| background: $uni-color; | |||
| color: #fff; | |||
| text-align: center; | |||
| font-size: 28rpx; | |||
| } | |||
| .uni-uncolor-btn{ | |||
| border-radius: 40rpx; | |||
| padding: 20rpx; | |||
| margin: 40rpx; | |||
| border: 1px solid $uni-color; | |||
| color: $uni-color; | |||
| text-align: center; | |||
| font-size: 28rpx; | |||
| } | |||
| @ -0,0 +1,7 @@ | |||
| ## 1.0.2(2023-07-02) | |||
| uv-action-sheet 由于弹出层uv-popup的修改,打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/actionSheet.html | |||
| ## 1.0.1(2023-05-16) | |||
| 1. 优化组件依赖,修改后无需全局引入,组件导入即可使用 | |||
| 2. 优化部分功能 | |||
| ## 1.0.0(2023-05-10) | |||
| uv-action-sheet 底部操作菜单 | |||
| @ -0,0 +1,50 @@ | |||
| export default { | |||
| props: { | |||
| // 标题,有值则显示,同时会显示关闭按钮 | |||
| title: { | |||
| type: String, | |||
| default: '' | |||
| }, | |||
| // 选项上方的描述信息 | |||
| description: { | |||
| type: String, | |||
| default: '' | |||
| }, | |||
| // 数据 | |||
| actions: { | |||
| type: Array, | |||
| default: () => [] | |||
| }, | |||
| // 取消按钮的文字,不为空时显示按钮 | |||
| cancelText: { | |||
| type: String, | |||
| default: '' | |||
| }, | |||
| // 点击某个菜单项时是否关闭弹窗 | |||
| closeOnClickAction: { | |||
| type: Boolean, | |||
| default: true | |||
| }, | |||
| // 处理底部安全区(默认true) | |||
| safeAreaInsetBottom: { | |||
| type: Boolean, | |||
| default: true | |||
| }, | |||
| // 小程序的打开方式 | |||
| openType: { | |||
| type: String, | |||
| default: '' | |||
| }, | |||
| // 点击遮罩是否允许关闭 (默认true) | |||
| closeOnClickOverlay: { | |||
| type: Boolean, | |||
| default: true | |||
| }, | |||
| // 圆角值 | |||
| round: { | |||
| type: [Boolean, String, Number], | |||
| default: 0 | |||
| }, | |||
| ...uni.$uv?.props?.actionSheet | |||
| } | |||
| } | |||
| @ -0,0 +1,280 @@ | |||
| <template> | |||
| <uv-popup | |||
| ref="popup" | |||
| mode="bottom" | |||
| :safeAreaInsetBottom="safeAreaInsetBottom" | |||
| :round="round" | |||
| :close-on-click-overlay="closeOnClickOverlay" | |||
| @change="popupChange" | |||
| > | |||
| <view class="uv-action-sheet"> | |||
| <view | |||
| class="uv-action-sheet__header" | |||
| v-if="title" | |||
| > | |||
| <text class="uv-action-sheet__header__title uv-line-1">{{title}}</text> | |||
| <view | |||
| class="uv-action-sheet__header__icon-wrap" | |||
| @tap.stop="cancel" | |||
| > | |||
| <uv-icon | |||
| name="close" | |||
| size="17" | |||
| color="#c8c9cc" | |||
| bold | |||
| ></uv-icon> | |||
| </view> | |||
| </view> | |||
| <text | |||
| class="uv-action-sheet__description" | |||
| :style="[{ | |||
| marginTop: `${title && description ? 0 : '18px'}` | |||
| }]" | |||
| v-if="description" | |||
| >{{description}}</text> | |||
| <slot> | |||
| <uv-line v-if="description"></uv-line> | |||
| <view class="uv-action-sheet__item-wrap"> | |||
| <view v-for="(item, index) in actions" :key="index"> | |||
| <!-- #ifdef MP --> | |||
| <button | |||
| class="uv-reset-button" | |||
| :openType="item.openType" | |||
| @getuserinfo="onGetUserInfo" | |||
| @contact="onContact" | |||
| @getphonenumber="onGetPhoneNumber" | |||
| @error="onError" | |||
| @launchapp="onLaunchApp" | |||
| @opensetting="onOpenSetting" | |||
| :lang="lang" | |||
| :session-from="sessionFrom" | |||
| :send-message-title="sendMessageTitle" | |||
| :send-message-path="sendMessagePath" | |||
| :send-message-img="sendMessageImg" | |||
| :show-message-card="showMessageCard" | |||
| :app-parameter="appParameter" | |||
| @tap="selectHandler(index)" | |||
| :hover-class="!item.disabled && !item.loading ? 'uv-action-sheet--hover' : ''" | |||
| > | |||
| <!-- #endif --> | |||
| <view | |||
| class="uv-action-sheet__item-wrap__item" | |||
| @tap.stop="selectHandler(index)" | |||
| :hover-class="!item.disabled && !item.loading ? 'uv-action-sheet--hover' : ''" | |||
| :hover-stay-time="150" | |||
| > | |||
| <template v-if="!item.loading"> | |||
| <text | |||
| class="uv-action-sheet__item-wrap__item__name" | |||
| :style="[itemStyle(index)]" | |||
| >{{ item.name }}</text> | |||
| <text | |||
| v-if="item.subname" | |||
| class="uv-action-sheet__item-wrap__item__subname" | |||
| >{{ item.subname }}</text> | |||
| </template> | |||
| <uv-loading-icon | |||
| v-else | |||
| custom-class="van-action-sheet__loading" | |||
| size="18" | |||
| mode="circle" | |||
| /> | |||
| </view> | |||
| <!-- #ifdef MP --> | |||
| </button> | |||
| <!-- #endif --> | |||
| <uv-line v-if="index !== actions.length - 1"></uv-line> | |||
| </view> | |||
| </view> | |||
| </slot> | |||
| <uv-gap | |||
| bgColor="#eaeaec" | |||
| height="6" | |||
| v-if="cancelText" | |||
| ></uv-gap> | |||
| <view hover-class="uv-action-sheet--hover"> | |||
| <text | |||
| @touchmove.stop.prevent | |||
| :hover-stay-time="150" | |||
| v-if="cancelText" | |||
| class="uv-action-sheet__cancel-text" | |||
| @tap="cancel" | |||
| >{{cancelText}}</text> | |||
| </view> | |||
| </view> | |||
| </uv-popup> | |||
| </template> | |||
| <script> | |||
| import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js' | |||
| import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js' | |||
| import button from '@/uni_modules/uv-ui-tools/libs/mixin/button.js' | |||
| import openType from '@/uni_modules/uv-ui-tools/libs/mixin/openType.js' | |||
| import props from './props.js'; | |||
| /** | |||
| * ActionSheet 操作菜单 | |||
| * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。 | |||
| * @tutorial https://www.uvui.cn/components/actionSheet.html | |||
| * @property {Boolean} show 操作菜单是否展示 (默认 false ) | |||
| * @property {String} title 操作菜单标题 | |||
| * @property {String} description 选项上方的描述信息 | |||
| * @property {Array<Object>} actions 按钮的文字数组,见官方文档示例 | |||
| * @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮 | |||
| * @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true ) | |||
| * @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true ) | |||
| * @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error ) | |||
| * @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true ) | |||
| * @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 | |||
| * @property {String} sessionFrom 会话来源,openType="contact"时有效 | |||
| * @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效 | |||
| * @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效 | |||
| * @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效 | |||
| * @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false ) | |||
| * @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效 | |||
| * | |||
| * @event {Function} select 点击ActionSheet列表项时触发 | |||
| * @event {Function} close 点击取消按钮时触发 | |||
| * @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效 | |||
| * @event {Function} contact 客服消息回调,openType="contact"时有效 | |||
| * @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效 | |||
| * @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效 | |||
| * @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效 | |||
| * @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效 | |||
| * @example <uv-action-sheet ref="actionSheet" :actions="list" :title="title" ></uv-action-sheet> | |||
| */ | |||
| export default { | |||
| name: "uv-action-sheet", | |||
| mixins: [openType, button, mpMixin , mixin, props], | |||
| emits: ['close', 'select'], | |||
| computed: { | |||
| // 操作项目的样式 | |||
| itemStyle() { | |||
| return (index) => { | |||
| let style = {}; | |||
| if (this.actions[index].color) style.color = this.actions[index].color | |||
| if (this.actions[index].fontSize) style.fontSize = this.$uv.addUnit(this.actions[index].fontSize) | |||
| // 选项被禁用的样式 | |||
| if (this.actions[index].disabled) style.color = '#c0c4cc' | |||
| return style; | |||
| } | |||
| }, | |||
| }, | |||
| methods: { | |||
| open() { | |||
| this.$refs.popup.open(); | |||
| }, | |||
| close() { | |||
| this.$refs.popup.close(); | |||
| }, | |||
| popupChange(e) { | |||
| if(!e.show) this.$emit('close'); | |||
| }, | |||
| // 点击取消按钮 | |||
| cancel() { | |||
| this.close(); | |||
| }, | |||
| selectHandler(index) { | |||
| const item = this.actions[index] | |||
| if (item && !item.disabled && !item.loading) { | |||
| this.$emit('select', item) | |||
| if (this.closeOnClickAction) { | |||
| this.close(); | |||
| } | |||
| } | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| $show-lines: 1; | |||
| $show-reset-button: 1; | |||
| @import '@/uni_modules/uv-ui-tools/libs/css/variable.scss'; | |||
| @import '@/uni_modules/uv-ui-tools/libs/css/components.scss'; | |||
| @import '@/uni_modules/uv-ui-tools/libs/css/color.scss'; | |||
| $uv-action-sheet-reset-button-width:100% !default; | |||
| $uv-action-sheet-title-font-size: 16px !default; | |||
| $uv-action-sheet-title-padding: 12px 30px !default; | |||
| $uv-action-sheet-title-color: $uv-main-color !default; | |||
| $uv-action-sheet-header-icon-wrap-right:15px !default; | |||
| $uv-action-sheet-header-icon-wrap-top:15px !default; | |||
| $uv-action-sheet-description-font-size:13px !default; | |||
| $uv-action-sheet-description-color:14px !default; | |||
| $uv-action-sheet-description-margin: 18px 15px !default; | |||
| $uv-action-sheet-item-wrap-item-padding:15px !default; | |||
| $uv-action-sheet-item-wrap-name-font-size:16px !default; | |||
| $uv-action-sheet-item-wrap-subname-font-size:13px !default; | |||
| $uv-action-sheet-item-wrap-subname-color: #c0c4cc !default; | |||
| $uv-action-sheet-item-wrap-subname-margin-top:10px !default; | |||
| $uv-action-sheet-cancel-text-font-size:16px !default; | |||
| $uv-action-sheet-cancel-text-color:$uv-content-color !default; | |||
| $uv-action-sheet-cancel-text-font-size:15px !default; | |||
| $uv-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default; | |||
| .uv-reset-button { | |||
| width: $uv-action-sheet-reset-button-width; | |||
| } | |||
| .uv-action-sheet { | |||
| text-align: center; | |||
| &__header { | |||
| position: relative; | |||
| padding: $uv-action-sheet-title-padding; | |||
| &__title { | |||
| font-size: $uv-action-sheet-title-font-size; | |||
| color: $uv-action-sheet-title-color; | |||
| font-weight: bold; | |||
| text-align: center; | |||
| } | |||
| &__icon-wrap { | |||
| position: absolute; | |||
| right: $uv-action-sheet-header-icon-wrap-right; | |||
| top: $uv-action-sheet-header-icon-wrap-top; | |||
| } | |||
| } | |||
| &__description { | |||
| font-size: $uv-action-sheet-description-font-size; | |||
| color: $uv-tips-color; | |||
| margin: $uv-action-sheet-description-margin; | |||
| text-align: center; | |||
| } | |||
| &__item-wrap { | |||
| &__item { | |||
| padding: $uv-action-sheet-item-wrap-item-padding; | |||
| @include flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| flex-direction: column; | |||
| &__name { | |||
| font-size: $uv-action-sheet-item-wrap-name-font-size; | |||
| color: $uv-main-color; | |||
| text-align: center; | |||
| } | |||
| &__subname { | |||
| font-size: $uv-action-sheet-item-wrap-subname-font-size; | |||
| color: $uv-action-sheet-item-wrap-subname-color; | |||
| margin-top: $uv-action-sheet-item-wrap-subname-margin-top; | |||
| text-align: center; | |||
| } | |||
| } | |||
| } | |||
| &__cancel-text { | |||
| font-size: $uv-action-sheet-cancel-text-font-size; | |||
| color: $uv-action-sheet-cancel-text-color; | |||
| text-align: center; | |||
| padding: $uv-action-sheet-cancel-text-font-size; | |||
| } | |||
| &--hover { | |||
| background-color: $uv-action-sheet-cancel-text-hover-background-color; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,92 @@ | |||
| { | |||
| "id": "uv-action-sheet", | |||
| "displayName": "uv-action-sheet 底部操作菜单 全面兼容小程序、nvue、vue2、vue3等多端", | |||
| "version": "1.0.2", | |||
| "description": "该组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheet API,配置更加灵活,所有平台都表现一致。", | |||
| "keywords": [ | |||
| "action-sheet", | |||
| "uvui", | |||
| "uv-ui", | |||
| "操作菜单", | |||
| "菜单选择" | |||
| ], | |||
| "repository": "", | |||
| "engines": { | |||
| "HBuilderX": "^3.1.0" | |||
| }, | |||
| "dcloudext": { | |||
| "type": "component-vue", | |||
| "sale": { | |||
| "regular": { | |||
| "price": "0.00" | |||
| }, | |||
| "sourcecode": { | |||
| "price": "0.00" | |||
| } | |||
| }, | |||
| "contact": { | |||
| "qq": "" | |||
| }, | |||
| "declaration": { | |||
| "ads": "无", | |||
| "data": "插件不采集任何数据", | |||
| "permissions": "无" | |||
| }, | |||
| "npmurl": "" | |||
| }, | |||
| "uni_modules": { | |||
| "dependencies": [ | |||
| "uv-ui-tools", | |||
| "uv-popup", | |||
| "uv-icon", | |||
| "uv-line", | |||
| "uv-loading-icon", | |||
| "uv-gap" | |||
| ], | |||
| "encrypt": [], | |||
| "platforms": { | |||
| "cloud": { | |||
| "tcb": "y", | |||
| "aliyun": "y" | |||
| }, | |||
| "client": { | |||
| "Vue": { | |||
| "vue2": "y", | |||
| "vue3": "y" | |||
| }, | |||
| "App": { | |||
| "app-vue": "y", | |||
| "app-nvue": "y" | |||
| }, | |||
| "H5-mobile": { | |||
| "Safari": "y", | |||
| "Android Browser": "y", | |||
| "微信浏览器(Android)": "y", | |||
| "QQ浏览器(Android)": "y" | |||
| }, | |||
| "H5-pc": { | |||
| "Chrome": "y", | |||
| "IE": "y", | |||
| "Edge": "y", | |||
| "Firefox": "y", | |||
| "Safari": "y" | |||
| }, | |||
| "小程序": { | |||
| "微信": "y", | |||
| "阿里": "y", | |||
| "百度": "y", | |||
| "字节跳动": "y", | |||
| "QQ": "y", | |||
| "钉钉": "u", | |||
| "快手": "u", | |||
| "飞书": "u", | |||
| "京东": "u" | |||
| }, | |||
| "快应用": { | |||
| "华为": "u", | |||
| "联盟": "u" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| ## ActionSheet 操作菜单 | |||
| > **组件名:uv-action-sheet** | |||
| 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。 | |||
| 本组件功能类似于uni的uni.showActionSheet API,配置更加灵活,所有平台都表现一致。 | |||
| ### <a href="https://www.uvui.cn/components/actionSheet.html" target="_blank">查看文档</a> | |||
| ### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui) | |||
| #### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a> | |||
| @ -0,0 +1,10 @@ | |||
| ## 1.0.4(2023-12-06) | |||
| 1. 阻止事件冒泡处理 | |||
| ## 1.0.3(2023-10-23) | |||
| 1. 修复报错的BUG | |||
| ## 1.0.2(2023-10-23) | |||
| 1. 修复设置singleSize、multipleSize、space等值带单位,存在不显示的BUG | |||
| ## 1.0.1(2023-09-13) | |||
| 1. 添加依赖 | |||
| ## 1.0.0(2023-08-30) | |||
| 1. 新增uv-album相册组件 | |||
| @ -0,0 +1,312 @@ | |||
| <template> | |||
| <view class="uv-album"> | |||
| <view | |||
| class="uv-album__row" | |||
| ref="uv-album__row" | |||
| v-for="(arr, index) in showUrls" | |||
| :forComputedUse="albumWidth" | |||
| :key="index" | |||
| > | |||
| <view | |||
| class="uv-album__row__wrapper" | |||
| v-for="(item, index1) in arr" | |||
| :key="index1" | |||
| :style="[imageStyle(index + 1, index1 + 1)]" | |||
| @tap.stop="previewFullImage ? onPreviewTap(getSrc(item)) : ''" | |||
| > | |||
| <image | |||
| :src="getSrc(item)" | |||
| :mode=" | |||
| urls.length === 1 | |||
| ? imageHeight > 0 | |||
| ? singleMode | |||
| : 'widthFix' | |||
| : multipleMode | |||
| " | |||
| :style="[ | |||
| { | |||
| width: imageWidth, | |||
| height: imageHeight | |||
| } | |||
| ]" | |||
| ></image> | |||
| <view | |||
| v-if=" | |||
| showMore && | |||
| urls.length > rowCount * showUrls.length && | |||
| index === showUrls.length - 1 && | |||
| index1 === showUrls[showUrls.length - 1].length - 1 | |||
| " | |||
| class="uv-album__row__wrapper__text" | |||
| > | |||
| <uv-text | |||
| :text="`+${urls.length - maxCount}`" | |||
| color="#fff" | |||
| :size="$uv.getPx(multipleSize) * 0.3" | |||
| align="center" | |||
| customStyle="justify-content: center" | |||
| ></uv-text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js' | |||
| import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js' | |||
| // #ifdef APP-NVUE | |||
| // 由于weex为阿里的KPI业绩考核的产物,所以不支持百分比单位,这里需要通过dom查询组件的宽度 | |||
| const dom = uni.requireNativePlugin('dom') | |||
| // #endif | |||
| /** | |||
| * Album 相册 | |||
| * @description 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。减少重复的模板代码 | |||
| * @tutorial https://www.uvui.cn/components/album.html | |||
| * @property {Array} urls 图片地址列表 Array<String>|Array<Object>形式 | |||
| * @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址 | |||
| * @property {String | Number} singleSize 单图时,图片长边的长度 (默认 180 ) | |||
| * @property {String | Number} multipleSize 多图时,图片边长 (默认 70 ) | |||
| * @property {String | Number} space 多图时,图片水平和垂直之间的间隔 (默认 6 ) | |||
| * @property {String} singleMode 单图时,图片缩放裁剪的模式 (默认 'scaleToFill' ) | |||
| * @property {String} multipleMode 多图时,图片缩放裁剪的模式 (默认 'aspectFill' ) | |||
| * @property {String | Number} maxCount 取消按钮的提示文字 (默认 9 ) | |||
| * @property {Boolean} previewFullImage 是否可以预览图片 (默认 true ) | |||
| * @property {String | Number} rowCount 每行展示图片数量,如设置,singleSize和multipleSize将会无效 (默认 3 ) | |||
| * @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 (默认 true ) | |||
| * | |||
| * @event {Function} albumWidth 某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送 (回调参数 width ) | |||
| * @example <uv-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></uv-album> | |||
| */ | |||
| export default { | |||
| name: 'uv-album', | |||
| mixins: [mpMixin, mixin], | |||
| emits: ['albumWidth'], | |||
| props: { | |||
| // 图片地址,Array<String>|Array<Object>形式 | |||
| urls: { | |||
| type: Array, | |||
| default: () => [] | |||
| }, | |||
| // 指定从数组的对象元素中读取哪个属性作为图片地址 | |||
| keyName: { | |||
| type: String, | |||
| default: '' | |||
| }, | |||
| // 单图时,图片长边的长度 | |||
| singleSize: { | |||
| type: [String, Number], | |||
| default: 180 | |||
| }, | |||
| // 多图时,图片边长 | |||
| multipleSize: { | |||
| type: [String, Number], | |||
| default: 70 | |||
| }, | |||
| // 多图时,图片水平和垂直之间的间隔 | |||
| space: { | |||
| type: [String, Number], | |||
| default: 6 | |||
| }, | |||
| // 单图时,图片缩放裁剪的模式 | |||
| singleMode: { | |||
| type: String, | |||
| default: 'scaleToFill' | |||
| }, | |||
| // 多图时,图片缩放裁剪的模式 | |||
| multipleMode: { | |||
| type: String, | |||
| default: 'aspectFill' | |||
| }, | |||
| // 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量 | |||
| maxCount: { | |||
| type: [String, Number], | |||
| default: 9 | |||
| }, | |||
| // 是否可以预览图片 | |||
| previewFullImage: { | |||
| type: Boolean, | |||
| default: true | |||
| }, | |||
| // 每行展示图片数量,如设置,singleSize和multipleSize将会无效 | |||
| rowCount: { | |||
| type: [String, Number], | |||
| default: 3 | |||
| }, | |||
| // 超出maxCount时是否显示查看更多的提示 | |||
| showMore: { | |||
| type: Boolean, | |||
| default: true | |||
| }, | |||
| ...uni.$uv?.props?.album | |||
| }, | |||
| data() { | |||
| return { | |||
| // 单图的宽度 | |||
| singleWidth: 0, | |||
| // 单图的高度 | |||
| singleHeight: 0, | |||
| // 单图时,如果无法获取图片的尺寸信息,让图片宽度默认为容器的一定百分比 | |||
| singlePercent: 0.6 | |||
| } | |||
| }, | |||
| watch: { | |||
| urls: { | |||
| immediate: true, | |||
| handler(newVal) { | |||
| if (newVal.length === 1) { | |||
| this.getImageRect() | |||
| } | |||
| } | |||
| } | |||
| }, | |||
| computed: { | |||
| imageStyle() { | |||
| return (index1, index2) => { | |||
| const { space, rowCount, multipleSize, urls } = this; | |||
| const rowLen = this.showUrls.length; | |||
| const allLen = this.urls.length; | |||
| const style = { | |||
| marginRight: this.$uv.addUnit(space), | |||
| marginBottom: this.$uv.addUnit(space) | |||
| } | |||
| // 如果为最后一行,则每个图片都无需下边框 | |||
| if (index1 === rowLen) style.marginBottom = 0 | |||
| // 每行的最右边一张和总长度的最后一张无需右边框 | |||
| if ( | |||
| index2 === rowCount || | |||
| (index1 === rowLen && | |||
| index2 === this.showUrls[index1 - 1].length) | |||
| ) | |||
| style.marginRight = 0 | |||
| return style | |||
| } | |||
| }, | |||
| // 将数组划分为二维数组 | |||
| showUrls() { | |||
| const arr = [] | |||
| this.urls.map((item, index) => { | |||
| // 限制最大展示数量 | |||
| if (index + 1 <= this.maxCount) { | |||
| // 计算该元素为第几个素组内 | |||
| const itemIndex = Math.floor(index / this.rowCount) | |||
| // 判断对应的索引是否存在 | |||
| if (!arr[itemIndex]) { | |||
| arr[itemIndex] = [] | |||
| } | |||
| arr[itemIndex].push(item) | |||
| } | |||
| }) | |||
| return arr | |||
| }, | |||
| imageWidth() { | |||
| return this.$uv.addUnit( | |||
| this.urls.length === 1 ? this.singleWidth : this.multipleSize | |||
| ) | |||
| }, | |||
| imageHeight() { | |||
| return this.$uv.addUnit( | |||
| this.urls.length === 1 ? this.singleHeight : this.multipleSize | |||
| ) | |||
| }, | |||
| // 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度 | |||
| // 因为用户在某些特殊的情况下,需要让文字与相册的宽度相等,所以这里事件的形式对外发送 | |||
| albumWidth() { | |||
| let width = 0 | |||
| if (this.urls.length === 1) { | |||
| width = this.singleWidth | |||
| } else { | |||
| width = | |||
| this.showUrls[0].length * this.$uv.getPx(this.multipleSize) + | |||
| this.$uv.getPx(this.space) * (this.showUrls[0].length - 1) | |||
| } | |||
| this.$emit('albumWidth', width) | |||
| return width | |||
| } | |||
| }, | |||
| methods: { | |||
| // 预览图片 | |||
| onPreviewTap(url) { | |||
| const urls = this.urls.map((item) => { | |||
| return this.getSrc(item) | |||
| }) | |||
| uni.previewImage({ | |||
| current: url, | |||
| urls | |||
| }) | |||
| }, | |||
| // 获取图片的路径 | |||
| getSrc(item) { | |||
| return this.$uv.test.object(item) ? | |||
| (this.keyName && item[this.keyName]) || item.src : | |||
| item | |||
| }, | |||
| // 单图时,获取图片的尺寸 | |||
| // 在小程序中,需要将网络图片的的域名添加到小程序的download域名才可能获取尺寸 | |||
| // 在没有添加的情况下,让单图宽度默认为盒子的一定宽度(singlePercent) | |||
| getImageRect() { | |||
| const src = this.getSrc(this.urls[0]) | |||
| uni.getImageInfo({ | |||
| src, | |||
| success: (res) => { | |||
| // 判断图片横向还是竖向展示方式 | |||
| const isHorizotal = res.width >= res.height | |||
| this.singleWidth = isHorizotal ? | |||
| this.singleSize : | |||
| (res.width / res.height) * this.$uv.getPx(this.singleSize) | |||
| this.singleHeight = !isHorizotal ? | |||
| this.singleSize : | |||
| (res.height / res.width) * this.singleWidth | |||
| }, | |||
| fail: () => { | |||
| this.getComponentWidth() | |||
| } | |||
| }) | |||
| }, | |||
| // 获取组件的宽度 | |||
| async getComponentWidth() { | |||
| // 延时一定时间,以获取dom尺寸 | |||
| await this.$uv.sleep(30) | |||
| // #ifndef APP-NVUE | |||
| this.$uGetRect('.uv-album__row').then((size) => { | |||
| this.singleWidth = size.width * this.singlePercent | |||
| }) | |||
| // #endif | |||
| // #ifdef APP-NVUE | |||
| // 这里ref="uv-album__row"所在的标签为通过for循环出来,导致this.$refs['uv-album__row']是一个数组 | |||
| const ref = this.$refs['uv-album__row'][0] | |||
| ref && | |||
| dom.getComponentRect(ref, (res) => { | |||
| this.singleWidth = res.size.width * this.singlePercent | |||
| }) | |||
| // #endif | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| @import '@/uni_modules/uv-ui-tools/libs/css/components.scss'; | |||
| .uv-album { | |||
| @include flex(column); | |||
| &__row { | |||
| @include flex(row); | |||
| flex-wrap: wrap; | |||
| &__wrapper { | |||
| position: relative; | |||
| &__text { | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| right: 0; | |||
| bottom: 0; | |||
| background-color: rgba(0, 0, 0, 0.3); | |||
| @include flex(row); | |||
| justify-content: center; | |||
| align-items: center; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,88 @@ | |||
| { | |||
| "id": "uv-album", | |||
| "displayName": "uv-album 相册 全面兼容vue3+2、app、h5、小程序等多端", | |||
| "version": "1.0.4", | |||
| "description": "本组件提供一个类似相册的功能,让开发者开发起来更加得心应手,功能齐全,灵活配置可以,开箱即用。减少重复的模板代码", | |||
| "keywords": [ | |||
| "album", | |||
| "uv-ui", | |||
| "uvui", | |||
| "相册", | |||
| "图片" | |||
| ], | |||
| "repository": "", | |||
| "engines": { | |||
| "HBuilderX": "^3.1.0" | |||
| }, | |||
| "dcloudext": { | |||
| "type": "component-vue", | |||
| "sale": { | |||
| "regular": { | |||
| "price": "0.00" | |||
| }, | |||
| "sourcecode": { | |||
| "price": "0.00" | |||
| } | |||
| }, | |||
| "contact": { | |||
| "qq": "" | |||
| }, | |||
| "declaration": { | |||
| "ads": "无", | |||
| "data": "插件不采集任何数据", | |||
| "permissions": "无" | |||
| }, | |||
| "npmurl": "" | |||
| }, | |||
| "uni_modules": { | |||
| "dependencies": [ | |||
| "uv-ui-tools", | |||
| "uv-text" | |||
| ], | |||
| "encrypt": [], | |||
| "platforms": { | |||
| "cloud": { | |||
| "tcb": "y", | |||
| "aliyun": "y" | |||
| }, | |||
| "client": { | |||
| "Vue": { | |||
| "vue2": "y", | |||
| "vue3": "y" | |||
| }, | |||
| "App": { | |||
| "app-vue": "y", | |||
| "app-nvue": "y" | |||
| }, | |||
| "H5-mobile": { | |||
| "Safari": "y", | |||
| "Android Browser": "y", | |||
| "微信浏览器(Android)": "y", | |||
| "QQ浏览器(Android)": "y" | |||
| }, | |||
| "H5-pc": { | |||
| "Chrome": "y", | |||
| "IE": "y", | |||
| "Edge": "y", | |||
| "Firefox": "y", | |||
| "Safari": "y" | |||
| }, | |||
| "小程序": { | |||
| "微信": "y", | |||
| "阿里": "y", | |||
| "百度": "y", | |||
| "字节跳动": "y", | |||
| "QQ": "y", | |||
| "钉钉": "u", | |||
| "快手": "u", | |||
| "飞书": "u", | |||
| "京东": "u" | |||
| }, | |||
| "快应用": { | |||
| "华为": "u", | |||
| "联盟": "u" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| # Album 相册 | |||
| > **组件名:uv-album** | |||
| 本组件提供一个类似相册的功能,让开发者开发起来更加得心应手。 | |||
| 功能齐全,灵活配置可以,开箱即用。减少重复的模板代码。 | |||
| # <a href="https://www.uvui.cn/components/album.html" target="_blank">查看文档</a> | |||
| ## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small> | |||
| ### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui) | |||
| <a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank"> | |||
|  | |||
| </a> | |||
| #### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a> | |||
| @ -0,0 +1,7 @@ | |||
| ## 1.0.2(2023-06-01) | |||
| 1. 修复点击触发两次实践的BUG | |||
| ## 1.0.1(2023-05-16) | |||
| 1. 优化组件依赖,修改后无需全局引入,组件导入即可使用 | |||
| 2. 优化部分功能 | |||
| ## 1.0.0(2023-05-10) | |||
| uv-alert 警告提示组件 | |||