紧急修复了一些bug

This commit is contained in:
张乐
2020-08-17 15:28:28 +08:00
parent b17ad9443e
commit a0311f57f3
122 changed files with 1235 additions and 3297 deletions

View File

@@ -1,14 +0,0 @@
# https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

View File

@@ -1,217 +1,282 @@
<p align="center">
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
</p>
# CRMEB Admin
## 开发规范
统一使用ES6 语法
方法注释
/*
* th => 表头
* data => 数据
* fileName => 文件名
* fileType => 文件类型
* sheetName => sheet页名
*/
export default function toExcel ({ th, data, fileName, fileType, sheetName })
行注释 //
<p align="center">
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
</a>
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Estado de Construcción">
</a>
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="Licencia">
</a>
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="Liberación Github">
</a>
<a href="https://gitter.im/vue-element-admin/discuss">
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="Gitter">
</a>
<a href="https://panjiachen.github.io/vue-element-admin-site/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="Donación">
</a>
</p>
### 命名
Español | [English](./README.md) | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md)
页面目录 文件夹命名格式骆驼式命名法,例如:用户列表 userList
例如:商品模块
store 商品
├─ store 商品管理
├─index.vue 首页
├─ creatStore 新建商品
├─ index.vue
├─ sort 商品分类
├─ index.vue
├─storeAttr 商品规格
├─ index.vue
├─storeComment 商品评论
├─ index.vue
## Introducción
页面命名、组建、文件夹 命名格式小驼峰命名法,例如:用户列表 userList
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) es una interfáz de administración preparada para producción. Está basada en [vue](https://github.com/vuejs/vue) y usa [element-ui](https://github.com/ElemeFE/element) como conjunto de herramientas de interfáz de usuario.
类名函数命名 大驼峰式 例如addUser
变量命名 小驼峰式 例如user 或者 userInfo
常量 采用全大些下划线命名 例如VUE_APP_API_URl
Vue Element Admin es una solución práctica basada en la nueva plataforma de desarrollo de vue, construida con soporte a i18 para el manejo de múltiples lenguajes, plantillas estándares para aplicaciones de negocio y un conjunto de asombrosas características. Esta herramienta ayuda a construir largas y complejas Aplicacones de una sola página (SPA). Creo que lo que necesites hacer, este proyecto te ayudará.
### 文件管理规范
views 页面模块必须件文件夹区分
api 接口一个模块一个文件
组建 一个组建一个文件夹
plugins 插件一个插件一个文件夹
vuex 路由状态管理一个模块在modules 中建一个文件夹
router 一个模块一个模块在modules 中建一个文件夹
style 样式尽量采用iView自带组建common.less 系统通用样式不要轻易动
自定义通用样式 style.less,每次添加必须加注释页面独立样式在在页面内写后缀less 格式
组建样式 styles 中添加文件夹 composents 对应components 目录新建样式文件
utils 自定义工具js 独立命名,一般不用新建文件夹
- [Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
## 模块命名
~~~
├─ login 登录
├─ dashboard 首页
├─ store 商品管理
├─ order 系统订单管理
├─ distribution 分销
├─ user 用户管理
├─ content 内容管理
├─ appSetting 各个应用模块功能管理公众号、小程序、支付宝、百度小程序、今日头条小程序
├─ marketing 营销管理 优惠劵 积分
├─ sms 设置 短信设置
├─ systemSetting 设置 管理员权限 系统设置 物流设置
├─ maintain 维护 配置分类 组合数据 表单配置
├─ error-page 错误页
- [Documentación](https://panjiachen.github.io/vue-element-admin-site/)
~~~
## 目录结构
主要目录结构及说明:
~~~
├── public # 静态资源
│ ├── favicon.ico # favicon图标
│ └── index.html # html 模板
│ └── UEditor # 富文本编辑器插件
├── src # 源代码
│ ├── api # 所有请求
│ │ └──user.js # 有关登录/用户的接口
│ │ └──article.js # 有关内容的接口
│ │ └──categoryApi.js # 有关分类的接口
│ │ └──configApi.js # 有关配置分类的接口
- [Canal de Gitter](https://gitter.im/vue-element-admin/discuss)
- [Para Donaciones](https://panjiachen.github.io/vue-element-admin-site/donate/)
- [Enlace de Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
│ │ └──cms.js # 有关内容(文章管理、分类)的接口
│ │ └──common.js # 表格删除、获取消息提醒的接口
│ │ └──finance.js # 有关财务的接口
│ │ └──index.js # 有关首页的接口
│ │ └──marketing.js # 有关营销的接口
│ │ └──order.js # 有关订单的接口
│ │ └──product.js # 有关商品的接口
│ │ └──setting.js # 有关设置的接口
│ │ └──system.js # 有关维护(开发配置、安全维护)的接口
│ │ └──systemAdmin.js # 有关管理员的接口(设置--管理权限--管理员列表)
│ │ └──systemMenus.js # 有关权限规则的接口(设置--管理权限--权限规则)
│ │ └──uploadPictures.js # 有关上传图片附件的接口
│ │ └──user.js # 有关会员的接口
│ ├── assets # 图片、svg 等静态资源
│ ├── components # 公共组件
│ │ └──cards # 统计
│ │ └──copyright # 页面footer的底部声明
│ │ └──customerInfo # 选择用户
│ │ └──echarts # 统计图
│ │ └──freightTemplate # 运费模板
│ │ └──from # 生成表单
│ │ └──goodsList # 商品列表
│ │ └──iconFrom # 导航添加图标
│ │ └──link # a连接
│ │ └──mde # 多文本框
│ │ └──modelSure # 确认模态框
│ │ └──newsCategory # 图文管理页
│ │ └──publicSearchFrom # 头部搜索(没用到)
│ │ └──quill # 编辑器(没用到)
│ │ └──referrerInfo # 推荐人信息
│ │ └──searchFrom # 订单页的搜索
│ │ └──sendCoupons # 发送优惠券
│ │ └──systemStore # 添加提货点
│ │ └──ueditorFrom # 编辑器组件(供参考,没用到,主要用安装组件--vue-ueditor-wrap
│ │ └──uploadPictures # 上传图片
│ │ └──uploadVideo # 上传视频(用于商品编辑器里面)
│ ├── i18n # 多语言
│ ├── layouts # 布局
│ │ └──header-breadcrumb # 头部面包屑样式
│ │ └──header-collapse # 头部控制折叠面板的图标
│ │ └──header-fullscreen # 头部控制是否全屏的图标
│ │ └──header-i18n # 头部控制多语言
│ │ └──header-log # 头部控制日志异常图标
│ │ └──header-logo # 头部logo
│ │ └──header-notice # 头部提示消息
│ │ └──header-reload # 头部控制刷新的图标
│ │ └──header-search # 头部搜索
│ │ └──header-setting # 设置页面风格
│ │ └──header-user # 我的(个人中心、退出登录)
│ │ └──menu-head #
│ │ └──menu-side # 侧边导航栏
│ │ └──tabs # 头部的横向导航标签
│ │ └──mixins # 用于横向滚动获取title的一个js
│ ├── libs # 公共方法
│ ├── menu # 菜单配置
│ ├── mixins # 通用混合
│ ├── mock # 数据模拟
│ ├── pages # 所有页面
│ │ └──account # 有关登录页
│ │ └──login # 登录
│ │ └──register # 注册
│ │ └──agent # 分销
│ │ └──agentManage # 分销员管理
│ │ └──app # 应用
│ │ └──routine # 小程序模板消息
│ │ └──wechat # 公众号
│ │ └──menus # 微信菜单
│ │ └──newsCategory # 图文管理
│ │ └──save # 图文添加
│ │ └──reply # 自动回复
│ │ └──follow # 微信关注回复/无效关键词回复
│ │ └──keyword # 关键字回复
│ │ └──user # 用户
│ │ └──tag # 用户标签
│ │ └──user # 微信用户
│ │ └──message # 用户行为记录
│ │ └──cms # 内容
│ │ └──addArticle # 添加文章/编辑文章
│ │ └──article # 文章管理
│ │ └──articleCategory # 文章分类
│ │ └──finance # 财务
│ │ └──commission # 佣金记录
│ │ └──financialRecords # 财务记录
│ │ └──bill # 资金记录
│ │ └──recharge # 充值记录
│ │ └──userExtract # 提现申请
│ │ └──index # 主页
│ │ └──marketing # 营销
│ │ └──storeBargain # 砍价商品
│ │ └──storeCombination # 拼团管理
│ │ └──combinaList # 拼团列表
│ │ └──create # 添加拼团商品
│ │ └──index # 拼团商品
│ │ └──storeCoupon # 优惠券制作
│ │ └──storeCouponIssue # 优惠券列表
│ │ └──storeCouponUser # 会员领取记录
│ │ └──storeSeckill # 秒杀管理
│ │ └──index # 秒杀商品
│ │ └──create # 添加秒杀商品
│ │ └──userPoint # 积分日志
│ │ └──notify # 短信设置
│ │ └──smsConfig # 短信账户
│ │ └──smsPay # 短信购买
│ │ └──smsTemplateApply # 短信模板
│ │ └──order # 订单管理
│ │ └──product # 商品
│ │ └──productAdd # 添加商品
│ │ └──productAttr # 商品规格
│ │ └──productClassify # 商品分类
│ │ └──productList # 商品管理
│ │ └──productReply # 商品评论管理
│ │ └──setting # 设置
│ │ └──cityDada # 城市数据
│ │ └──clerkList # 核销员管理
│ │ └──freight # 物流公司
│ │ └──setSystem # 系统设置
│ │ └──shippingTemplates # 运费模板
│ │ └──storeList # 提货点列表
│ │ └──storeService # 客服管理
│ │ └──systemAdmin # 管理员列表
│ │ └──systemMenus # 权限规则
│ │ └──systemRole # 身份管理
│ │ └──systemStore # 门店设置
│ │ └──user # 个人中心
│ │ └──verifyOrder # 核销订单
│ │ └──system # 维护
│ │ └──auth # 商业授权
│ │ └──clear # 刷新缓存
│ │ └──configTab # 配置
│ │ └──index # 配置分类
│ │ └──list # 配置列表
│ │ └──error # 错误页
│ │ └──403 # 403
│ │ └──404 # 404
│ │ └──500 # 500
│ │ └──group # 组合数据
│ │ └──maintain
│ │ └──systemCleardata # 清除数据
│ │ └──systemDatabackup # 数据备份
│ │ └──systemFile # 文件校验
│ │ └──opendir # 文件管理
│ │ └──systemLog # 系统日志
│ │ └──user # 会员
│ │ └──group # 会员分组
│ │ └──label # 会员标签
│ │ └──level # 会员等级
│ │ └──list # 会员管理
│ ├── plugins # 插件
│ ├── router # 路由配置
│ │ └──modules # 页面路由模块
│ │ └──agent.js # 有关分销
│ │ └──app.js # 有关应用(小程序、公众号)
│ │ └──cms.js # 有关内容(文章管理、文章分类)
│ │ └──echarts.js # 有关统计
│ │ └──finance.js # 有关财务
│ │ └──index.js # 有关主页
│ │ └──marketing.js # 有关营销
│ │ └──order.js # 有关订单
│ │ └──product.js # 有关商品
│ │ └──setting.js # 有关设置
│ │ └──system.js # 有关维护
│ │ └──user.js # 有关会员
│ │ └──index.js # 路由的导出以及拦截处理
│ │ └──routes.js # 路由的汇总
│ ├── store # Vuex 状态管理
│ ├── utils # js工具
│ │ └──authLapse.js # 授权提示框
│ │ └──modalForm.js # 表单模态框
│ │ └──videoCloud.js # 上传云储存视频(七牛、腾讯、阿里)
│ │ └──validate.js # 将时间戳转化成时间;
│ │ └──public.js # 询问模态框;
│ ├── styles # 样式管理
│ ├── setting.env.js # 开发配置文件
│ ├── setting.js # 业务配置文件
│ ├── main.js # 入口文件 加载组件 初始化等
│ └── App.vue # 入口页面
├── tests # 测试管理
├── alias.config.js # 别名,仅用于配置 WebStorm 识别别名,无实际用处
├── babel.config.js # babel 配置
├── jest.config.js # jest 配置
├── package.json # package.json
└── vue.config.js # Vue CLI 3 配置
~~~
## 开发打包项目
~~~
# 进入项目目录
$ cd admin-iView
- [Canal de Gitee](https://panjiachen.gitee.io/vue-element-admin/)
# 安装依赖
$ npm install
- Plantilla base recomendada para usar: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
- Aplicación de Escritorio: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- Plantilla de Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Créditos: [@Armour](https://github.com/Armour))
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
# 启动项目(本地开发环境)
$ npm run dev
**Después de la versión `v4.1.0+`, la rama por defecto master no tendrá soporte para i18n. Por favor use [i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), los cambios serán incluidos en la rama master**
# 打包项目
$ npm run build
~~~
**la versión actual es `v4.0+` construida con `vue-cli`. Si encuentra algún problema, por favor coloque un [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). Si desea usar la versión anterior, puede cambiar de rama a [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0), no relacionado con `vue-cli`**
## 配置
**Este proyecto no está soportado para versiones muy viejas de navegadores (e.g. IE).**
## Preparación
Necesita instalar [node](https://nodejs.org/) y [git](https://git-scm.com/) localmente. El proyecto es basado en [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), toda la solicitud de datos simulada se realiza a través de [Mock.js](https://github.com/nuysoft/Mock).
Entendiendo y aprendiendo esto pudiera ayudarle con su proyecto.
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
## Patrocinantes
Se un patrocinante y pon tu logo en nuestro README on GitHub con un enlace directo a tu sitio web. [[Se un Patrocinante]](https://www.patreon.com/panjiachen)
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Plantilla de Dashboard de administración hecha con Vue, React y Angular.</p>
## Características
```
- Iniciar / Cerrar Sesión
- Permisos de Authentication
- Página de Permisos
- Directivas de permisos
- Página de configuración de permisos
- Autenticación por dos pasos
- Construcción Multi-entorno
- dev sit stage producción
- Características Globales
- I18n
- Temas dinámicos
- Dynamic sidebar (soporte a rutas multi-nivel)
- Barra de rutas dinámica
- Tags-view (Tab page Support right-click operation)
- Svg Sprite
- Datos de simulación con Mock
- Pantalla completa
- Responsive Sidebar
- Editor
- Editor de Texto Enriquecido
- Editor Markdown
- Editor JSON
- Excel
- Exportación a Excel
- Carga de Excel
- Visualización de Excel
- Exportación como zip
- Tabla
- Tabla Dinámica
- Tabla con Arrastrar y Soltar
- Tabla de edición en línea
- Páginas de Error
- 401
- 404
- Componentes
- Carga de Avatar
- Botón para subir al inicio
- Arrastrar y Soltar (Diaglogo)
- Arrastrar y Soltar (Seleccionar)
- Arrastrar y Soltar (Kanban)
- Arrastrar y Soltar (Lista)
- Panel de división
- Componente para soltar archivos
- Adhesión de objetos
- Contador hasta
- Ejemplo Avanzado
- Registro de Errores
- Tablero de indicadores
- Página de Guías
- ECharts (Gráficos)
- Portapapeles
- Convertidor de Markdown a html
```
## Iniciando
```bash
# clone el proyecto
git clone https://github.com/PanJiaChen/vue-element-admin.git
# vaya al directorio clonado
cd vue-element-admin
# instale las dependencias
npm install
# corra el proyecto como desarrollador
npm run dev
```
Automáticamente se abrirá el siguiente enlace en su navegador http://localhost:9527
## Construcción
```bash
# Construcción para entornos de prueba
npm run build:stage
# Construcción para entornos de producción
npm run build:prod
```
## Avanzado
```bash
# Vista previa con efectos de entorno
npm run preview
# Vista previa con efectos + análisis de recursos estáticos
npm run preview -- --report
# Chequeo de formato de código
npm run lint
# Chequeo de formato de código y auto-corrección
npm run lint -- --fix
```
Vaya a [Documentación](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) para mayor información
## Registro de Cambios
Los cambios detallados por cada liberación se encuentran en [notas de liberación](https://github.com/PanJiaChen/vue-element-admin/releases).
## Demostración en línea
[Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
## Donación
Si este proyecto es de mucha ayuda para ti, puedes comprarle al autor un vaso de jugo :tropical_drink:
![Donar](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
[dona por Paypal](https://www.paypal.me/panfree23)
[Comprame un Café](https://www.buymeacoffee.com/Pan)
## Navegadores Soportados
Navegadores modernos e Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| últimas 2 versiones| últimas 2 versiones| últimas 2 versiones
## Licencia
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
Copyright (c) 2017-presente PanJiaChen

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -90,7 +90,7 @@ export function AddArticle(pram) {
return request({
url: '/admin/article/save',
method: 'post',
params: data
data: data
})
}
@@ -101,7 +101,6 @@ export function AddArticle(pram) {
*/
export function UpdateArticle(pram) {
const data = {
id: pram.id,
author: pram.author,
cid: pram.cid,
content: pram.content,
@@ -118,6 +117,7 @@ export function UpdateArticle(pram) {
return request({
url: '/admin/article/update',
method: 'post',
params: data
params: { id: pram.id },
data: data
})
}

View File

@@ -77,10 +77,11 @@ export function couponUserListApi(params) {
* 积分日志 列表
* @param pram
*/
export function integralListApi(data) {
export function integralListApi(params, data) {
return request({
url: '/admin/user/bill/list',
method: 'post',
params,
data
})
}

View File

@@ -241,3 +241,15 @@ export function importProductApi(params) {
params
})
}
/**
* 恢复
* @param pram
*/
export function restoreApi(params) {
return request({
url: `/admin/store/product/importProduct`,
method: 'post',
params
})
}

View File

@@ -50,7 +50,7 @@ export function fileFileApi(data, params) {
*/
export function fileImageApi(data, params) {
return request({
url: '/admin/wechat/media/upload',
url: '/admin/upload/image',
method: 'POST',
params,
data
@@ -91,3 +91,17 @@ export function attachmentMoveApi(data) {
data
})
}
/**
* 微信上传图片
* @param data
*/
export function wechatUploadApi(data, params) {
return request({
url: `/admin/wechat/media/upload`,
method: 'post',
data,
params
})
}

View File

@@ -29,25 +29,11 @@ export function adminInfo(pram) {
})
}
export function adminList(pram) {
const data = {
account: pram.account,
addTime: pram.addTime,
isDel: pram.isDel,
lastIp: pram.lastIp,
lastTime: pram.lastTime,
level: pram.level,
loginCount: pram.loginCount,
page: pram.page,
limit: pram.limit,
realName: pram.realName,
roles: pram.roles,
status: pram.status
}
export function adminList(params) {
return request({
url: '/admin/system/admin/list',
method: 'GET',
params: data
params
})
}

View File

@@ -1,111 +0,0 @@
<template>
<transition :name="transitionName">
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
<svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height:16px;width:16px"><path d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" /></svg>
</div>
</transition>
</template>
<script>
export default {
name: 'BackToTop',
props: {
visibilityHeight: {
type: Number,
default: 400
},
backPosition: {
type: Number,
default: 0
},
customStyle: {
type: Object,
default: function() {
return {
right: '50px',
bottom: '50px',
width: '40px',
height: '40px',
'border-radius': '4px',
'line-height': '45px',
background: '#e7eaf1'
}
}
},
transitionName: {
type: String,
default: 'fade'
}
},
data() {
return {
visible: false,
interval: null,
isMoving: false
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll)
if (this.interval) {
clearInterval(this.interval)
}
},
methods: {
handleScroll() {
this.visible = window.pageYOffset > this.visibilityHeight
},
backToTop() {
if (this.isMoving) return
const start = window.pageYOffset
let i = 0
this.isMoving = true
this.interval = setInterval(() => {
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
if (next <= this.backPosition) {
window.scrollTo(0, this.backPosition)
clearInterval(this.interval)
this.isMoving = false
} else {
window.scrollTo(0, next)
}
i++
}, 16.7)
},
easeInOutQuad(t, b, c, d) {
if ((t /= d / 2) < 1) return c / 2 * t * t + b
return -c / 2 * (--t * (t - 2) - 1) + b
}
}
}
</script>
<style scoped>
.back-to-ceiling {
position: fixed;
display: inline-block;
text-align: center;
cursor: pointer;
}
.back-to-ceiling:hover {
background: #d5dbe7;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
.back-to-ceiling .Icon {
fill: #9aaabf;
background: none;
}
</style>

View File

@@ -1,7 +1,6 @@
<template>
<div>
<el-form ref="editPram" :model="editPram" label-width="130px">
{{biztype}}
<el-form-item
label="分类名称"
prop="name"
@@ -34,16 +33,6 @@
<el-form-item label="状态">
<el-switch v-model="editPram.status" :active-value="true" :inactive-value="false" />
</el-form-item>
<el-form-item label="类型" prop="type" :rules="[{required:true,message:'请选择类型',trigger:['blur']}]">
<el-select v-model="editPram.type" disabled>
<el-option
v-for="item in constants.categoryType"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="扩展字段" v-if="biztype.value !== 1 && biztype.value !== 3 && biztype.value !== 5">
<el-input v-model="editPram.extra" type="textarea" placeholder="扩展字段" />
</el-form-item>
@@ -52,8 +41,6 @@
<el-button @click="close">取消</el-button>
</el-form-item>
</el-form>
<!-- {{// editPram}}-->
<!-- {{prent}}-->
</div>
</template>
<!--创建和编辑公用一个组件-->

View File

@@ -16,7 +16,6 @@
<el-card class="box-card">
<div slot="header" class="clearfix">
<div class="container">
{{biztype}}
<el-form inline size="small">
<el-form-item>
<el-select v-model="listPram.status" placeholder="状态" clearable class="selWidth">
@@ -87,7 +86,6 @@
</template>
</el-table-column>
<el-table-column label="操作" min-width="200" fixed="right">
{{biztype}}
<template slot-scope="scope">
<el-button
v-if="biztype.value!==3"

View File

@@ -1,61 +0,0 @@
<template>
<el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
<slot />
</el-select>
</template>
<script>
import Sortable from 'sortablejs'
export default {
name: 'DragSelect',
props: {
value: {
type: Array,
required: true
}
},
computed: {
selectVal: {
get() {
return [...this.value]
},
set(val) {
this.$emit('input', [...val])
}
}
},
mounted() {
this.setSort()
},
methods: {
setSort() {
const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
this.sortable = Sortable.create(el, {
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
setData: function(dataTransfer) {
dataTransfer.setData('Text', '')
// to avoid Firefox bug
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
},
onEnd: evt => {
const targetRow = this.value.splice(evt.oldIndex, 1)[0]
this.value.splice(evt.newIndex, 0, targetRow)
}
})
}
}
}
</script>
<style scoped>
.drag-select >>> .sortable-ghost {
opacity: .8;
color: #fff!important;
background: #42b983!important;
}
.drag-select >>> .el-tag {
cursor: pointer;
}
</style>

View File

@@ -1,297 +0,0 @@
<template>
<div :id="id" :ref="id" :action="url" class="dropzone">
<input type="file" name="file">
</div>
</template>
<script>
import Dropzone from 'dropzone'
import 'dropzone/dist/dropzone.css'
// import { getToken } from 'api/qiniu';
Dropzone.autoDiscover = false
export default {
props: {
id: {
type: String,
required: true
},
url: {
type: String,
required: true
},
clickable: {
type: Boolean,
default: true
},
defaultMsg: {
type: String,
default: '上传图片'
},
acceptedFiles: {
type: String,
default: ''
},
thumbnailHeight: {
type: Number,
default: 200
},
thumbnailWidth: {
type: Number,
default: 200
},
showRemoveLink: {
type: Boolean,
default: true
},
maxFilesize: {
type: Number,
default: 2
},
maxFiles: {
type: Number,
default: 3
},
autoProcessQueue: {
type: Boolean,
default: true
},
useCustomDropzoneOptions: {
type: Boolean,
default: false
},
defaultImg: {
default: '',
type: [String, Array]
},
couldPaste: {
type: Boolean,
default: false
}
},
data() {
return {
dropzone: '',
initOnce: true
}
},
watch: {
defaultImg(val) {
if (val.length === 0) {
this.initOnce = false
return
}
if (!this.initOnce) return
this.initImages(val)
this.initOnce = false
}
},
mounted() {
const element = document.getElementById(this.id)
const vm = this
this.dropzone = new Dropzone(element, {
clickable: this.clickable,
thumbnailWidth: this.thumbnailWidth,
thumbnailHeight: this.thumbnailHeight,
maxFiles: this.maxFiles,
maxFilesize: this.maxFilesize,
dictRemoveFile: 'Remove',
addRemoveLinks: this.showRemoveLink,
acceptedFiles: this.acceptedFiles,
autoProcessQueue: this.autoProcessQueue,
dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
dictMaxFilesExceeded: '只能一个图',
previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
init() {
const val = vm.defaultImg
if (!val) return
if (Array.isArray(val)) {
if (val.length === 0) return
val.map((v, i) => {
const mockFile = { name: 'name' + i, size: 12345, url: v }
this.options.addedfile.call(this, mockFile)
this.options.thumbnail.call(this, mockFile, v)
mockFile.previewElement.classList.add('dz-success')
mockFile.previewElement.classList.add('dz-complete')
vm.initOnce = false
return true
})
} else {
const mockFile = { name: 'name', size: 12345, url: val }
this.options.addedfile.call(this, mockFile)
this.options.thumbnail.call(this, mockFile, val)
mockFile.previewElement.classList.add('dz-success')
mockFile.previewElement.classList.add('dz-complete')
vm.initOnce = false
}
},
accept: (file, done) => {
/* 七牛*/
// const token = this.$store.getters.token;
// getToken(token).then(response => {
// file.token = response.data.qiniu_token;
// file.key = response.data.qiniu_key;
// file.url = response.data.qiniu_url;
// done();
// })
done()
},
sending: (file, xhr, formData) => {
// formData.append('token', file.token);
// formData.append('key', file.key);
vm.initOnce = false
}
})
if (this.couldPaste) {
document.addEventListener('paste', this.pasteImg)
}
this.dropzone.on('success', file => {
vm.$emit('dropzone-success', file, vm.dropzone.element)
})
this.dropzone.on('addedfile', file => {
vm.$emit('dropzone-fileAdded', file)
})
this.dropzone.on('removedfile', file => {
vm.$emit('dropzone-removedFile', file)
})
this.dropzone.on('error', (file, error, xhr) => {
vm.$emit('dropzone-error', file, error, xhr)
})
this.dropzone.on('successmultiple', (file, error, xhr) => {
vm.$emit('dropzone-successmultiple', file, error, xhr)
})
},
destroyed() {
document.removeEventListener('paste', this.pasteImg)
this.dropzone.destroy()
},
methods: {
removeAllFiles() {
this.dropzone.removeAllFiles(true)
},
processQueue() {
this.dropzone.processQueue()
},
pasteImg(event) {
const items = (event.clipboardData || event.originalEvent.clipboardData).items
if (items[0].kind === 'file') {
this.dropzone.addFile(items[0].getAsFile())
}
},
initImages(val) {
if (!val) return
if (Array.isArray(val)) {
val.map((v, i) => {
const mockFile = { name: 'name' + i, size: 12345, url: v }
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v)
mockFile.previewElement.classList.add('dz-success')
mockFile.previewElement.classList.add('dz-complete')
return true
})
} else {
const mockFile = { name: 'name', size: 12345, url: val }
this.dropzone.options.addedfile.call(this.dropzone, mockFile)
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val)
mockFile.previewElement.classList.add('dz-success')
mockFile.previewElement.classList.add('dz-complete')
}
}
}
}
</script>
<style scoped>
.dropzone {
border: 2px solid #E5E5E5;
font-family: 'Roboto', sans-serif;
color: #777;
transition: background-color .2s linear;
padding: 5px;
}
.dropzone:hover {
background-color: #F6F6F6;
}
i {
color: #CCC;
}
.dropzone .dz-image img {
width: 100%;
height: 100%;
}
.dropzone input[name='file'] {
display: none;
}
.dropzone .dz-preview .dz-image {
border-radius: 0px;
}
.dropzone .dz-preview:hover .dz-image img {
transform: none;
filter: none;
width: 100%;
height: 100%;
}
.dropzone .dz-preview .dz-details {
bottom: 0px;
top: 0px;
color: white;
background-color: rgba(33, 150, 243, 0.8);
transition: opacity .2s linear;
text-align: left;
}
.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
background-color: transparent;
}
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
border: none;
}
.dropzone .dz-preview .dz-details .dz-filename:hover span {
background-color: transparent;
border: none;
}
.dropzone .dz-preview .dz-remove {
position: absolute;
z-index: 30;
color: white;
margin-left: 15px;
padding: 10px;
top: inherit;
bottom: 15px;
border: 2px white solid;
text-decoration: none;
text-transform: uppercase;
font-size: 0.8rem;
font-weight: 800;
letter-spacing: 1.1px;
opacity: 0;
}
.dropzone .dz-preview:hover .dz-remove {
opacity: 1;
}
.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
margin-left: -40px;
margin-top: -50px;
}
.dropzone .dz-preview .dz-success-mark i, .dropzone .dz-preview .dz-error-mark i {
color: white;
font-size: 5rem;
}
</style>

View File

@@ -498,6 +498,7 @@ export const selectComponents = [
__slot__: {
'list-type': true
},
accept: '',
// headers: { 'Authori-zation': getToken() },
// data: { model: 'product', pid: 0 },
// action: SettingMer.apiBaseURL + 'admin/upload/image?model=product&pid=0',
@@ -520,22 +521,22 @@ export const selectComponents = [
required: true,
span: 24,
showTip: false,
buttonText: '点击上传',
buttonText: '',
regList: [],
changeTag: true,
fileSize: 2,
sizeUnit: 'MB',
// fileSize: 2,
// sizeUnit: 'MB',
document: 'https://element.eleme.cn/#/zh-CN/component/upload'
},
__slot__: {
'list-type': true
},
action: 'https://jsonplaceholder.typicode.com/posts/',
// action: 'https://jsonplaceholder.typicode.com/posts/',
disabled: true,
accept: '',
accept: 'image',
name: 'file',
'auto-upload': true,
'list-type': 'text',
// 'auto-upload': true,
// 'list-type': 'text',
multiple: false
},
{

View File

@@ -219,14 +219,16 @@
<el-form-item v-if="activeData.name !== undefined" label="文件字段名">
<el-input v-model="activeData.name" placeholder="请输入上传文件字段名" />
</el-form-item>
<el-form-item v-if="activeData.accept !== undefined" label="文件类型">
<el-form-item v-if="activeData.accept === 'image'" label="文件类型">
<span>图片</span>
</el-form-item>
<el-form-item v-if="activeData.accept !== undefined && activeData.accept !== 'image'" label="文件类型">
<el-select
v-model="activeData.accept"
placeholder="请选择文件类型"
:style="{ width: '100%' }"
clearable
>
<el-option label="图片" value="image/*" />
<el-option label="视频" value="video/*" />
<el-option label="音频" value="audio/*" />
<el-option label="excel" value=".xls,.xlsx" />
@@ -619,6 +621,7 @@ import {
inputComponents, selectComponents, layoutComponents
} from '@/components/FormGenerator/components/generator/config'
import { saveFormConf } from '../utils/db'
import Templates from "../../../views/appSetting/wxAccount/wxTemplate/index";
const dateTimeFormat = {
date: 'yyyy-MM-dd',
@@ -633,6 +636,7 @@ const dateTimeFormat = {
export default {
components: {
Templates,
TreeNodeDialog,
IconsDialog
},

View File

@@ -1,72 +0,0 @@
<template>
<div class="json-editor">
<textarea ref="textarea" />
</div>
</template>
<script>
import CodeMirror from 'codemirror'
import 'codemirror/addon/lint/lint.css'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/rubyblue.css'
require('script-loader!jsonlint')
import 'codemirror/mode/javascript/javascript'
import 'codemirror/addon/lint/lint'
import 'codemirror/addon/lint/json-lint'
export default {
name: 'JsonEditor',
/* eslint-disable vue/require-prop-types */
props: ['value'],
data() {
return {
jsonEditor: false
}
},
watch: {
value(value) {
const editorValue = this.jsonEditor.getValue()
if (value !== editorValue) {
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
}
}
},
mounted() {
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
lineNumbers: true,
mode: 'application/json',
gutters: ['CodeMirror-lint-markers'],
theme: 'rubyblue',
lint: true
})
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
this.jsonEditor.on('change', cm => {
this.$emit('changed', cm.getValue())
this.$emit('input', cm.getValue())
})
},
methods: {
getValue() {
return this.jsonEditor.getValue()
}
}
}
</script>
<style scoped>
.json-editor{
height: 100%;
position: relative;
}
.json-editor >>> .CodeMirror {
height: auto;
min-height: 300px;
}
.json-editor >>> .CodeMirror-scroll{
min-height: 300px;
}
.json-editor >>> .cm-s-rubyblue span.cm-string {
color: #F08047;
}
</style>

View File

@@ -1,360 +0,0 @@
<template>
<div :class="computedClasses" class="material-input__component">
<div :class="{iconClass:icon}">
<i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" />
<input
v-if="type === 'email'"
v-model="currentValue"
:name="name"
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autocomplete="autoComplete"
:required="required"
type="email"
class="material-input"
@focus="handleMdFocus"
@blur="handleMdBlur"
@input="handleModelInput"
>
<input
v-if="type === 'url'"
v-model="currentValue"
:name="name"
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autocomplete="autoComplete"
:required="required"
type="url"
class="material-input"
@focus="handleMdFocus"
@blur="handleMdBlur"
@input="handleModelInput"
>
<input
v-if="type === 'number'"
v-model="currentValue"
:name="name"
:placeholder="fillPlaceHolder"
:step="step"
:readonly="readonly"
:disabled="disabled"
:autocomplete="autoComplete"
:max="max"
:min="min"
:minlength="minlength"
:maxlength="maxlength"
:required="required"
type="number"
class="material-input"
@focus="handleMdFocus"
@blur="handleMdBlur"
@input="handleModelInput"
>
<input
v-if="type === 'password'"
v-model="currentValue"
:name="name"
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autocomplete="autoComplete"
:max="max"
:min="min"
:required="required"
type="password"
class="material-input"
@focus="handleMdFocus"
@blur="handleMdBlur"
@input="handleModelInput"
>
<input
v-if="type === 'tel'"
v-model="currentValue"
:name="name"
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autocomplete="autoComplete"
:required="required"
type="tel"
class="material-input"
@focus="handleMdFocus"
@blur="handleMdBlur"
@input="handleModelInput"
>
<input
v-if="type === 'text'"
v-model="currentValue"
:name="name"
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autocomplete="autoComplete"
:minlength="minlength"
:maxlength="maxlength"
:required="required"
type="text"
class="material-input"
@focus="handleMdFocus"
@blur="handleMdBlur"
@input="handleModelInput"
>
<span class="material-input-bar" />
<label class="material-label">
<slot />
</label>
</div>
</div>
</template>
<script>
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
export default {
name: 'MdInput',
props: {
/* eslint-disable */
icon: String,
name: String,
type: {
type: String,
default: 'text'
},
value: [String, Number],
placeholder: String,
readonly: Boolean,
disabled: Boolean,
min: String,
max: String,
step: String,
minlength: Number,
maxlength: Number,
required: {
type: Boolean,
default: true
},
autoComplete: {
type: String,
default: 'off'
},
validateEvent: {
type: Boolean,
default: true
}
},
data() {
return {
currentValue: this.value,
focus: false,
fillPlaceHolder: null
}
},
computed: {
computedClasses() {
return {
'material--active': this.focus,
'material--disabled': this.disabled,
'material--raised': Boolean(this.focus || this.currentValue) // has value
}
}
},
watch: {
value(newValue) {
this.currentValue = newValue
}
},
methods: {
handleModelInput(event) {
const value = event.target.value
this.$emit('input', value)
if (this.$parent.$options.componentName === 'ElFormItem') {
if (this.validateEvent) {
this.$parent.$emit('el.form.change', [value])
}
}
this.$emit('change', value)
},
handleMdFocus(event) {
this.focus = true
this.$emit('focus', event)
if (this.placeholder && this.placeholder !== '') {
this.fillPlaceHolder = this.placeholder
}
},
handleMdBlur(event) {
this.focus = false
this.$emit('blur', event)
this.fillPlaceHolder = null
if (this.$parent.$options.componentName === 'ElFormItem') {
if (this.validateEvent) {
this.$parent.$emit('el.form.blur', [this.currentValue])
}
}
}
}
}
</script>
<style lang="scss" scoped>
// Fonts:
$font-size-base: 16px;
$font-size-small: 18px;
$font-size-smallest: 12px;
$font-weight-normal: normal;
$font-weight-bold: bold;
$apixel: 1px;
// Utils
$spacer: 12px;
$transition: 0.2s ease all;
$index: 0px;
$index-has-icon: 30px;
// Theme:
$color-white: white;
$color-grey: #9E9E9E;
$color-grey-light: #E0E0E0;
$color-blue: #2196F3;
$color-red: #F44336;
$color-black: black;
// Base clases:
%base-bar-pseudo {
content: '';
height: 1px;
width: 0;
bottom: 0;
position: absolute;
transition: $transition;
}
// Mixins:
@mixin slided-top() {
top: - ($font-size-base + $spacer);
left: 0;
font-size: $font-size-base;
font-weight: $font-weight-bold;
}
// Component:
.material-input__component {
margin-top: 36px;
position: relative;
* {
box-sizing: border-box;
}
.iconClass {
.material-input__icon {
position: absolute;
left: 0;
line-height: $font-size-base;
color: $color-blue;
top: $spacer;
width: $index-has-icon;
height: $font-size-base;
font-size: $font-size-base;
font-weight: $font-weight-normal;
pointer-events: none;
}
.material-label {
left: $index-has-icon;
}
.material-input {
text-indent: $index-has-icon;
}
}
.material-input {
font-size: $font-size-base;
padding: $spacer $spacer $spacer - $apixel * 10 $spacer / 2;
display: block;
width: 100%;
border: none;
line-height: 1;
border-radius: 0;
&:focus {
outline: none;
border: none;
border-bottom: 1px solid transparent; // fixes the height issue
}
}
.material-label {
font-weight: $font-weight-normal;
position: absolute;
pointer-events: none;
left: $index;
top: 0;
transition: $transition;
font-size: $font-size-small;
}
.material-input-bar {
position: relative;
display: block;
width: 100%;
&:before {
@extend %base-bar-pseudo;
left: 50%;
}
&:after {
@extend %base-bar-pseudo;
right: 50%;
}
}
// Disabled state:
&.material--disabled {
.material-input {
border-bottom-style: dashed;
}
}
// Raised state:
&.material--raised {
.material-label {
@include slided-top();
}
}
// Active state:
&.material--active {
.material-input-bar {
&:before,
&:after {
width: 50%;
}
}
}
}
.material-input__component {
background: $color-white;
.material-input {
background: none;
color: $color-black;
text-indent: $index;
border-bottom: 1px solid $color-grey-light;
}
.material-label {
color: $color-grey;
}
.material-input-bar {
&:before,
&:after {
background: $color-blue;
}
}
// Active state:
&.material--active {
.material-label {
color: $color-blue;
}
}
// Errors:
&.material--has-errors {
&.material--active .material-label {
color: $color-red;
}
.material-input-bar {
&:before,
&:after {
background: transparent;
}
}
}
}
</style>

View File

@@ -1,31 +0,0 @@
// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
export default {
minHeight: '200px',
previewStyle: 'vertical',
useCommandShortcut: true,
useDefaultHTMLSanitizer: true,
usageStatistics: false,
hideModeSwitch: false,
toolbarItems: [
'heading',
'bold',
'italic',
'strike',
'divider',
'hr',
'quote',
'divider',
'ul',
'ol',
'task',
'indent',
'outdent',
'divider',
'table',
'image',
'link',
'divider',
'code',
'codeblock'
]
}

View File

@@ -1,118 +0,0 @@
<template>
<div :id="id" />
</template>
<script>
// deps for editor
import 'codemirror/lib/codemirror.css' // codemirror
import 'tui-editor/dist/tui-editor.css' // editor ui
import 'tui-editor/dist/tui-editor-contents.css' // editor content
import Editor from 'tui-editor'
import defaultOptions from './default-options'
export default {
name: 'MarkdownEditor',
props: {
value: {
type: String,
default: ''
},
id: {
type: String,
required: false,
default() {
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
}
},
options: {
type: Object,
default() {
return defaultOptions
}
},
mode: {
type: String,
default: 'markdown'
},
height: {
type: String,
required: false,
default: '300px'
},
language: {
type: String,
required: false,
default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
}
},
data() {
return {
editor: null
}
},
computed: {
editorOptions() {
const options = Object.assign({}, defaultOptions, this.options)
options.initialEditType = this.mode
options.height = this.height
options.language = this.language
return options
}
},
watch: {
value(newValue, preValue) {
if (newValue !== preValue && newValue !== this.editor.getValue()) {
this.editor.setValue(newValue)
}
},
language(val) {
this.destroyEditor()
this.initEditor()
},
height(newValue) {
this.editor.height(newValue)
},
mode(newValue) {
this.editor.changeMode(newValue)
}
},
mounted() {
this.initEditor()
},
destroyed() {
this.destroyEditor()
},
methods: {
initEditor() {
this.editor = new Editor({
el: document.getElementById(this.id),
...this.editorOptions
})
if (this.value) {
this.editor.setValue(this.value)
}
this.editor.on('change', () => {
this.$emit('input', this.editor.getValue())
})
},
destroyEditor() {
if (!this.editor) return
this.editor.off('change')
this.editor.remove()
},
setValue(value) {
this.editor.setValue(value)
},
getValue() {
return this.editor.getValue()
},
setHtml(value) {
this.editor.setHtml(value)
},
getHtml() {
return this.editor.getHtml()
}
}
}
</script>

View File

@@ -1,134 +0,0 @@
<template>
<div class="upload-container">
<el-upload
:data="dataObj"
:multiple="false"
:show-file-list="false"
:on-success="handleImageSuccess"
class="image-uploader"
drag
action="https://httpbin.org/post"
>
<i class="el-icon-upload" />
<div class="el-upload__text">
将文件拖到此处<em>点击上传</em>
</div>
</el-upload>
<div class="image-preview">
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
<img :src="imageUrl+'?imageView2/1/w/200/h/200'">
<div class="image-preview-action">
<i class="el-icon-delete" @click="rmImage" />
</div>
</div>
</div>
</div>
</template>
<script>
import { getToken } from '@/api/qiniu'
export default {
name: 'SingleImageUpload',
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
tempUrl: '',
dataObj: { token: '', key: '' }
}
},
computed: {
imageUrl() {
return this.value
}
},
methods: {
rmImage() {
this.emitInput('')
},
emitInput(val) {
this.$emit('input', val)
},
handleImageSuccess() {
this.emitInput(this.tempUrl)
},
beforeUpload() {
const _self = this
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key
const token = response.data.qiniu_token
_self._data.dataObj.token = token
_self._data.dataObj.key = key
this.tempUrl = response.data.qiniu_url
resolve(true)
}).catch(err => {
console.log(err)
reject(false)
})
})
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
.upload-container {
width: 100%;
position: relative;
@include clearfix;
.image-uploader {
width: 60%;
float: left;
}
.image-preview {
width: 200px;
height: 200px;
position: relative;
border: 1px dashed #d9d9d9;
float: left;
margin-left: 50px;
.image-preview-wrapper {
position: relative;
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
.image-preview-action {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
cursor: default;
text-align: center;
color: #fff;
opacity: 0;
font-size: 20px;
background-color: rgba(0, 0, 0, .5);
transition: opacity .3s;
cursor: pointer;
text-align: center;
line-height: 200px;
.el-icon-delete {
font-size: 36px;
}
}
&:hover {
.image-preview-action {
opacity: 1;
}
}
}
}
</style>

View File

@@ -1,130 +0,0 @@
<template>
<div class="singleImageUpload2 upload-container">
<el-upload
:data="dataObj"
:multiple="false"
:show-file-list="false"
:on-success="handleImageSuccess"
class="image-uploader"
drag
action="https://httpbin.org/post"
>
<i class="el-icon-upload" />
<div class="el-upload__text">
Drag或<em>点击上传</em>
</div>
</el-upload>
<div v-show="imageUrl.length>0" class="image-preview">
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
<img :src="imageUrl">
<div class="image-preview-action">
<i class="el-icon-delete" @click="rmImage" />
</div>
</div>
</div>
</div>
</template>
<script>
import { getToken } from '@/api/qiniu'
export default {
name: 'SingleImageUpload2',
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
tempUrl: '',
dataObj: { token: '', key: '' }
}
},
computed: {
imageUrl() {
return this.value
}
},
methods: {
rmImage() {
this.emitInput('')
},
emitInput(val) {
this.$emit('input', val)
},
handleImageSuccess() {
this.emitInput(this.tempUrl)
},
beforeUpload() {
const _self = this
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key
const token = response.data.qiniu_token
_self._data.dataObj.token = token
_self._data.dataObj.key = key
this.tempUrl = response.data.qiniu_url
resolve(true)
}).catch(() => {
reject(false)
})
})
}
}
}
</script>
<style lang="scss" scoped>
.upload-container {
width: 100%;
height: 100%;
position: relative;
.image-uploader {
height: 100%;
}
.image-preview {
width: 100%;
height: 100%;
position: absolute;
left: 0px;
top: 0px;
border: 1px dashed #d9d9d9;
.image-preview-wrapper {
position: relative;
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
.image-preview-action {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
cursor: default;
text-align: center;
color: #fff;
opacity: 0;
font-size: 20px;
background-color: rgba(0, 0, 0, .5);
transition: opacity .3s;
cursor: pointer;
text-align: center;
line-height: 200px;
.el-icon-delete {
font-size: 36px;
}
}
&:hover {
.image-preview-action {
opacity: 1;
}
}
}
}
</style>

View File

@@ -1,157 +0,0 @@
<template>
<div class="upload-container">
<el-upload
:data="dataObj"
:multiple="false"
:show-file-list="false"
:on-success="handleImageSuccess"
class="image-uploader"
drag
action="https://httpbin.org/post"
>
<i class="el-icon-upload" />
<div class="el-upload__text">
将文件拖到此处<em>点击上传</em>
</div>
</el-upload>
<div class="image-preview image-app-preview">
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
<img :src="imageUrl">
<div class="image-preview-action">
<i class="el-icon-delete" @click="rmImage" />
</div>
</div>
</div>
<div class="image-preview">
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
<img :src="imageUrl">
<div class="image-preview-action">
<i class="el-icon-delete" @click="rmImage" />
</div>
</div>
</div>
</div>
</template>
<script>
import { getToken } from '@/api/qiniu'
export default {
name: 'SingleImageUpload3',
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
tempUrl: '',
dataObj: { token: '', key: '' }
}
},
computed: {
imageUrl() {
return this.value
}
},
methods: {
rmImage() {
this.emitInput('')
},
emitInput(val) {
this.$emit('input', val)
},
handleImageSuccess(file) {
this.emitInput(file.files.file)
},
beforeUpload() {
const _self = this
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key
const token = response.data.qiniu_token
_self._data.dataObj.token = token
_self._data.dataObj.key = key
this.tempUrl = response.data.qiniu_url
resolve(true)
}).catch(err => {
console.log(err)
reject(false)
})
})
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
.upload-container {
width: 100%;
position: relative;
@include clearfix;
.image-uploader {
width: 35%;
float: left;
}
.image-preview {
width: 200px;
height: 200px;
position: relative;
border: 1px dashed #d9d9d9;
float: left;
margin-left: 50px;
.image-preview-wrapper {
position: relative;
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
.image-preview-action {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
cursor: default;
text-align: center;
color: #fff;
opacity: 0;
font-size: 20px;
background-color: rgba(0, 0, 0, .5);
transition: opacity .3s;
cursor: pointer;
text-align: center;
line-height: 200px;
.el-icon-delete {
font-size: 36px;
}
}
&:hover {
.image-preview-action {
opacity: 1;
}
}
}
.image-app-preview {
width: 320px;
height: 180px;
position: relative;
border: 1px dashed #d9d9d9;
float: left;
margin-left: 50px;
.app-fake-conver {
height: 44px;
position: absolute;
width: 100%; // background: rgba(0, 0, 0, .1);
text-align: center;
line-height: 64px;
color: #fff;
}
}
}
</style>

View File

@@ -17,7 +17,6 @@
</el-upload>
</div>
</template>
<script>
import { fileFileApi } from '@/api/systemSetting'
import { getToken } from '@/utils/auth'

View File

@@ -1,6 +1,5 @@
<template>
<div>
{{multiple}}
<div class="acea-row" v-if="multiple">
<div
v-for="(item,index) in imageList"

View File

@@ -4,6 +4,7 @@
title="上传图片"
:visible.sync="visible"
width="896px"
:modal="false"
:before-close="handleClose"
>
<upload-index v-if="visible" :isMore="isMore" :modelName="modelName" @getImage="getImage" />

View File

@@ -2,81 +2,101 @@
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 v-else class="sidebar-title">{{ title }} </h1>
<img v-if="logoSmall" :src="logoSmall" class="sidebar-logo-small">
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 class="sidebar-title">{{ title }} </h1>
<img v-if="logo" :src="logo" class="sidebar-logo-big">
</router-link>
</transition>
</div>
</template>
<script>
export default {
name: 'SidebarLogo',
props: {
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
title: 'Vue Element Admin',
logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
import * as systemConfigApi from '@/api/systemConfig.js'
export default {
name: 'SidebarLogo',
props: {
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
title: 'Vue Element Admin',
logo: '',
logoSmall: ''
}
},
mounted() {
this.getLogo()
this.getSquareLogo()
},
methods: {
getLogo() {
systemConfigApi.configGetUniq({key: "site_logo"}).then(data => {
this.logo = data
})
},
getSquareLogo() {
systemConfigApi.configGetUniq({key: "site_logo_square"}).then(data => {
this.logoSmall = data
})
}
}
}
}
</script>
<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebar-logo-big{
width: auto;
height: 40px;
vertical-align: middle;
margin-right: 12px;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 50px;
line-height: 50px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
.sidebar-logo-container {
position: relative;
width: 100%;
height: 65px;
line-height: 65px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo-small {
width: 35px;
height: 35px;
vertical-align: middle;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

View File

@@ -8,7 +8,7 @@
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:unique-opened="true"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"

View File

@@ -216,7 +216,7 @@ export const constantRoutes = [
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: '主页', icon: 'dashboard', affix: true }
meta: { title: '控制台', icon: 'dashboard', affix: true }
}
]
},

View File

@@ -28,7 +28,7 @@ module.exports = {
* @type {boolean} true | false
* @description Whether show the logo in sidebar
*/
sidebarLogo: false,
sidebarLogo: true,
/**
* @type {string | array} 'production' | ['production', 'development']

View File

@@ -334,11 +334,11 @@ table .el-image{
//富文本编辑器弹框
.edui-shadow{
z-index: -1 !important;
//z-index: -1 !important;
}
.edui-default{
z-index: 4000;
//z-index: 4000;
}
.edui-dialog{
z-index: 4009 !important;
//z-index: 4009 !important;
}

View File

@@ -4,7 +4,7 @@
*/
export const page = {
limit: [10, 15, 20, 50, 100],
limit: [20, 40, 60, 80, 100],
page: 1,
layout: 'total, sizes, prev, pager, next, jumper'
}

View File

@@ -154,7 +154,7 @@
<script>
import { getToken } from '@/utils/auth'
import { replySaveApi, replyEditApi, replyInfoApi, replyListApi, keywordsInfoApi, replyUpdateApi } from '@/api/wxApi'
import { fileImageApi } from '@/api/systemSetting'
import { wechatUploadApi } from '@/api/systemSetting'
export default {
name: 'Index',
components: { },
@@ -278,7 +278,7 @@ export default {
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
fileImageApi(formData, {type: this.formValidate.type === 'image'?'image':'voice'}).then(res => {
wechatUploadApi(formData, {type: this.formValidate.type === 'image'?'image':'voice'}).then(res => {
loading.close()
this.formValidate.contents.mediaId = res.mediaId
this.formValidate.contents.srcUrl = res.url

View File

@@ -145,12 +145,12 @@ export default {
},
hadlerInitEditData() {
if (this.isEdit !== 1) return
const { author, cid, content, imageInput,
const { author, cid, content, imageInputs,
isBanner, isHot, shareSynopsis, shareTitle, sort, synopsis, title, url, id } = this.editData
this.pram.author = author
this.pram.cid = Number.parseInt(cid)
this.pram.content = content
this.pram.imageInput = imageInput
this.pram.imageInput = imageInputs
this.pram.isBanner = isBanner
this.pram.isHot = isHot
this.pram.shareSynopsis = shareSynopsis

View File

@@ -81,7 +81,9 @@
top="1vh"
width="80%"
destroy-on-close
:modal="false"
:close-on-click-modal="false"
class="articleModal"
>
<edit
v-if="editDialogConfig.visible"
@@ -187,6 +189,8 @@ export default {
}
</script>
<style scoped>
<style scoped lang="scss">
.articleModal{
z-index: 333 !important;
}
</style>

View File

@@ -11,7 +11,7 @@
<el-date-picker v-model="timeVal" value-format="yyyy/MM/dd" format="yyyy/MM/dd" size="small" type="daterange" placement="bottom-end" placeholder="自定义时间" style="width: 250px;" @change="onchangeTime" />
</el-form-item>
<el-form-item label="关键字:">
<el-input v-model="tableFrom.keyword" placeholder="请输入请输入姓名、电话、UID" class="selWidth" size="small">
<el-input v-model="tableFrom.keywords" placeholder="请输入请输入姓名、电话、UID" class="selWidth" size="small">
<el-button slot="append" icon="el-icon-search" size="small" @click="seachList" />
</el-input>
</el-form-item>
@@ -283,7 +283,7 @@
listLoading: true,
tableFrom: {
dateLimit: '',
keyword: '',
keywords: '',
page: 1,
limit: 20
},
@@ -357,7 +357,7 @@
// 具体日期
onchangeTimeSpread(e) {
this.timeValSpread = e
this.tableFrom.dateLimit = e ? this.timeValSpread.join('-') : ''
this.tableFrom.dateLimit = e ? this.timeValSpread.join(',') : ''
this.onName === 'man' ? this.getListSpread() : this.getSpreadOrderList()
},
onChanges() {
@@ -416,7 +416,7 @@
// 具体日期
onchangeTime(e) {
this.timeVal = e
this.tableFrom.dateLimit = e ? this.timeVal.join('-') : ''
this.tableFrom.dateLimit = e ? this.timeVal.join(',') : ''
this.tableFrom.page = 1
this.getList()
},

View File

@@ -7,7 +7,7 @@
</el-form-item>
<el-form-item label="优惠劵类型">
<el-radio-group v-model="ruleForm.useType">
<el-radio :label="1">通用</el-radio>
<el-radio :label="1">通用</el-radio>
<el-radio :label="2">商品券</el-radio>
<el-radio :label="3">品类券</el-radio>
</el-radio-group>
@@ -84,8 +84,8 @@
<el-form-item label="领取方式" prop="resource">
<el-radio-group v-model="ruleForm.type">
<el-radio :label="1">手动领取</el-radio>
<el-radio :label="2">新人</el-radio>
<el-radio :label="3">赠送</el-radio>
<el-radio :label="2">新人</el-radio>
<el-radio :label="3">赠送</el-radio>
<!--<el-radio :label="4">付费会员卷</el-radio>-->
</el-radio-group>
</el-form-item>

View File

@@ -5,19 +5,30 @@
<div class="filter-container">
<el-form :inline="true">
<el-form-item label="使用状态:" class="mr10">
<el-select v-model="tableFromIssue.status" placeholder="请选择评价状态" clearable class="selWidth" @change="seachList">
<el-select v-model="tableFromIssue.status" placeholder="请选择使用状态" clearable class="selWidth" @change="seachList">
<el-option label="已使用" value="1" />
<el-option label="未使用" value="0" />
<el-option label="已过期" value="2" />
</el-select>
</el-form-item>
<el-form-item label="领取人:" class="mr10">
<el-input v-model="tableFromIssue.coupon_id" placeholder="请输入领取人" class="selWidth">
<el-button size="mini" slot="append" icon="el-icon-search" @click="seachList"/>
</el-input>
<el-form-item label="领取人:">
<el-select v-model="tableFromIssue.uid" class="selWidth" reserve-keyword remote filterable
:remote-method="remoteMethod" :loading="loading" placeholder="请输入用户名称" clearable @change="seachList">
<el-option
v-for="item in options"
:key="item.uid"
:label="item.nickname"
:value="item.uid">
</el-option>
</el-select>
</el-form-item>
<!--<el-form-item label="领取人:" class="mr10">-->
<!--<el-input v-model="tableFromIssue.uid" placeholder="请输入领取人" class="selWidth">-->
<!--<el-button size="mini" slot="append" icon="el-icon-search" @click="seachList"/>-->
<!--</el-input>-->
<!--</el-form-item>-->
<el-form-item label="优惠劵:" class="mr10">
<el-input v-model="tableFromIssue.name" placeholder="请输入优惠劵" class="selWidth">
<el-input v-model="tableFromIssue.name" placeholder="请输入优惠劵" class="selWidth" clearable>
<el-button slot="append" icon="el-icon-search" @click="seachList"/>
</el-input>
</el-form-item>
@@ -109,6 +120,7 @@
<script>
import { couponUserListApi } from '@/api/marketing'
import { roterPre } from '@/settings'
import { userListApi } from '@/api/user'
export default {
name: 'CouponUser',
filters: {
@@ -139,19 +151,35 @@
tableFromIssue: {
page: 1,
limit: 20,
uid: '',
name: '',
status: ''
},
issueData: {
data: [],
total: 0
}
},
loading: false,
options: []
}
},
mounted() {
this.getIssueList()
},
methods: {
remoteMethod(query) {
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
userListApi({keywords: query, page: 1, limit: 10}).then(res => {
this.options = res.list
})
}, 200);
} else {
this.options = [];
}
},
seachList() {
this.tableFromIssue.page = 1
this.getIssueList()

View File

@@ -2,7 +2,7 @@
<div class="divBox">
<el-card class="box-card">
<zb-parser
:form-id="109"
:form-id="formId"
:is-create="isCreate"
:edit-data="editData"
@submit="handlerSubmit"
@@ -13,21 +13,51 @@
<script>
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
import { smsSaveApi } from '@/api/sms'
import { configSaveForm, configInfo } from '@/api/systemConfig.js'
export default {
name: "integralconfig",
components: { zbParser },
data() {
return {
isCreate: 0,
editData: {}
editData: {},
formId: 109
}
},
mounted() {
this.getFormInfo()
},
methods: {
handlerSubmit(formValue) {
smsSaveApi(formValue).then(data => {
this.$message.success('新增成功')
this.editData = {}
handlerSubmit(data) {
const tempArr = []
for (var key in data) {
const obj = {}
obj.name = key
obj.title = key
obj.value = data[key]
tempArr.push(obj)
}
const _pram = {
'fields': tempArr,
'id': this.formId,
'sort': 0,
'status': true
}
console.log(_pram)
configSaveForm(_pram).then(res => {
this.getFormInfo()
this.$message.success('操作成功')
})
},
// 获取表单详情
getFormInfo() {
configInfo({ id: this.formId }).then(res => {
this.isShow = false
this.editData = res
this.isCreate = 1
setTimeout(() => { // 让表单重复渲染待编辑数据
this.isShow = true
}, 80)
})
}
}

View File

@@ -92,22 +92,22 @@
/>
<el-table-column
label="商品信息"
min-width="330"
min-width="400"
>
<!--<template slot-scope="scope">-->
<!--<div v-if="scope.row.productList.length">-->
<!--<div v-for="(val, i ) in scope.row.productList" :key="i" class="tabBox acea-row row-middle">-->
<!--<div class="demo-image__preview">-->
<!--<el-image-->
<!--:src="val.info.productInfo.image"-->
<!--:preview-src-list="imgList"-->
<!--/>-->
<!--</div>-->
<!--&lt;!&ndash;<span class="tabBox_tit">{{ val.info.productInfo.store_name + ' | ' }}{{ val.info.productInfo.attrInfo.suk ? val.info.productInfo.attrInfo.suk:'-' }}</span>&ndash;&gt;-->
<!--&lt;!&ndash;<span class="tabBox_pice">{{ '¥'+ val.info.productInfo.attrInfo.price ? val.info.productInfo.attrInfo.price:'-' + ' x '+ val.info.cart_num }}</span>&ndash;&gt;-->
<!--</div>-->
<!--</div>-->
<!--</template>-->
<template slot-scope="scope">
<div v-if="scope.row.productList.length">
<div v-for="(val, i ) in scope.row.productList" :key="i" class="tabBox acea-row row-middle">
<div class="demo-image__preview">
<el-image
:src="val.info.productInfo.image"
:preview-src-list="imgList"
/>
</div>
<span class="tabBox_tit mr10">{{ val.info.productInfo.storeName + ' | ' }}{{ val.info.productInfo.attrInfo.suk ? val.info.productInfo.attrInfo.suk:'-' }}</span>
<span class="tabBox_pice">{{ '¥'+ val.info.productInfo.attrInfo.price ? val.info.productInfo.attrInfo.price + ' x '+ val.info.cartNum : '-' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column
prop="payPrice"

View File

@@ -12,7 +12,7 @@
<el-form-item label="快递公司:" prop="expressId"
:rules="[{ required: true, message: '请选择快递公司', trigger: 'change' }]">
<el-select v-model="formItem.expressId" style="width:80%;">
<el-option v-for="(item,i) in express" :value="item.id" :key="i">{{ item.name }}</el-option>
<el-option v-for="(item,i) in express" :value="item.id" :key="i" :label="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item label="快递单号:" prop="expressCode"
@@ -69,7 +69,7 @@
},
// 物流公司列表
getList () {
expressList({ page: 1, limit: 999}).then(async res => {
expressList({ page: 1, limit: 999, isShow:true }).then(async res => {
this.express = res.list
})
},

View File

@@ -51,11 +51,8 @@
<el-table-column
label="发送时间"
min-width="150"
>
<template slot-scope="scope">
<span>{{scope.row.creatTime}}</span>
</template>
</el-table-column>
prop="createTime"
/>
<el-table-column
prop="resultcode"
label="状态码"

View File

@@ -1,43 +1,41 @@
<template>
<div class="divBox">
<el-card v-if="isShowList" v-loading="fullscreenLoading" class="box-card">
<div slot="header" class="clearfix">
<div class="content acea-row row-middle">
<div class="demo-basic--circle acea-row row-middle">
<el-avatar :size="50" :src="circleUrl" class="mr20" />
<div class="dashboard-workplace-header-tip">
<div class="dashboard-workplace-header-tip-title">{{ smsAccount }}祝您每一天开心</div>
<div class="dashboard-workplace-header-tip-desc">
<span class="mr10">修改密码</span>
<span @click="signOut">退出登录</span>
</div>
<div class="content acea-row row-middle">
<div class="demo-basic--circle acea-row row-middle">
<el-avatar :size="50" :src="circleUrl" class="mr20" />
<div class="dashboard-workplace-header-tip">
<div class="dashboard-workplace-header-tip-title">{{ smsAccount }}祝您每一天开心</div>
<div class="dashboard-workplace-header-tip-desc">
<span class="mr10">修改密码</span>
<span @click="signOut">退出登录</span>
</div>
</div>
<div class="dashboard-workplace-header-extra">
<el-row type="flex" justify="center" align="middle" :gutter="12">
<el-col :span="8">
</div>
<div class="dashboard-workplace-header-extra">
<el-row type="flex" justify="center" align="middle" :gutter="12">
<el-col :span="8">
<span class="pfont acea-row row-middle">
<el-avatar icon="el-icon-user-solid" size="small" class="mr10" />
<span>剩余条数</span>
</span>
<span class="rR" v-text="numbers" />
</el-col>
<el-col :span="8">
<span class="rR" v-text="numbers" />
</el-col>
<el-col :span="8">
<span class="pfont acea-row row-middle">
<el-avatar icon="el-icon-user-solid" size="small" class="mr10" />
<span>已发送</span>
</span>
<span class="rR" v-text="sendTotal" />
</el-col>
<el-col :span="8">
<span class="rR" v-text="sendTotal" />
</el-col>
<el-col :span="8">
<span class="pfont acea-row row-middle">
<el-avatar icon="el-icon-user-solid" size="small" class="mr10" />
<span>总条数</span>
</span>
<span class="rR" v-text="amount" />
</el-col>
</el-row>
</div>
<span class="rR" v-text="amount" />
</el-col>
</el-row>
</div>
</div>
</el-card>

View File

@@ -3,18 +3,20 @@
<div class="divBox" v-if="isLogin">
<el-card v-loading="fullscreenLoading" class="box-card">
<div slot="header" class="clearfix">
<div class="filter-container">
<div class="demo-input-suffix acea-row">
<span class="seachTiele">模板状态</span>
<el-select v-model="tableFrom.status" placeholder="请选择" clearable class="filter-item selWidth mr20" @change="userSearchs">
<el-option value="1">可用</el-option>
<el-option value="0">不可用</el-option>
</el-select>
<span class="seachTiele">模板名称</span>
<el-input v-model="tableFrom.title" placeholder="请输入商品名称,关键字,产品编号" class="selWidth">
<el-button slot="append" icon="el-icon-search" @change="userSearchs" />
</el-input>
</div>
<div class="container">
<el-form :inline="true">
<el-form-item label="模板状态:" class="mr10">
<el-select v-model="tableFrom.status" placeholder="请选择" clearable class="filter-item selWidth mr20" @change="userSearchs">
<el-option value="1" label="可用"></el-option>
<el-option value="0" label="不可用"></el-option>
</el-select>
</el-form-item>
<el-form-item label="模板名称:" class="mr10">
<el-input v-model="tableFrom.title" placeholder="请输入模板名称" class="selWidth">
<el-button slot="append" icon="el-icon-search" @click="userSearchs" />
</el-input>
</el-form-item>
</el-form>
</div>
<el-button size="mini" type="primary" @click="add">添加短信模板</el-button>
</div>
@@ -105,8 +107,8 @@ export default {
filters: {
statusFilter(status) {
const statusMap = {
0: '没有',
1: ''
0: '不可用',
1: '可用'
}
return statusMap[status]
},

View File

@@ -946,6 +946,7 @@
// 提交
handleSubmit (name) {
this.onChangeGroup()
if( this.formValidate.specType && this.formValidate.attr.length < 1 ) return this.$message.warning("请填写多规格属性!");
this.formValidate.cateId = this.formValidate.cateIds.join(',')
this.formValidate.sliderImage = JSON.stringify(this.formValidate.sliderImages)
if(this.formValidate.specType){

View File

File diff suppressed because it is too large Load Diff

View File

@@ -98,6 +98,7 @@
>
<template slot-scope="scope">
<el-switch
:disabled="tableFrom.type === '5'"
v-model="scope.row.isShow"
:active-value="true"
:inactive-value="false"
@@ -120,7 +121,8 @@
<router-link :to="{path: '/store/list/creatProduct/' + scope.row.id}">
<el-button type="text" size="small" class="mr10">编辑</el-button>
</router-link>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
<el-button v-if="tableFrom.type === '5'" type="text" size="small" @click="handleRestore(scope.row.id, scope.$index)">恢复商品</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">{{ tableFrom.type === '5' ? '删除' : '加入回收站' }}</el-button>
</template>
</el-table-column>
</el-table>
@@ -148,7 +150,7 @@
</template>
<script>
import { productLstApi, productDeleteApi, categoryApi, putOnShellApi, offShellApi, productHeadersApi, productExportApi } from '@/api/store'
import { productLstApi, productDeleteApi, categoryApi, putOnShellApi, offShellApi, productHeadersApi, productExportApi, restoreApi } from '@/api/store'
import { getToken } from '@/utils/auth'
import taoBao from './taoBao'
export default {
@@ -188,6 +190,16 @@ export default {
this.getCategorySelect()
},
methods: {
handleRestore(id) {
this.$modalSure("恢复商品").then(() => {
restoreApi(id)
.then((res) => {
this.$message.success('操作成功');
this.goodHeade();
this.getList();
})
});
},
seachList() {
this.tableFrom.page = 1
this.getList()

View File

@@ -17,15 +17,27 @@
</el-select>
</el-form-item>
<el-form-item label="商品搜索:" class="mr10">
<el-input v-model="tableFrom.productId" placeholder="请输入商品名称,关键字,产品编号" class="selWidth" size="small">
<el-input v-model="tableFrom.productSearch" placeholder="请输入商品名称,商品id" class="selWidth" size="small">
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
</el-input>
</el-form-item>
<el-form-item label="用户名称:">
<el-input v-model="tableFrom.nickname" placeholder="请输入用户名称" class="selWidth" size="small">
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
</el-input>
{{uids}}
<el-select v-model="uids" style="width: 500px" reserve-keyword multiple remote filterable
:remote-method="remoteMethod" :loading="loading" placeholder="请输入用户名称" clearable @change="seachList">
<el-option
v-for="item in options"
:key="item.uid"
:label="item.nickname"
:value="item.uid">
</el-option>
</el-select>
</el-form-item>
<!--<el-form-item label="用户名称:">-->
<!--<el-input v-model="tableFrom.nickname" placeholder="请输入用户名称" class="selWidth" size="small">-->
<!--<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>-->
<!--</el-input>-->
<!--</el-form-item>-->
</el-form>
</div>
<el-button size="small" type="primary" @click="add">添加虚拟评论</el-button>
@@ -120,6 +132,7 @@
import creatComment from './creatComment.vue'
import { categoryApi, replyListApi, replyDeleteApi, replyCommentApi } from '@/api/store'
import { formatDates } from '@/utils/index';
import { userListApi } from '@/api/user'
export default {
name: 'StoreComment',
filters: {
@@ -163,11 +176,14 @@ export default {
limit: 20,
isReply: '',
dateLimit: '',
nickname: '',
productId:'',
uid: '',
productSearch:'',
isDel: false
},
timeVal: []
timeVal: [],
loading: false,
uids: [],
options: []
}
},
mounted() {
@@ -176,6 +192,19 @@ export default {
this.getCategorySelect()
},
methods:{
remoteMethod(query) {
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
userListApi({keywords: query, page: 1, limit: 10}).then(res => {
this.options = res.list
})
}, 200);
} else {
this.options = [];
}
},
seachList() {
this.tableFrom.page = 1
this.getList()
@@ -278,6 +307,7 @@ export default {
// 列表
getList() {
this.listLoading = true
this.tableFrom.uid = this.uids.join(',')
replyListApi(this.tableFrom).then(res => {
this.tableData.data = res.list
this.tableData.total = res.total

View File

@@ -7,7 +7,7 @@
<el-form-item label="管理员密码" prop="pwd">
<el-input
v-model="pram.pwd"
placeholder="管理员密码,不更改可以不填写"
placeholder="管理员密码"
clearable
@input="handlerPwdInput"
@clear="handlerPwdInput"
@@ -77,7 +77,7 @@ export default {
pwd: null,
repwd: null,
realName: null,
roles: null,
roles: [],
status: null,
id: null
},
@@ -88,7 +88,7 @@ export default {
pwd: [{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] }],
repwd: [{ required: true, message: '确认密码密码', validator: validatePass, trigger: ['blur', 'change'] }],
realName: [{ required: true, message: '管理员姓名', trigger: ['blur', 'change'] }],
roles: [{ required: true, message: '管理员身份', trigger: ['blur', 'change'] }]
roles: [{ required: true, message: '管理员身份', type: 'array', trigger: ['blur', 'change'] }]
}
}
},
@@ -103,7 +103,8 @@ export default {
handleGetRoleList() {
const _pram = {
page: 1,
limit: constants.page.limit[4]
limit: constants.page.limit[4],
status: 1
}
roleApi.getRoleList(_pram).then(data => {
this.roleList = data

View File

@@ -3,7 +3,7 @@
<el-card class="box-card">
<el-form inline size="small">
<el-form-item>
<el-select v-model="listPram.realName" placeholder="身份" clearable class="selWidth">
<el-select v-model="listPram.roles" placeholder="身份" clearable class="selWidth">
<el-option
v-for="item in roleList.list"
:key="item.id"
@@ -33,10 +33,10 @@
</el-select>
</el-form-item>
<el-form-item>
<el-input v-model="listPram.roleName" placeholder="姓名或者账号" clearable class="selWidth"/>
<el-input v-model="listPram.realName" placeholder="姓名或者账号" clearable class="selWidth"/>
</el-form-item>
<el-form-item>
<el-button size="mini" type="primary" @click.native="handleGetAdminList">查询</el-button>
<el-button size="mini" type="primary" @click="handleSearch">查询</el-button>
</el-form-item>
</el-form>
<el-form inline>
@@ -136,7 +136,7 @@ export default {
roles: null,
status: null,
page: 1,
limit: constants.page.limit[1]
limit: constants.page.limit[0]
},
roleList: [],
menuList: [],
@@ -152,12 +152,18 @@ export default {
this.handleGetRoleList()
},
methods: {
handleSearch() {
this.listPram.page = 1
this.handleGetAdminList()
},
handleSizeChange(val) {
this.listPram.limit = val
this.handleGetAdminList()
this.handleGetRoleList(this.listPram)
},
handleCurrentChange(val) {
this.listPram.page = val
this.handleGetAdminList()
this.handleGetRoleList(this.listPram)
},
handleGetRoleList() {
@@ -171,15 +177,15 @@ export default {
},
handlerOpenDel(rowData) {
this.$confirm('确认删除当前数据').then(() => {
const _pram = { id: rowData.id, isDel: 1, roles: Array.of(rowData.roles) }
systemAdminApi.adminUpdate(_pram).then(data => {
const _pram = { id: rowData.id}
systemAdminApi.adminDel(_pram).then(data => {
this.$message.success('删除数据成功')
this.handleGetAdminList()
})
})
},
handleGetAdminList() {
systemAdminApi.adminList(this.listPram).then(data => {
systemAdminApi.adminList( this.listPram ).then(data => {
this.listData = data
// this.handlerGetMenuList()
})

View File

@@ -88,7 +88,7 @@ export default {
updateTime: null,
level: null,
page: 1,
limit: constants.page.limit[1],
limit: constants.page.limit[0],
roleName: null,
rules: null,
status: null

View File

@@ -4,9 +4,19 @@
<div slot="header" class="clearfix">
<div class="container">
<el-form ref="form" inline :model="form">
<el-form-item label="搜索:">
<el-input v-model="form.name" placeholder="请输入内容" class="selWidth" size="small">
<el-button slot="append" size="small" icon="el-icon-search" @click="getExpressList" />
<el-form-item label="状态">
<el-select v-model="form.isShow" placeholder="状态" clearable @change="handlerSearch" class="selWidth">
<el-option
v-for="item in constants.switchStatus"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="关键字:">
<el-input v-model="form.keywords" placeholder="请输入关键字" class="selWidth" size="small">
<el-button slot="append" size="small" icon="el-icon-search" @click="handlerSearch" />
</el-input>
</el-form-item>
</el-form>
@@ -67,7 +77,7 @@
</el-table>
<div class="block-pagination">
<el-pagination
:page-sizes="[12, 20, 40, 60]"
:page-sizes="[20, 40, 60, 80]"
:page-size="tableData.limit"
:current-page="tableData.page"
layout="total, sizes, prev, pager, next, jumper"
@@ -78,7 +88,7 @@
</div>
</el-card>
<el-dialog
title="提示"
title="添加物流公司"
:visible.sync="dialogVisible"
width="700px"
:before-close="handleClose"
@@ -92,19 +102,22 @@
import parser from '@/components/FormGenerator/components/parser/Parser'
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
import * as logistics from '@/api/logistics.js'
import * as constants from '@/utils/constants.js'
export default {
name: 'CompanyList',
components: { parser },
data() {
return {
constants,
// 表单
formConf: { fields: [] },
form: {
name: ''
keywords: '',
isShow: null
},
tableData: {},
page: 1,
limit: 12,
limit: 20,
loading: false,
dialogVisible: false,
fromType: 'add',
@@ -118,13 +131,18 @@ export default {
this.getExpressList()
},
methods: {
handlerSearch() {
this.page = 1
this.getExpressList()
},
// 获取物流公司列表
getExpressList() {
this.loading = true
logistics.expressList({
page: this.page,
limit: this.limit,
keywords: this.form.name
keywords: this.form.keywords,
isShow: this.form.isShow
}).then(res => {
this.loading = false
this.tableData = res
@@ -182,7 +200,6 @@ export default {
})
} else {
data.id = this.editId
console.log(data)
logistics.expressUpdate(data).then(res => {
this.handleClose()
this.getExpressList()

View File

@@ -4,8 +4,8 @@
<div slot="header" class="clearfix">
<div class="container">
<el-form ref="form" inline :model="form">
<el-form-item label="搜索">
<el-input v-model="form.name" placeholder="请输入内容" class="selWidth" size="small">
<el-form-item label="模板名称">
<el-input v-model="form.keywords" placeholder="请输入模板名称" class="selWidth" size="small">
<el-button slot="append" icon="el-icon-search" @click="handleSearch" />
</el-input>
</el-form-item>
@@ -26,7 +26,7 @@
/>
<el-table-column
label="模板名称"
min-width="150"
min-width="180"
prop="name"
/>
<el-table-column
@@ -47,11 +47,11 @@
<p>{{ row.appoint | statusFilter }}</p>
</template>
</el-table-column>
<el-table-column
min-width="120"
label="指定区域不配送"
prop="type"
/>
<!--<el-table-column-->
<!--min-width="120"-->
<!--label="指定区域不配送"-->
<!--prop="type"-->
<!--/>-->
<el-table-column
label="排序"
min-width="100"
@@ -76,7 +76,7 @@
</el-table>
<div class="block-pagination">
<el-pagination
:page-sizes="[12, 20, 40, 60]"
:page-sizes="[20, 40, 60, 80]"
:page-size="tableData.limit"
:current-page="tableData.page"
layout="total, sizes, prev, pager, next, jumper"
@@ -117,11 +117,11 @@ export default {
return {
dialogVisible: false,
form: {
name: ''
keywords: ''
},
tableData: '',
page: 1,
limit: 12,
limit: 20,
loading: false
}
},
@@ -136,6 +136,7 @@ export default {
this.$refs.addTemplates.changType(0, this.te)
},
handleSearch() {
this.page = 1
this.getDataList()
},
// 分页
@@ -151,7 +152,7 @@ export default {
getDataList() {
this.loading = true
logistics.shippingTemplatesList({
name: this.form.name,
keywords: this.form.keywords,
page: this.page,
limit: this.limit
}).then(res => {

View File

@@ -1,8 +1,7 @@
<template>
<div class="divBox">
<el-card class="box-card">
{{activeNamel1}}
<el-tabs v-model="activeNamel1" @tab-click="handleTabClick">
<el-tabs v-model="activeNamel1" @tab-click="handleTabClick" v-loading="loading">
<el-tab-pane
v-for="tab,index in treeList"
:key="index"
@@ -26,7 +25,6 @@
</template>
<!-- 正常配置渲染-->
<template v-else>
{{activeNamel2}}
<el-tabs v-if="tab.child.length > 0" v-model="activeNamel2"
type="border-card" @tab-click="handleItemTabClick">
<el-tab-pane
@@ -75,6 +73,7 @@ export default {
components: {Template, parser },
data() {
return {
loading: false,
formConf: { content: { fields: [] }, id: null, render: false, isEdit: false },
formConfChild: { content: { fields: [] }, id: null, render: false, isEdit: false },
activeNamel1: null,
@@ -88,7 +87,6 @@ export default {
}
},
mounted() {
console.log(this.$route.path.split("/")[1])
this.handlerGetTreeList()
this.getCurrentUploadSelectedFlag()
},
@@ -137,11 +135,15 @@ export default {
this.currentEditId = id
this.formConf.content = { fields: [] }
this.formConf.render = false
this.loading = true
systemFormConfigApi.getFormConfigInfo(formPram).then(data => {
const { id, name, info, content } = data
this.formConf.content = JSON.parse(content)
this.formConf.id = id
this.handlerGetSettingInfo(id, 1)
this.loading = false
}).catch(() =>{
this.loading = false
})
},
handleItemTabClick(tab, event) { //这里对tabs=tab.name和radio=id做了兼容
@@ -154,11 +156,15 @@ export default {
this.currentEditId = id
this.formConfChild.content = { fields: [] }
this.formConfChild.render = false
this.loading = true
systemFormConfigApi.getFormConfigInfo(formPram).then(data => {
const { id, name, info, content } = data
this.formConfChild.content = JSON.parse(content)
this.formConfChild.id = id
this.handlerGetSettingInfo(id, 2)
this.loading = false
}).catch(() =>{
this.loading = false
})
},
handlerGetSettingInfo(id, level) {
@@ -203,6 +209,7 @@ export default {
},
handlerGetTreeList() {
const _pram = { type: constants.categoryType[5].value, status: -1 }
this.loading = true
categoryApi.treeCategroy(_pram).then(data => {
this.treeList = this.handleAddArrt(data)
if (this.treeList.length > 0) this.activeNamel1 = this.treeList[0].extra
@@ -214,6 +221,9 @@ export default {
} else {
this.handlerGetLevel1FormConfig(this.treeList[0].extra)
}
this.loading = false
}).catch(() =>{
this.loading = false
})
},
handleAddArrt(treeData) {

View File

@@ -27,19 +27,19 @@
</el-form-item>
<el-form-item label="用户等级:">
<el-select v-model="ruleForm.level" placeholder="请选择" class="selWidth" clearable filterable>
<el-option value="">全部</el-option>
<el-option value="" label="全部"></el-option>
<el-option :value="item.id" v-for="(item, index) in levelList" :key="index" :label="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item label="用户分组:">
<el-select v-model="ruleForm.groupId" placeholder="请选择" class="selWidth" clearable filterable>
<el-option value="">全部</el-option>
<el-option value="" label="全部"></el-option>
<el-option :value="item.id" v-for="(item, index) in groupList" :key="index" :label="item.groupName"></el-option>
</el-select>
</el-form-item>
<el-form-item label="用户标签:">
<el-select v-model="labelData" placeholder="请选择" class="selWidth" clearable filterable multiple >
<el-option value="">全部</el-option>
<el-option value="" label="全部"></el-option>
<el-option :value="item.id" v-for="(item, index) in labelLists" :key="index" :label="item.name"></el-option>
</el-select>
</el-form-item>
@@ -148,8 +148,8 @@
this.ruleForm.tagId=this.labelData.join(',')
userUpdateApi({id: this.ruleForm.id},this.ruleForm).then(async res => {
this.$message.success('编辑成功')
this.$parent.visible = false
this.$parent.getList()
this.$parent.$parent.visible = false
this.$parent.$parent.getList()
})
} else {
return false;

View File

@@ -6,7 +6,7 @@
<el-tab-pane :label="item.name" :name="item.type.toString()" v-for="(item,index) in headeNum" :key="index"/>
</el-tabs>
<div class="container">
<el-form inline size="small" :label-position="labelPosition" label-width="100px">
<el-form inline size="small" :model="userFrom" ref="userFrom" :label-position="labelPosition" label-width="100px">
<el-row>
<el-col :xs="24" :sm="24" :md="24" :lg="18" :xl="18">
<el-col v-bind="grid">
@@ -27,7 +27,6 @@
<el-col v-bind="grid">
<el-form-item label="用户等级:">
<el-select v-model="levelData" placeholder="请选择" class="selWidth" clearable filterable multiple>
<el-option value="">全部</el-option>
<el-option :value="item.id" v-for="(item, index) in levelList" :key="index" :label="item.name"></el-option>
</el-select>
</el-form-item>
@@ -35,7 +34,6 @@
<el-col v-bind="grid">
<el-form-item label="用户分组:">
<el-select v-model="groupData" placeholder="请选择" class="selWidth" clearable filterable multiple>
<el-option value="">全部</el-option>
<el-option :value="item.id" v-for="(item, index) in groupList" :key="index" :label="item.groupName"></el-option>
</el-select>
</el-form-item>
@@ -43,7 +41,6 @@
<el-col v-bind="grid">
<el-form-item label="用户标签:">
<el-select v-model="labelData" placeholder="请选择" class="selWidth" clearable filterable multiple>
<el-option value="">全部</el-option>
<el-option :value="item.id" v-for="(item, index) in labelLists" :key="index" :label="item.name"></el-option>
</el-select>
</el-form-item>
@@ -104,23 +101,23 @@
<el-col v-bind="grid">
<el-form-item label="访问情况:">
<el-select v-model="userFrom.accessType" placeholder="请选择" class="selWidth" clearable>
<el-option value="">全部</el-option>
<el-option value="visitno">时间段未访问</el-option>
<el-option value="visit">时间段访问过</el-option>
<el-option value="add_time">首次访问</el-option>
<el-option value="" label="全部"></el-option>
<el-option value="visitno" label="时间段未访问"></el-option>
<el-option value="visit" label="时间段访问过"></el-option>
<el-option value="add_time" label="首次访问"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col v-bind="grid">
<el-form-item label="消费情况:">
<el-select v-model="userFrom.payCount" placeholder="请选择" class="selWidth" clearable>
<el-option value="">全部</el-option>
<el-option value="-1">0</el-option>
<el-option value="0">1+</el-option>
<el-option value="1">2+</el-option>
<el-option value="2">3+</el-option>
<el-option value="3">4+</el-option>
<el-option value="4">5+</el-option>
<el-option value="" label="全部"></el-option>
<el-option value="-1" label="0"></el-option>
<el-option value="0" label="1+"></el-option>
<el-option value="1" label="2+"></el-option>
<el-option value="2" label="3+"></el-option>
<el-option value="3" label="4+"></el-option>
<el-option value="4" label="5+"></el-option>
</el-select>
</el-form-item>
</el-col>
@@ -216,7 +213,7 @@
<el-table-column
prop="uid"
label="ID"
min-width="50"
min-width="80"
/>
<el-table-column label="头像" min-width="80">
<template slot-scope="scope">
@@ -230,10 +227,15 @@
</template>
</el-table-column>
<el-table-column
prop="nickname"
label="姓名"
min-width="150"
/>
>
<template slot-scope="scope">
<span>{{scope.row.nickname | filterEmpty}}</span>
<span></span>
<span></span>
</template>
</el-table-column>
<el-table-column
label="用户等级"
min-width="100"
@@ -265,6 +267,11 @@
label="余额"
min-width="100"
/>
<el-table-column
prop="integral"
label="积分"
min-width="100"
/>
<el-table-column label="操作" min-width="200" fixed="right" align="center">
<template slot-scope="scope">
<el-button type="text" size="small" @click="onDetails(scope.row.uid)">账户详情</el-button>
@@ -493,9 +500,9 @@
},
headeNum: [
{ 'type': '', 'name': '全部用户' },
{ 'type': 'wechat', 'name': '微信公众号' },
{ 'type': 'routine', 'name': '微信小程序' },
{ 'type': 'h5', 'name': 'H5' }
{ 'type': 'wechat', 'name': '微信公众号用户' },
{ 'type': 'routine', 'name': '微信小程序用户' },
{ 'type': 'h5', 'name': 'H5用户' }
],
listLoading: true,
tableData: {
@@ -505,8 +512,7 @@
loginType: '',
userFrom: {
labelId: '',
loginType: '',
status: true,
userType: '',
sex: '',
isPromoter: '',
country: '',
@@ -569,6 +575,29 @@
this.getCityList()
},
methods: {
reset(formName) {
this.userFrom = {
labelId: '',
userType: '',
sex: '',
isPromoter: '',
country: '',
payCount: '',
accessType: '',
dateLimit: '',
keywords: '',
province: '',
city: '',
page: 1,
limit: 15,
level: '',
groupId: ''
}
this.levelData = []
this.groupData = []
this.labelData = []
this.getList()
},
// 列表
getCityList() {
logistics.cityListTree().then(res => {
@@ -624,6 +653,7 @@
this.$message.success('设置成功')
this.loadingBtn = false
this.handlePointClose()
this.getList()
}).catch(() => {
this.loadingBtn = false
})
@@ -741,8 +771,8 @@
// 列表
getList() {
this.listLoading = true
if(this.loginType == 0) this.loginType =''
this.userFrom.loginType = this.loginType
this.userFrom.userType = this.loginType
if(this.loginType == 0) this.userFrom.userType =''
this.userFrom.level = this.levelData.join(',')
this.userFrom.groupId = this.groupData.join(',')
this.userFrom.labelId = this.labelData.join(',')

View File

@@ -220,5 +220,5 @@ export function getLiveList(page,limit) {
* 获取小程序二维码
*/
export function getQrcode(data) {
return request.post('qrcode/get',data);
return request.post('qrcode/get',data,{ noAuth: true });
}

View File

@@ -5,14 +5,16 @@ import request from "@/utils/request.js";
* @param numType boolean true 购物车数量,false=购物车产品数量
*/
export function getCartCounts(numType) {
return request.get("cart/count", { numType: numType === undefined ? true : numType });
return request.get("cart/count", {
numType: numType === undefined ? true : numType
});
}
/**
* 获取购物车列表
*
*/
export function getCartList(data) {
return request.get("cart/list",data);
return request.get("cart/list", data);
}
/**
@@ -21,108 +23,121 @@ export function getCartList(data) {
* @param int number 修改数量
*/
export function changeCartNum(cartId, number) {
return request.post("cart/num", { id: cartId, number: number },{},1);
return request.post("cart/num", {
id: cartId,
number: number
}, {}, 1);
}
/**
* 清除购物车
* @param object ids join(',') 切割成字符串
*/
export function cartDel(ids){
if (typeof ids === 'object')
ids = ids.join(',');
return request.post('cart/delete', { ids: ids},{},1);
*/
export function cartDel(ids) {
if (typeof ids === 'object')
ids = ids.join(',');
return request.post('cart/delete', {
ids: ids
}, {}, 1);
}
/**
* 购物车重选提交
*
*/
export function getResetCart(data){
return request.post('cart/resetcart', data);
*/
export function getResetCart(data) {
return request.post('cart/resetcart', data);
}
/**
* 订单列表
* @param object data
*/
export function getOrderList(data){
return request.get('order/list',data);
*/
export function getOrderList(data) {
return request.get('order/list', data);
}
/**
* 订单产品信息
* @param string unique
*/
export function orderProduct(data){
return request.post('order/product', data);
*/
export function orderProduct(data) {
return request.post('order/product', data);
}
/**
* 订单评价
* @param object data
*
*/
export function orderComment(data){
return request.post('order/comment',data);
*/
export function orderComment(data) {
return request.post('order/comment', data);
}
/**
* 订单支付
* @param object data
*/
export function orderPay(data){
return request.post('order/pay',data);
*/
export function orderPay(data) {
return request.post('order/pay', data);
}
/**
* 订单统计数据
*/
export function orderData(){
return request.get('order/data')
*/
export function orderData() {
return request.get('order/data')
}
/**
* 订单取消
* @param string id
*
*/
export function orderCancel(id){
return request.post('order/cancel',{id:id},{},1);
*/
export function orderCancel(id) {
return request.post('order/cancel', {
id: id
}, {}, 1);
}
/**
* 删除已完成订单
* @param string uni
*
*/
export function orderDel(uni){
return request.post('order/del',{id:uni},{},1);
*/
export function orderDel(uni) {
return request.post('order/del', {
id: uni
}, {}, 1);
}
/**
* 订单详情
* @param string uni
*/
export function getOrderDetail(uni){
return request.get('order/detail/'+uni);
*/
export function getOrderDetail(uni) {
return request.get('order/detail/' + uni);
}
/**
* 再次下单
* @param string uni
*
*/
export function orderAgain(uni){
return request.post('order/again',{nui:uni});
*/
export function orderAgain(uni) {
return request.post('order/again', {
nui: uni
});
}
/**
* 订单收货
* @param string uni
*
*/
export function orderTake(uni){
return request.post('order/take',{id:uni},{},1);
*/
export function orderTake(uni) {
return request.post('order/take', {
id: uni
}, {}, 1);
}
/**
@@ -130,40 +145,43 @@ export function orderTake(uni){
* @returns {*}
*/
export function express(uni) {
return request.get("order/express/" + uni);
return request.get("order/express/" + uni);
}
/**
* 获取退款理由
*
*/
export function ordeRefundReason(){
return request.get('order/refund/reason');
*/
export function ordeRefundReason() {
return request.get('order/refund/reason');
}
/**
* 订单退款审核
* @param object data
*/
export function orderRefundVerify(data){
return request.post('order/refund/verify',data);
*/
export function orderRefundVerify(data) {
return request.post('order/refund/verify', data);
}
/**
* 订单确认获取订单详细信息
* @param string cartId
*/
export function orderConfirm(cartId,isNew){
return request.post('order/confirm', { cartIds: cartId,isNew:isNew}, {}, 1);
*/
export function orderConfirm(cartId, isNew) {
return request.post('order/confirm', {
cartIds: cartId,
isNew: isNew
}, {}, 1);
}
/**
* 获取当前金额能使用的优惠卷
* @param string price
*
*/
export function getCouponsOrderPrice( data){
return request.get('coupons/order', data)
*/
export function getCouponsOrderPrice(data) {
return request.get('coupons/order', data)
}
/**
@@ -171,9 +189,9 @@ export function getCouponsOrderPrice( data){
* @param string key
* @param object data
*
*/
export function orderCreate(key,data){
return request.post('order/create/'+key,data);
*/
export function orderCreate(key, data) {
return request.post('order/create/' + key, data);
}
/**
@@ -183,5 +201,5 @@ export function orderCreate(key,data){
* @returns {*}
*/
export function postOrderComputed(key, data) {
return request.post("order/computed/" + key, data);
}
return request.post("order/computed/" + key, data);
}

View File

@@ -5,22 +5,18 @@ import wechat from "@/libs/wechat.js";
* 获取微信公众号js配置
* @returns {*}
*/
export function getWechatConfig() {
return request.get("wechat/config",{ url: encodeURIComponent(wechat.signLink()) },{ noAuth: true });
}
// export function getWechatConfig() {
// return request.get(
// "wechat/config?t="+ Date.parse(new Date()),
// { url: encodeURIComponent(wechat.signLink()) },
// "wechat/config",
// { url: encodeURIComponent(location.href.split('#')[0]) },
// { noAuth: true }
// );
// }
export function getWechatConfig() {
return request.get(
"wechat/config",
{ url: encodeURIComponent(location.href.split('#')[0]) },
{ noAuth: true }
);
}
/**
* 获取微信sdk配置
* @returns {*}
@@ -71,7 +67,7 @@ export function follow() {
* @retins {*}
* */
export function imageBase64(image) {
return request.post("qrcode/base64",image,{},1);
return request.post("qrcode/base64",image,{ noAuth: true },1);
}
/**

View File

@@ -131,7 +131,9 @@ export function getCollectUserList(data) {
*
*/
export function getReplyList(id, data) {
return request.get('reply/list/' + id, data)
return request.get('reply/list/' + id, data,{
noAuth: true
})
}
/**
@@ -139,7 +141,9 @@ export function getReplyList(id, data) {
* @param int id
*/
export function getReplyConfig(id) {
return request.get('reply/config/' + id);
return request.get('reply/config/' + id,{},{
noAuth: true
});
}
/**

View File

@@ -131,7 +131,7 @@
let data = res.data;
if (data.status == "WECHAT_H5_PAY") {
uni.hideLoading();
location.replace(data.result.jsConfig.mweb_url);
location.replace(data.result.jsConfig.h5PayUrl);
return that.$util.Tips({
title: "支付成功",
icon: 'success'

View File

@@ -110,7 +110,6 @@
this.$emit('ChangeCartNum', true);
},
tapAttr: function(indexw, indexn) {
console.log('45454555');
let that = this;
that.$emit("attrVal", {
indexw: indexw,
@@ -119,7 +118,7 @@
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attrValues[indexn]);
let value = that
.getCheckedValue()
.sort()
// .sort()
.join(",");
that.$emit("ChangeAttr", value);

View File

@@ -11,7 +11,7 @@
<view class="child-box" v-if="tabClick>0 && tabTitle[tabClick].child?tabTitle[tabClick].child.length>0:0">
<scroll-view scroll-x="true" style="white-space: nowrap; display: flex;align-items: center; height: 100%;" scroll-with-animation :scroll-left="tabLeft" show-scrollbar="false">
<view class="wrapper">
<view v-for="(item,index) in tabTitle[tabClick].child?tabTitle[tabClick].child:[]" class="child-item" :class="{on:index == childIndex}" @click="childTab(tabClick,index)">
<view v-for="(item,index) in tabTitle[tabClick].child?tabTitle[tabClick].child:[]" :key="index" class="child-item" :class="{on:index == childIndex}" @click="childTab(tabClick,index)">
<image :src="item.url" mode=""></image>
<view class="txt line1">{{item.name}}</view>
</view>

View File

@@ -37,11 +37,12 @@ class AuthWechat {
signLink() {
if (typeof window.entryUrl === 'undefined' || window.entryUrl === '') {
window.entryUrl = document.location.href
window.entryUrl = location.href.split('#')[0]
}
return /(Android)/i.test(navigator.userAgent) ? document.location.href : window.entryUrl;
return /(Android)/i.test(navigator.userAgent) ? location.href.split('#')[0] : window.entryUrl;
}
/**
* 初始化wechat(分享配置)
*/

View File

@@ -6,7 +6,7 @@
indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
<block v-for="(item,index) in imgUrls" :key="index">
<swiper-item>
<image :src="item.img" class="slide-image"></image>
<image :src="item.pic" class="slide-image"></image>
</swiper-item>
</block>
</swiper>

View File

@@ -221,7 +221,6 @@
} from '@/config/app.js';
import {
getProductDetail,
getProductCode,
collectAdd,
collectDel,
postCartAdd,
@@ -229,8 +228,7 @@
getReplyConfig
} from '@/api/store.js';
import {
getUserInfo,
userShare
getUserInfo
} from '@/api/user.js';
import {
getCoupons
@@ -653,8 +651,8 @@
// #ifdef H5
that.$set(that, 'storeImage', that.storeInfo.image);
if (that.isLogin) {
that.getCartCount();
that.ShareInfo();
};
};
// #endif
if (that.isLogin) {
@@ -762,7 +760,7 @@
for (let i = 0; i < productAttr.length; i++) {
this.$set(productAttr[i], "index", value[i]);
}
//sort();排序函数:数字-英文-汉字;
//sort();排序函数:数字-英文-汉字;
let productSelect = this.productValue[value.join(",")];
if (productSelect && productAttr.length) {
this.$set(
@@ -774,7 +772,7 @@
this.$set(this.attr.productSelect, "price", productSelect.price);
this.$set(this.attr.productSelect, "stock", productSelect.stock);
this.$set(this.attr.productSelect, "unique", productSelect.id);
this.$set(this.attr.productSelect, "cart_num", 1);
this.$set(this.attr.productSelect, "cart_num", 1);
this.$set(this, "attrValue", value.join(","));
this.$set(this, "attrTxt", "已选择");
} else if (!productSelect && productAttr.length) {

View File

@@ -144,7 +144,7 @@
<!-- 首页推荐 -->
<view class="index-product-wrapper" :class="iSshowH?'on':''">
<view class="nav-bd">
<view class="item" v-for="(item,index) in explosiveMoney" :index="item.id" :class="{active:index == ProductNavindex}"
<view class="item" v-for="(item,index) in explosiveMoney" :key="index" :index="item.id" :class="{active:index == ProductNavindex}"
@click="ProductNavTab(item,index)">
<view class="txt">{{item.title}}</view>
<view class="label">{{item.info}}</view>

View File

@@ -249,7 +249,7 @@
<!-- 首页推荐 -->
<view class="index-product-wrapper" style="min-height: 1500rpx;">
<view class="nav-bd">
<view class="item" v-for="(item,index) in explosiveMoney" :index="item.id" :class="{active:index == ProductNavindex}"
<view class="item" v-for="(item,index) in explosiveMoney" :key="index" :index="item.id" :class="{active:index == ProductNavindex}"
@click="ProductNavTab(item,index)">
<view class="txt">{{item.title}}</view>
<view class="label">{{item.info2}}</view>

View File

@@ -164,7 +164,7 @@
</view>
<view class='wrapper' v-else-if='orderInfo.deliveryType=="send"'>
<view class='item acea-row row-between'>
<view>配送方式</view>
<view>配送方式</view>
<view class='conter'>送货</view>
</view>
<view class='item acea-row row-between'>

View File

@@ -15,8 +15,8 @@
<view class="name" v-if="userInfo.uid">
{{userInfo.nickname}}
<view class="vip" v-if="userInfo.vip">
<image :src="userInfo.vip_icon" alt="">
<view style="margin-left: 10rpx;" class="vip-txt">{{userInfo.vip_name}}</view>
<image :src="userInfo.vipIcon" alt="">
<view style="margin-left: 10rpx;" class="vip-txt">{{userInfo.vipName}}</view>
</view>
</view>
<view class="num" v-if="userInfo.phone" @click="goEdit()">
@@ -388,6 +388,7 @@
border-radius: 18px;
font-size: 20rpx;
margin-left: 12rpx;
margin-top: 2rpx;
image {
width: 27rpx;

View File

@@ -7,7 +7,7 @@
<image :src='productInfo.image'></image>
</view>
<view class='text acea-row row-between'>
<view class='name line2'>{{productInfo.store_name}}</view>
<view class='name line2'>{{productInfo.storeName}}</view>
<view class='money'>
<view>{{productInfo.price}}</view>
<view class='num'>x{{cart_num}}</view>

View File

@@ -221,8 +221,8 @@
});
const backUrl = that.$Cache.get(BACK_URL) || "/pages/index/index";
that.$Cache.clear(BACK_URL);
getUserInfo().then(res => {
that.$store.commit("SETUID", res.data.uid);
// getUserInfo().then(res => {
that.$store.commit("SETUID", res.data.user.uid);
if (backUrl === '/pages/index/index' || backUrl === '/pages/order_addcart/order_addcart' || backUrl ===
'/pages/user/index') {
@@ -235,7 +235,7 @@
url: '/pages/index/index'
});
}
})
// })
})
.catch(res => {
that.$util.Tips({

View File

@@ -61,7 +61,7 @@
</view>
<view class='item acea-row row-between-wrapper' v-if='shippingType==0'>
<view>快递费用</view>
<view class='discount' v-if='priceGroup.storePostage > 0'>+¥{{priceGroup.storePostage}}</view>
<view class='discount' v-if='parseFloat(priceGroup.storePostage) > 0'>+¥{{priceGroup.storePostage}}</view>
<view class='discount' v-else>免运费</view>
</view>
<view v-else>
@@ -293,8 +293,6 @@
this.cartId = options.cartId;
this.is_address = options.is_address ? true : false;
this.news = options.new || true;
console.log('options.new');
console.log(options.new);
this.again = options.again || false;
if (this.isLogin) {
this.getaddressInfo();
@@ -572,16 +570,14 @@
let that = this;
if (that.addressId) {
getAddressDetail(that.addressId).then(res => {
// res.data.isDefault = parseInt(res.data.isDefault);
res.data.isDefault = parseInt(res.data.isDefault);
that.addressInfo = res.data || {};
that.addressId = res.data.id || 0;
that.address.addressId = res.data.id || 0;
})
} else {
getAddressDefault().then(res => {
// res.data.isDefault = parseInt(res.data.isDefault);
console.log('大家发挥绝代风华');
console.log(res.data.id);
res.data.isDefault = parseInt(res.data.isDefault);
that.addressInfo = res.data || {};
that.addressId = res.data.id || 0;
that.address.addressId = res.data.id || 0;
@@ -779,7 +775,16 @@
break;
case "WECHAT_H5_PAY": //网页版公众号支付
setTimeout(() => {
location.href = jsConfig.mweb_url;
let domain = encodeURIComponent(location.href);
let urls = jsConfigAgain.h5PayUrl + '&redirect_url='+ domain;
location.href = urls;
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages
});
}, 100);
break;
}

View File

@@ -214,33 +214,11 @@
tab: 5,
url: '/pages/users/user_money/index'
});
}).catch(err=>{
return that.$util.Tips({
title: err
});
})
// // #ifdef MP || APP-PLUS
// rechargeRoutine({
// price: parseFloat(value),
// type: 1
// })
// // #endif
// // #ifdef H5
// rechargeWechat({
// price: parseFloat(value),
// from: that.from,
// type: 1
// })
// // #endif
// .then(res => {
// return that.$util.Tips({
// title: '转入成功',
// icon: 'success'
// }, {
// tab: 5,
// url: '/pages/users/user_money/index'
// });
// }).catch(err => {
// return that.$util.Tips({
// title: err
// })
// });
} else if (res.cancel) {
return that.$util.Tips({
title: '已取消'
@@ -252,7 +230,6 @@
uni.showLoading({
title: '正在支付',
})
// #ifdef MP || APP-PLUS
let money = parseFloat(this.money);
if (this.rechar_id == 0) {
if (Number.isNaN(money)) {
@@ -268,7 +245,7 @@
} else {
money = this.numberPic
}
// #ifdef MP || APP-PLUS
rechargeRoutine({
price: money,
type: 0,
@@ -294,7 +271,6 @@
});
},
fail: function(err) {
console.log(err);
return that.$util.Tips({
title: '支付失败'
});
@@ -314,7 +290,7 @@
// #endif
// #ifdef H5
rechargeWechat({
price: that.rechar_id == 0 ? that.money : that.numberPic,
price: money,
from: that.from,
rechar_id: that.rechar_id,
payType: 0
@@ -353,12 +329,16 @@
});
})
.catch(function(err) {
console.log(err);
return that.$util.Tips({
title: '支付失败'
});
});
}
}).catch(res=>{
uni.hideLoading();
return that.$util.Tips({
title: res
});
})
// #endif
}

View File

@@ -29,7 +29,7 @@
</view>
</view>
<view class="numList acea-row row-around row-middle">
<view class="item" :class="current >=item.experience?'past':''" v-for="(item,index) in levelList">{{item.experience}}</view>
<view class="item" :class="current >=item.experience?'past':''" v-for="(item,index) in levelList" :key="index">{{item.experience}}</view>
</view>
</view>
<view class="vipList acea-row">
@@ -108,7 +108,7 @@
<view class="icons"></view>经验值明细
</view>
<view class="list">
<view class="item acea-row row-between-wrapper" v-for="(item,index) in expList">
<view class="item acea-row row-between-wrapper" v-for="(item,index) in expList" :key="index">
<view class="text">
<view class="name">{{item.title}}</view>
<view class="data">{{item.add_time}}</view>

View File

@@ -2,8 +2,9 @@ package com.common;
import com.constants.Constants;
import com.utils.RedisUtil;
import com.utils.RequestUtil;
import com.utils.ThreadLocalUtil;
import com.zbkj.crmeb.authorization.model.TokenModel;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -23,7 +24,7 @@ public class CheckFrontToken {
@Autowired
protected RedisUtil redisUtil;
public Boolean check(String token){
public Boolean check(String token, HttpServletRequest request){
try {
boolean exists = redisUtil.exists(Constants.USER_TOKEN_REDIS_KEY_PREFIX + token);
@@ -35,13 +36,29 @@ public class CheckFrontToken {
ThreadLocalUtil.set(hashedMap);
redisUtil.set(Constants.USER_TOKEN_REDIS_KEY_PREFIX +token, value, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
}else{
//判断路由,部分路由不管用户是否登录/token过期都可以访问
exists = checkRouter(RequestUtil.getUri(request));
}
return exists;
}catch (Exception e){
return false;
}
}
//路由在此处则返回true无论用户是否登录都可以访问
public boolean checkRouter(String uri) {
String[] routerList = {
"api/front/product/detail",
"api/front/coupons",
"api/front/index"
};
return ArrayUtils.contains(routerList, uri);
}
public String getTokenFormRequest(HttpServletRequest request){
return request.getHeader(Constants.HEADER_AUTHORIZATION_KEY);
}

View File

@@ -8,7 +8,7 @@ package com.constants;
* @since 2020/4/1415:46
*/
public class Constants {
public static final long TOKEN_EXPRESS_MINUTES = (60 * 24);
public static final long TOKEN_EXPRESS_MINUTES = (60 * 1); //1小时
public static final int NUM_ZERO = 0;
public static final int NUM_ONE = 1;

View File

@@ -3,6 +3,7 @@ package com.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.common.CheckFrontToken;
import com.common.CommonResult;
import com.utils.RequestUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@@ -22,11 +23,17 @@ public class FrontTokenInterceptor implements HandlerInterceptor {
String token = checkFrontToken.getTokenFormRequest(request);
if(token == null || token.isEmpty()){
//判断路由,部分路由不管用户是否登录都可以访问
boolean result = checkFrontToken.checkRouter(RequestUtil.getUri(request));
if(result){
return true;
}
response.getWriter().write(JSONObject.toJSONString(CommonResult.unauthorized()));
return false;
}
Boolean result = checkFrontToken.check(token);
Boolean result = checkFrontToken.check(token, request);
if(!result){
response.getWriter().write(JSONObject.toJSONString(CommonResult.unauthorized()));
return false;

View File

@@ -16,6 +16,7 @@ import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.Security;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -739,4 +740,15 @@ public class CrmebUtil {
String result = CrmebUtil.mapToStringUrl(map) + "&key=" + signKey;
return DigestUtils.md5Hex(result).toUpperCase();
}
/**
* 检查是否可以转换int
* @param str
* @return
*/
public static boolean isString2Num(String str){
Pattern pattern = Pattern.compile("^[0-9]*$");
Matcher matcher = pattern.matcher(str);
return matcher.matches();
}
}

View File

@@ -17,10 +17,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
@@ -62,7 +59,7 @@ public class ArticleController {
*/
@ApiOperation(value = "新增")
@RequestMapping(value = "/save", method = RequestMethod.POST)
public CommonResult<String> save(@Validated ArticleRequest articleRequest){
public CommonResult<String> save(@RequestBody @Validated ArticleRequest articleRequest){
Article article = new Article();
BeanUtils.copyProperties(articleRequest, article);
article.setImageInput(systemAttachmentService.clearPrefix(article.getImageInput()));
@@ -124,7 +121,7 @@ public class ArticleController {
@ApiOperation(value = "修改")
@RequestMapping(value = "/update", method = RequestMethod.POST)
@ApiImplicitParam(name="id", value="文章ID")
public CommonResult<String> update(@RequestParam Integer id, @Validated ArticleRequest articleRequest){
public CommonResult<String> update(@RequestParam Integer id, @RequestBody @Validated ArticleRequest articleRequest){
Article article = new Article();
BeanUtils.copyProperties(articleRequest, article);
article.setId(id);

View File

@@ -99,6 +99,7 @@ public class ArticleServiceImpl extends ServiceImpl<ArticleDao, Article> impleme
BeanUtils.copyProperties(article, articleVo);
if(!StringUtils.isBlank(article.getImageInput()) ){
articleVo.setImageInput(CrmebUtil.jsonToListString(article.getImageInput()));
articleVo.setImageInputs(article.getImageInput());
}
articleVoArrayList.add(articleVo);
}

View File

@@ -46,9 +46,12 @@ public class ArticleVo implements Serializable {
@ApiModelProperty(value = "文章作者")
private String author;
@ApiModelProperty(value = "文章图片")
@ApiModelProperty(value = "文章图片 前端用")
private List<String> imageInput = new ArrayList<>();
@ApiModelProperty(value = "文章图片 后端用")
private String imageInputs;
@ApiModelProperty(value = "文章简介")
private String synopsis;

View File

@@ -6,6 +6,7 @@ import com.exception.CrmebException;
import com.utils.RedisUtil;
import com.utils.ThreadLocalUtil;
import com.zbkj.crmeb.authorization.model.TokenModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -81,7 +82,10 @@ public class TokenManagerImpl implements TokenManager {
*/
@Override
public Object getLocalInfo(String key) {
return ThreadLocalUtil.get(key);
if(StringUtils.isNotBlank(key)){
return ThreadLocalUtil.get(key);
}
return null;
}
/**

View File

@@ -91,15 +91,15 @@ public class WebConfig implements WebMvcConfigurer {
excludePathPatterns("/api/front/share").
excludePathPatterns("/api/front/article/**").
excludePathPatterns("/api/front/city/**").
excludePathPatterns("/api/front/product/**").
excludePathPatterns("/api/front/product/hot").
excludePathPatterns("/api/front/products/**").
excludePathPatterns("/api/front/reply/**").
excludePathPatterns("/api/front/user/service/**").
excludePathPatterns("/api/front/coupons").
excludePathPatterns("/api/front/logistics").
excludePathPatterns("/api/front/groom/list/**").
excludePathPatterns("/api/front/index").
excludePathPatterns("/api/front/category").
// excludePathPatterns("/api/front/cart/count").
excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
}

View File

@@ -1,7 +1,5 @@
package com.zbkj.crmeb.express.request;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -30,5 +28,5 @@ public class ShippingTemplatesSearchRequest implements Serializable {
@ApiModelProperty(value = "模板名称")
private String name;
private String keywords;
}

View File

@@ -51,8 +51,8 @@ public class ShippingTemplatesServiceImpl extends ServiceImpl<ShippingTemplatesD
public List<ShippingTemplates> getList(ShippingTemplatesSearchRequest request, PageParamRequest pageParamRequest) {
PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
LambdaQueryWrapper<ShippingTemplates> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if(!StringUtils.isBlank(request.getName())){
lambdaQueryWrapper.eq(ShippingTemplates::getName, request.getName());
if(!StringUtils.isBlank(request.getKeywords())){
lambdaQueryWrapper.like(ShippingTemplates::getName, request.getKeywords());
}
lambdaQueryWrapper.orderByDesc(ShippingTemplates::getSort).orderByDesc(ShippingTemplates::getId);
return dao.selectList(lambdaQueryWrapper);

View File

@@ -97,7 +97,7 @@ public class UserController {
@ApiOperation(value = "当前登录用户信息")
@RequestMapping(value = "/userinfo", method = RequestMethod.GET)
public CommonResult<User> getInfo(){
return CommonResult.success(userService.getInfo());
return CommonResult.success(userService.getUserPromoter());
}
/**

View File

@@ -36,5 +36,7 @@ public class LoginRequest implements Serializable {
@Pattern(regexp = RegularConstants.PASSWORD, message = "密码格式错误密码必须以字母开头长度在6~18之间只能包含字符、数字和下划线")
private String password;
}
@ApiModelProperty(value = "推广人id")
@JsonProperty(value = "spread_spid")
private Integer spreadPid = 0;
}

View File

@@ -133,4 +133,16 @@ public class UserCenterResponse implements Serializable {
@ApiModelProperty(value = "订单状态数量")
private UserCenterOrderStatusNumResponse orderStatusNum;
@ApiModelProperty(value = "用户优惠券数量")
private Integer couponCount;
@ApiModelProperty(value = "是否会员")
private boolean vip;
@ApiModelProperty(value = "会员图标")
private String vipIcon;
@ApiModelProperty(value = "会员名称")
private String vipName;
}

View File

@@ -154,14 +154,10 @@ public class IndexServiceImpl implements IndexService {
indexInfoResponse.setLogoUrl(systemConfigService.getValueByKey(Constants.CONFIG_KEY_SITE_LOGO));
Integer userId = userService.getUserId();
if(userId > 0){
User user = userService.getById(userId);
User user = userService.getInfo();
if(null != user){
indexInfoResponse.setSubscribe(user.getSubscribe());
}
return indexInfoResponse;
}

View File

@@ -488,8 +488,8 @@ public class OrderServiceImpl implements OrderService {
StoreOrder storeOrderPram = new StoreOrder();
// storeOrderPram.setStatus(status);
storeOrderPram.setUid(currentUser.getUid());
storeOrderPram.setIsDel(false);
storeOrderPram.setIsSystemDel(false);
// storeOrderPram.setIsDel(false);
// storeOrderPram.setIsSystemDel(false);
storeOrderPram.setStatus(status);
List<StoreOrder> orderList = storeOrderService.getUserOrderList(storeOrderPram, pageRequest);

View File

@@ -3,6 +3,7 @@ package com.zbkj.crmeb.front.service.impl;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.constants.Constants;
import com.exception.CrmebException;
import com.github.pagehelper.PageInfo;
import com.utils.CrmebUtil;
import com.zbkj.crmeb.category.model.Category;
@@ -143,49 +144,55 @@ public class ProductServiceImpl implements ProductService {
@Override
public ProductDetailResponse getDetail(Integer id) {
ProductDetailResponse productDetailResponse = new ProductDetailResponse();
StoreProductResponse productResponse = storeProductService.getByProductId(id);
StoreProductStoreInfoResponse storeInfo = new StoreProductStoreInfoResponse();
try {
StoreProductResponse productResponse = storeProductService.getByProductId(id);
StoreProductStoreInfoResponse storeInfo = new StoreProductStoreInfoResponse();
BeanUtils.copyProperties(productResponse,storeInfo);
BeanUtils.copyProperties(productResponse,storeInfo);
// 设置点赞和收藏
User current = userService.getInfo();
if(null != current){
storeInfo.setUserLike(storeProductRelationService.getLikeOrCollectByUser(current.getUid(),id,true).size() > 0);
storeInfo.setUserCollect(storeProductRelationService.getLikeOrCollectByUser(current.getUid(),id,false).size() > 0);
}
productDetailResponse.setStoreInfo(storeInfo);
// 设置点赞和收藏
User user = userService.getInfo();
if(null != user){
if(null != user.getUid()){
storeInfo.setUserLike(storeProductRelationService.getLikeOrCollectByUser(user.getUid(),id,true).size() > 0);
storeInfo.setUserCollect(storeProductRelationService.getLikeOrCollectByUser(user.getUid(),id,false).size() > 0);
user = userService.updateForPromoter(user);
productDetailResponse.setPriceName(getPacketPriceRange(productResponse,user.getIsPromoter()));
}
}
storeInfo.setUserLike(false);
storeInfo.setUserCollect(false);
productDetailResponse.setPriceName("0");
productDetailResponse.setStoreInfo(storeInfo);
// 根据制式设置attr属性
setSkuAttr(id, productDetailResponse, productResponse);
// 根据制式设置sku属性
HashMap<String,Object> skuMap = new HashMap<>();
for (StoreProductAttrValueResponse attrValue : productResponse.getAttrValue()) {
skuMap.put(attrValue.getSuk(),attrValue);
}
// 根据制式设置attr属性
setSkuAttr(id, productDetailResponse, productResponse);
// 根据制式设置sku属性
HashMap<String,Object> skuMap = new HashMap<>();
for (StoreProductAttrValueResponse attrValue : productResponse.getAttrValue()) {
skuMap.put(attrValue.getSuk(),attrValue);
}
// for (HashMap<String, Object> attrValue : productResponse.getAttrValues()) {
// System.out.println("attrValue:"+attrValue);
// skuMap.putAll(attrValue);
// }
productDetailResponse.setProductValue(skuMap);
// 优品推荐
List<StoreProduct> storeProducts = storeProductService.getRecommendStoreProduct(18);
List<StoreProductRecommendResponse> storeProductRecommendResponses = new ArrayList<>();
for (StoreProduct product:storeProducts) {
StoreProductRecommendResponse sPRecommendResponse = new StoreProductRecommendResponse();
BeanUtils.copyProperties(product,sPRecommendResponse);
sPRecommendResponse.setActivity(null); // todo 暂放 设置优品推荐中的拼团砍价秒杀属性
productDetailResponse.setProductValue(skuMap);
// 优品推荐
List<StoreProduct> storeProducts = storeProductService.getRecommendStoreProduct(18);
List<StoreProductRecommendResponse> storeProductRecommendResponses = new ArrayList<>();
for (StoreProduct product:storeProducts) {
StoreProductRecommendResponse sPRecommendResponse = new StoreProductRecommendResponse();
BeanUtils.copyProperties(product,sPRecommendResponse);
sPRecommendResponse.setActivity(null); // todo 暂放 设置优品推荐中的拼团砍价秒杀属性
// sPRecommendResponse.setCheckCoupon(storeCouponService.getListByUser(product.getId()).size() > 0);
storeProductRecommendResponses.add(sPRecommendResponse);
}
productDetailResponse.setGoodList(storeProductRecommendResponses);
storeProductRecommendResponses.add(sPRecommendResponse);
}
productDetailResponse.setGoodList(storeProductRecommendResponses);
// 当前商品的佣金区间
if(null != current){
current = userService.updateForPromoter(current);
productDetailResponse.setPriceName(getPacketPriceRange(productResponse,current.getIsPromoter()));
}catch (Exception e){
throw new CrmebException(e.getMessage());
}
return productDetailResponse;
}

View File

@@ -181,6 +181,7 @@ public class StoreCouponUserServiceImpl extends ServiceImpl<StoreCouponUserDao,
storeCouponUser.setMinPrice(storeCoupon.getMinPrice());
storeCouponUser.setStartTime(storeCoupon.getUseStartTime());
storeCouponUser.setEndTime(storeCoupon.getUseEndTime());
storeCouponUser.setUseType(storeCoupon.getUseType());
storeCouponUserList.add(storeCouponUser);
}
@@ -332,6 +333,7 @@ public class StoreCouponUserServiceImpl extends ServiceImpl<StoreCouponUserDao,
storeCouponUser.setType(type);
storeCouponUser.setStartTime(storeCoupon.getUseStartTime());
storeCouponUser.setEndTime(storeCoupon.getUseEndTime());
storeCouponUser.setUseType(storeCoupon.getUseType());
storeCouponUserList.add(storeCouponUser);
}
@@ -428,7 +430,7 @@ public class StoreCouponUserServiceImpl extends ServiceImpl<StoreCouponUserDao,
request.setUid(userId);
PageInfo<StoreCouponUserResponse> list = getList(request, pageParamRequest);
if(list.getList().size() < 1){
if(null == list.getList() || list.getList().size() < 1){
return null;
}
Date date = DateUtil.nowDateTime();

View File

@@ -82,7 +82,8 @@ public class StoreProductController {
@ApiOperation(value = "删除")
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public CommonResult<String> delete(@RequestBody @PathVariable Integer id){
if(storeProductService.removeById(id)){
if(storeProductService.deleteProduct(id)){
// if(storeProductService.removeById(id)){
storeCartService.productStatusNotEnable(id);
return CommonResult.success();
}else{

View File

@@ -139,6 +139,7 @@ public class StoreProductReplyController {
lup.eq(StoreProductReply::getId, id);
lup.set(StoreProductReply::getMerchantReplyContent, request.getMerchantReplyContent());
lup.set(StoreProductReply::getMerchantReplyTime, DateUtil.getNowTime());
lup.set(StoreProductReply::getIsReply, true);
storeProductReplyService.update(lup);
}
return CommonResult.success();

View File

@@ -1,6 +1,8 @@
package com.zbkj.crmeb.store.model;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -105,6 +107,7 @@ public class StoreProduct implements Serializable {
@ApiModelProperty(value = "是否包邮")
private Boolean isPostage;
// @TableLogic
@ApiModelProperty(value = "是否删除")
private Boolean isDel;

View File

@@ -30,7 +30,7 @@ public class StoreOrderSearchRequest {
private Integer uid;
@ApiModelProperty(value = "创建时间区间")
private String timeRage;
private String dateLimit;
@ApiModelProperty(value = "订单状态all 总数; 未支付 unPaid 未发货 notShipped待收货 spike待评价 bargain已完成 complete待核销 toBeWrittenOff退款中:refunding已退款:refunded已删除:deleted")
private String status;

View File

@@ -12,6 +12,7 @@ import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
/**
* <p>
@@ -91,7 +92,7 @@ public class StoreProductAttrValueRequest implements Serializable {
private Date updateTime;
@ApiModelProperty(value = "attrValue字段前端传递后用作sku字段")
private HashMap<String,String> attrValue;
private LinkedHashMap<String,String> attrValue;
}

View File

@@ -35,6 +35,9 @@ public class StoreProductReplySearchRequest implements Serializable {
@ApiModelProperty(value = "商品id, 多个逗号分割")
private String productId;
@ApiModelProperty(value = "商品名称, 关键字,产品编号")
private String productSearch;
@ApiModelProperty(value = "0未删除1已删除")
private Boolean isDel;

View File

@@ -114,4 +114,11 @@ public interface StoreProductService extends IService<StoreProduct> {
boolean decProductStock(Integer productId, Integer num, Integer attrValueId, Integer type);
List<Integer> getSecondaryCategoryByProductId(String productId);
/**
* 删除商品
* @param productId 商品id
* @return 删除结果
*/
boolean deleteProduct(Integer productId);
}

View File

@@ -24,6 +24,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Classname RetailShopServiceImpl
@@ -59,7 +60,8 @@ public class RetailShopServiceImpl extends ServiceImpl<UserDao, User> implements
@Override
public PageInfo<RetailShopUserResponse> getList(String keywords, String dateLimit, PageParamRequest pageRequest) {
Page<User> pageUserPage = PageHelper.startPage(pageRequest.getPage(), pageRequest.getLimit());
User currentUser = userService.getInfo();
// User currentUser = userService.getUserByEntity();
UserSearchRequest userSearchRequest = new UserSearchRequest();
userSearchRequest.setStatus(true);
userSearchRequest.setIsPromoter(true);
@@ -80,8 +82,12 @@ public class RetailShopServiceImpl extends ServiceImpl<UserDao, User> implements
for (RetailShopUserResponse rShopUser:retailShopUserResponses) {
// 推广用户数量
List<Integer> userIds = new ArrayList<>();
userIds.add(currentUser.getUid());
// List<Integer> userIds = new ArrayList<>();
List<Integer> userIds = userResponses.getList().stream().map(e -> {
return e.getUid();
}).collect(Collectors.toList());
// userIds.add(currentUser.getUid());
// rShopUser.setSpreadPeopleCount(userService.getSpreadPeopleIdList(userIds).size());
rShopUser.setSpreadPeopleCount(userService.getSpreadPeopleIdList(userIds).size());
// 获取提现数据
rShopUser.setUserExtractResponse(userExtractService.getUserExtractByUserId(rShopUser.getUid()));

Some files were not shown because too many files have changed in this diff Show More