Compare commits

..

1 Commits

Author SHA1 Message Date
ch c3b3502e95 pref: 调整项目目录结构
2 years ago

@ -5,59 +5,30 @@
* @LastEditTime: 2022-05-07 11:39:38
* @Description: file content
-->
# shop-pc
## 前置环境
由于项目依赖问题,开发 `node` 版本必须是 `14`
如果电脑安装 `Node 18`,那么怎么添多个 `node` 版本,可以使用 `nvm` 版本管理工具。具体安装可以参考下面教程
[window install nvm](https://juejin.cn/post/7074108351524634655)
[mac install nvm](https://juejin.cn/post/7206882855200047161)
## 修改前端接口请求地址
进入到 ` plugins/config/env.js` 中:
```js
// 修改对应值即可
const ENV = {
base_url: "https://k8s-horse-gateway.mashibing.cn",
imUrl: "wss://k8s-horse-gateway.mashibing.cn",
};
export default ENV;
```
> `注意 ⚠️`:通常本地开发访问线上接口地址时会出现跨越(协议、域名、端口不一样时就会出现跨越问题),此时后端服务需要配置跨域相关的内容。
## 运行&打包
- 运行直接执行 npm run dev 打包执行 npm run build 即可,会根据分支读取不同环境变量配置;
- 运行直接执行 npm run dev 打包执行npm run build 即可,会根据分支读取不同环境变量配置;
## 环境变量配置
- 环境变量配置文件 env.config;
- 配置与分支对应关系msb_prod -> prod msb_beta -> beta msb_test -> test msb-其他 -> dev
- 环境变量配置文件env.config;
- 配置与分支对应关系msb_prod -> prod msb_beta -> beta msb_test -> test msb-其他 -> dev
- 输出的环境变量文件plugins/config/env.js
- 修改环境变量配置后需要执行 “ node env.config " 输出的环境变量才会更新
```js
``` js
// 直接引入输出的配置文件即可
import ENV from "@/plugins/config/env.js";
import ENV from '@/plugins/config/env.js';
// 直接访问你在配置文件中定义的属性
console.log(ENV.baseUrl);
```
## 公共方法 utils
```
- 公共方法统一放置 utils 文件夹内,可以按分类建方法文件 如:验证类 verify.js 请求类 request.js
## 公共方法utils
- 公共方法统一放置utils文件夹内可以按分类建方法文件 如验证类verify.js 请求类request.js
- 所有公共方法采用大驼峰命名法
- 所有的方法都从 index.js 输出,引入时统一引入 index不允许直接引入方法文件
- 所有的方法都从index.js输出引入时统一引入index不允许直接引入方法文件
- 所有方法文件如果导出的是多个方法,不允许在定义方法时导出,必须在文件底部一一导出,并附上方法简单的注释
```js
``` js
// 正确
import {Req, IsPhone} from '@/common/utils';
@ -75,25 +46,21 @@ export {
IsEmail
}
```
## 组件
- 根目录的components 只放置真正的组件某个页面的业务模块应该在pages的相应目录下新建module目录放置
- 所有的自定义组件文件名以大驼峰命名且在templet中使用也用大驼峰形式使用(包括页面内的模块组件)
- 根目录的 components 只放置真正的组件,某个页面的业务模块应该在 pages 的相应目录下新建 module 目录放置
- 所有的自定义组件文件名以大驼峰命名,且在 templet 中使用也用大驼峰形式使用(包括页面内的模块组件)
## storage的使用
- 不要在页面内直接使用loaclStorage全都放置到vuex中做一次管理
## storage 的使用
- 不要在页面内直接使用 loaclStorage全都放置到 vuex 中做一次管理
## 请求
- 项目中有两个 axios 请求实例,一个事 nuxt 自带的(不需要 Token 请使用这个),一个是额外封装的(需要 Token 请使用这个);
- 需要 Token 的请求,不要写在 asyncData 中;
- 项目中有两个axios请求实例一个事nuxt自带的不需要Token请使用这个一个是额外封装的需要Token请使用这个
- 需要Token的请求不要写在asyncData中
- 所有请求方法命名以Api+请求类型+具体方) 法命名
- 所有请求使用 ToAsyncAwait 包裹
- 不允许使用 try catch 和 then 处理返回结果
```js
- 所有请求使用ToAsyncAwait 包裹
- 不允许使用try catch 和 then 处理返回结果
``` js
// 使用示例
// xxapi.js
import {ToAsyncAwait, ReqestTk} from '@/common/utils'
@ -104,7 +71,7 @@ export {
}
// user.vue
improt {ApiGetUserInfo} from '@/common/api/xxapi.js';
const getUserInfo = async () =>{
const {error, result} = await ApiGetUserInfo();
if(error){
@ -115,47 +82,46 @@ export {
}
```
## css
- 采用BEM命名法
- 采用 BEM 命名法
### 兼容 CSS
```css
### 兼容CSS
``` css
/* 以下兼容方式的样式请使用util.css中的adj方法 */
.my-class {
transform: translate3d(-50%, 0, 0);
-webkit-transform: translate3d(-50%, 0, 0);
-moz-transform: translate3d(-50%, 0, 0);
-o-transform: translate3d(-50%, 0, 0);
-ms-transform: translate3d(-50%, 0, 0);
.my-class{
transform: translate3d(-50%, 0, 0);
-webkit-transform: translate3d(-50%, 0, 0);
-moz-transform: translate3d(-50%, 0, 0);
-o-transform: translate3d(-50%, 0, 0);
-ms-transform: translate3d(-50%, 0, 0);
}
/* 使用以下方法 */
@import "~/assets/scss/util.scss";
.my-class {
.my-class{
@include adj(transform, translate3d(-50%, 0, 0));
}
```
## 登录相关
```javascript
// 访问token
this.$store.state.token;
this.$store.state.token
// 设置token
this.$store.commit("setToken");
this.$store.commit('setToken')
// 退出登录
this.$store.commit("setLoginOut");
this.$store.commit('setLoginOut')
// 获取登录的用户信息
this.$store.state.userInfo;
this.$store.state.userInfo
// 登录拦截
// 示例:点击购买课程前需要判断当前用户是否登录,未登录则弹出登录弹窗
function onPurchaseCourse() {
if (!this.$isLoginValidate()) {
return;
}
// 此处省略其他业务代码...
if (!this.$isLoginValidate()) {
return;
}
// 此处省略其他业务代码...
}
```

@ -1,4 +1,4 @@
FROM node:14.17.0
FROM node:12.13.1
WORKDIR /workload
COPY nuxt.config.js /workload/nuxt.config.js

@ -1,43 +1,44 @@
/*
* @Author: ch
* @Date: 2022-05-05 14:40:00
* @LastEditors: ch
* @LastEditTime: 2022-06-24 14:21:20
* @Description: 根据git分支生成对应环境的环境变量
* @LastEditors: ch cwl_ch@163.com
* @LastEditTime: 2022-08-03 16:47:17
* @Description:
* 开发时如果环境变量换了可以不用重启服务直接运行node env.config.js即可
*/
const fs = require('fs');
const path = require('path');
const getRepoInfo = require('git-repo-info');
const fs = require("fs");
const path = require("path");
const envConfig = {
dev : {
base_url: 'https://k8s-horse-gateway.mashibing.cn',
imUrl : 'wss://k8s-horse-gateway.mashibing.cn'
},
test : {
base_url: 'https://k8s-horse-gateway.mashibing.cn',
imUrl : 'wss://k8s-horse-gateway.mashibing.cn'
},
beta : {
base_url: 'https://you-gateway.mashibing.com',
imUrl : 'wss://you-gateway.mashibing.com'
},
prod : {
base_url: 'https://you-gateway.mashibing.com',
imUrl : 'wss://you-gateway.mashibing.com'
}
}
dev: {
base_url: "https://k8s-horse-gateway.mashibing.cn",
imUrl: "wss://k8s-horse-gateway.mashibing.cn",
},
test: {
base_url: "https://k8s-horse-gateway.mashibing.cn",
imUrl: "wss://k8s-horse-gateway.mashibing.cn",
},
beta: {
base_url: "https://you-gateway.mashibing.com",
imUrl: "wss://you-gateway.mashibing.com",
},
prod: {
base_url: "https://you-gateway.mashibing.com",
imUrl: "wss://you-gateway.mashibing.com",
},
};
let curEnvConfig = null;
const argv = global.process.argv;
for(key in envConfig){
if(argv.includes(`--ENV:${key}`)){
curEnvConfig = envConfig[key];
break;
}
for (key in envConfig) {
if (argv.includes(`--ENV:${key}`)) {
curEnvConfig = envConfig[key];
break;
}
}
if(!curEnvConfig){
curEnvConfig = envConfig.dev;
if (!curEnvConfig) {
curEnvConfig = envConfig.dev;
}
fs.writeFileSync(`${path.resolve(__dirname, './plugins/config')}/env.js`,
`const ENV = ${JSON.stringify(curEnvConfig)}; export default ENV;`);
fs.writeFileSync(
`${path.resolve(__dirname, "./src/common/plugins/config")}/env.js`,
`const ENV = ${JSON.stringify(curEnvConfig)}; export default ENV;`
);

@ -1,11 +1,18 @@
/*
* @Author: ch
* @Date: 2022-05-03 22:14:16
* @LastEditors: ch
* @LastEditTime: 2023-04-21 16:14:15
* @LastEditors: ch cwl_ch@163.com
* @LastEditTime: 2022-08-03 15:30:44
* @Description: file content
*/
export default {
srcDir: "src/",
dir: {
layouts: "pages/layouts",
static: "assets/static",
middleware: "common/middleware",
store: "common/store",
},
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: "马士兵严选",
@ -25,25 +32,25 @@ export default {
routes.push({
name: "custom",
path: "/",
component: resolve(__dirname, "pages/index/index.vue"),
component: resolve(__dirname, "src/pages/index/index.vue"),
});
},
middleware: ["redirect"],
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: ["@assets/scss/global.scss", "element-ui/lib/theme-chalk/index.css"],
css: ["@/assets/scss/global.scss", "element-ui/lib/theme-chalk/index.css"],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
"@/plugins/element-ui",
"@/plugins/axios",
"@/plugins/axiosTk.js",
"@plugins/vue-inject.js",
"@/plugins/v-distpicker",
"@/plugins/router",
"@/plugins/im",
"@/plugins/chat",
"@/common/plugins/element-ui",
"@/common/plugins/axios",
"@/common/plugins/axiosTk.js",
"@/common/plugins/vue-inject.js",
"@/common/plugins/v-distpicker",
"@/common/plugins/router",
"@/common/plugins/im",
"@/common/plugins/chat",
],
// Auto import components: https://go.nuxtjs.dev/config-components

8415
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -21,12 +21,12 @@
"element-ui": "^2.15.8",
"js-util-all": "^1.0.6",
"lodash": "^4.17.21",
"nuxt": "2.15.8",
"nuxt": "^2.15.8",
"qrcode": "^1.5.0",
"v-distpicker": "^1.2.13",
"vue": "2.6.14",
"vue-server-renderer": "2.6.14",
"vue-template-compiler": "2.6.14"
"vue": "^2.6.14",
"vue-server-renderer": "^2.6.14",
"vue-template-compiler": "^2.6.14"
},
"devDependencies": {
"@vue/test-utils": "^1.3.0",
@ -34,7 +34,6 @@
"babel-jest": "^27.4.4",
"eslint": "^8.15.0",
"eslint-plugin-prettier": "^4.0.0",
"git-repo-info": "^2.1.1",
"jest": "^27.4.4",
"node-sass": "^4.14.1",
"prettier": "^2.6.2",

@ -1,43 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:24:03
* @LastEditors: ch
* @LastEditTime: 2022-05-07 10:27:01
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import {axios} from "../axios";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/uc`;
/**
* 获取当前登录用户信息
*/
export const ApiGetCurrentUser = () =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/user/current`));
/**
* 修改用户信息
* @param {*} data
*/
export const ApiPutUser = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/user/`, data));
/**
* 登录
* @param {*} data
*/
export const ApiPostLogin = (data) => ToAsyncAwait(axios.post(`${BASE_URL}/user/login`, data));
/**
* 退出登录
*/
export const ApiPostLogout = () => ToAsyncAwait(axiosTk.get(`${BASE_URL}/user/logout`));
/**
* 获取手机验证码
* @param {*} params
*/
export const ApiGetCode = (params) => ToAsyncAwait(axios.get(`${BASE_URL}/user/login/verificationCode`, { params }));

@ -1,22 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-31 11:17:38
* @LastEditors: ch
* @LastEditTime: 2022-06-01 15:53:53
* @Description: file content
*/
import {ToAsyncAwait} from '@/plugins/utils';
import { AD_PLATFORM } from '../dicts/ad';
import {axios} from "../axios";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/marketing`;
// 获取广告列表
export const ApiGetAdList = (params) => ToAsyncAwait(axios.get(`${BASE_URL}/app/advertisement`, {
params: {
platform : AD_PLATFORM.PC,
...params
}
}))

@ -1,34 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:24:03
* @LastEditors: ch
* @LastEditTime: 2022-05-07 10:28:22
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/base`;
/**
* 获取收货地址
*/
export const ApiGetAddress = () =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/receiveAddress`));
/**
* 新增收货地址
*/
export const ApiPostAddress = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/receiveAddress`, data));
/**
* 收货地址修改
*/
export const ApiPutAddress = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/receiveAddress`, data));
/**
* 收货删除
*/
export const ApiDeleteAddress = (data) =>
ToAsyncAwait(axiosTk.delete(`${BASE_URL}/receiveAddress?idList=${data.idList}`));

@ -1,38 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:24:03
* @LastEditors: ch
* @LastEditTime: 2022-05-07 10:29:08
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/product`;
/**
* 设置购物车数量
* @param {id,number} data
*/
export const ApiPutCartNum = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/shoppingCart/number`, data));
/**
* 往购物车中添加商品
* @param {prodcutId, productSkuId, number} data
*/
export const ApiPutAddCart = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/shoppingCart/increase`, data));
/**
* 删除购物车中的商品
* @param {idList} data
*/
export const ApiDeleteCartGoods = (data) =>
ToAsyncAwait(axiosTk.delete(`${BASE_URL}/shoppingCart?idList=${data.idList}`, data));
/**
* 获取购物车列表
*/
export const ApiGetCartList = () =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/shoppingCart`));

@ -1,86 +0,0 @@
/*
* @Author: ch
* @Date: 2022-06-20 11:38:48
* @LastEditors: ch
* @LastEditTime: 2022-06-30 11:48:53
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import {axios} from "../axios";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/comment`;
/**
* 根据商品获取评论列表未
* @param {*} param0
*/
export const ApiGetCommentList = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/comment`, {
params,
headers: {
notVerifyToken : true
}
}));
/**
* 根据商品获取评论总数
* @param {*} param0
*/
export const ApiGetCommentCount = ({productId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/comment/getAllCommentCountByProductId/${productId}`,{
headers: {
notVerifyToken : true
}
}));
/**
* 根据商品获取标签评论总数
* @param {*} param0
*/
export const ApiGetCommentTabCount = ({productId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/comment/listCommentLabel/${productId}`,{
headers: {
notVerifyToken : true
}
}));
/**
* 获取订单评论详情
* @param {*} param0
*/
export const ApiGetOrderCommentDetail = ({orderId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/comment/listOrderCommentByOrderId/${orderId}`));
/**
* 获取商品满意度
* @param {*} param0
*/
export const ApiGetProductSatisfaction = ({productId}) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/comment/getProductSatisfaction/${productId}`));
/**
* 获取评论详情
* @param {*} param0
*/
export const ApiGetCommentDetail = ({commentId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/comment/getCommentDetail/${commentId}`, {
headers: {
notVerifyToken : true
}
}));
/**
* 新增评论
* @param {*} param0
*/
export const ApiPostComment = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/app/comment`, data));
/**
* 更新评论有用数
* @param {*} param0
*/
export const ApiPutCommentUseful = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/comment/updateUsefulCount`, data));

@ -1,57 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:24:03
* @LastEditors: ch
* @LastEditTime: 2022-05-07 10:29:22
* @Description: file content
*/
import {axios} from "../axios";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/product`;
/**
* 获取商品瀑布流
* @param {*} params
*/
export const ApiGetGoodsList = (params) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/product/page`, {params}));
/**
* 获取推荐商品
* @param {*} params
*/
export const ApiGetRecommendedGoodsList = (params) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/product/recommended`, params));
/**
* 获取商品详情
* @param {*} params
*/
export const ApiGetGoodsDetail = (params) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/product/${params.id}`));
/**
* 获取商品sku信息
* @param {*} productId
*/
export const ApiGetGoodsSkus = (params) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/product/sku`,{params}));
/**
* 获取首页分类导航
*/
export const ApiGetCategoryNav = () =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/product/categoryNavigation`));
/**
* 获取一级分类列表
*/
export const ApiGetCategoryOneList = () =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/productCategory/levelOne`));
/**
* 获取二级分类和商品列表
*/
export const ApiGetCategoryTwoAndGoods = (params) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/productCategory/listCategoryAndProduct/${params.categoryId}`));

@ -1,21 +0,0 @@
/*
* @Author: ch
* @Date: 2022-06-12 14:06:01
* @LastEditors: ch
* @LastEditTime: 2022-06-14 21:14:54
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/im`;
/**
* 获取soket登录秘钥
*/
export const ApiGetSoketTicket = () => ToAsyncAwait(axiosTk.get(`${BASE_URL}/ticket`, {
params: {
ticketType: 'CONNECT_TICKET'
}
}));

@ -1,173 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:17:25
* @LastEditors: ch
* @LastEditTime: 2022-06-28 09:56:23
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import {ToAsyncAwait} from "@/plugins/utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/trade`;
const APPID = 'wx0643970a8e86d028';
/**
* 获取订单
* @param {*} params
*/
export const ApiGetOrderList = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/page`, {params}));
/**
* 获取立即购买预订单
* @param {*} data
*/
export const ApiGetBeforeOrder = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/buyAdvanceOrder`, {params}));
/**
* 获取购物车预订单
* @param {*} data
*/
export const ApiGetBeforeCartOrder = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/cartAdvanceOrder`, {params}));
/**
* 订单详情
* @param {*} id
*/
export const ApiGetOrderDetail = (id) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/${id}`));
/**
* 订单商品详情信息
* @param {*} orderProductId
*/
export const ApiGetOrderProductDetail = ({orderProductId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/product/${orderProductId}`));
/**
* 获取待评价订单详请列表
*/
export const ApiGetCommentOrderDetailList = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/listOrderProductWaitComment`,{params}))
/**
* 提交订单
* @param {*} data
*/
export const ApiGetOrderPaySatus = ({orderId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/payResult/${orderId}`));
/**
* 获取物流信息
* @param {*} orderId
*/
export const ApiGetOrderLogistics = ({orderId}) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/logistics/${orderId}`));
/**
* 获取物流列表
* @param {*} params
*/
export const ApiGetOrderLogisticsList = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/listReceiveOrder`, { params }));
/**
* 确认收货
* @param {*} orderId
*/
export const ApiPutOrderReceive = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/tradeOrder/receive`, data));
/**
* 提交订单
* @param {*} data
*/
export const ApiPostSubmitOrder = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/app/tradeOrder/submitOrder`, data));
/**
* 取消订单
* @param {*} data
*/
export const ApiPutCancelOrder = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/tradeOrder/cancel`, data));
/**
* 获取订单统计数据
*/
export const ApiGetOrderStatistics = () =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/tradeOrder/statistics`))
/**
* 申请售后
* @param {*} data
*/
export const ApiPostApplySaleAfter = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/app/refundOrder/applyRefund`, data));
/**
* 修改售后申请
* @param {*} data
*/
export const ApiPostEditSaleAfter = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/refundOrder/updateRefund`, data));
/**
* 撤销售后申请
* @param {*} data
*/
export const ApiPostCancelSaleAfter = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/refundOrder/cancelRefund`, data));
/**
* 售后订单列表
* @param {*} data
*/
export const ApiGetSaleAfterOrderList = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/refundOrder/page`, params));
/**
* 售后订单详情
* @param {*} data
*/
export const ApiGetSaleAfterOrderDetail = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/refundOrder/refundInfo`, params));
/**
* 售后物流公司
* @param {*} data
*/
export const ApiGetLogisticsCompanylist = (params) =>
ToAsyncAwait(axiosTk.get(`${BASE_URL}/app/refundOrder/logisticsCompany`));
/**
* 售后提交物流信息
* @param {*} data
*/
export const ApiPutLogisticsInfo = (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/refundOrder/completeRefund`, data));
/**
* 退款订单统计
*/
export const ApiGetRefundStatistisc= (data) =>
ToAsyncAwait(axiosTk.put(`${BASE_URL}/app/refundOrder/statistics`, data));
/**
* 微信h5支付获取支付URL
* @param {*} data
*/
export const ApiPostWxH5Pay = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/pay/wxPay/h5`, data));

@ -1,20 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:24:03
* @LastEditors: ch
* @LastEditTime: 2022-05-07 10:30:17
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/oss/oss`;
/**
* 获取OOS信息
* @param {*} data
*/
export const ApiPostGetOssConfig = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/generateOssSignature`, data));

@ -1,26 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-08 00:44:22
* @LastEditors: ch
* @LastEditTime: 2022-06-29 14:51:00
* @Description: file content
*/
import {axiosTk} from "../axiosTk";
import {ToAsyncAwait} from "@/plugins/utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/trade`;
/**
* 获取微信支付二维码
* @param {*} data
*/
export const ApiPostWxPayCdoeImg = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/payCenter/wxPay/nativeData`, data));
/**
* 获取支付宝支付二维码
* @param {*} data
*/
export const ApiPostAliPayCdoeImg = (data) =>
ToAsyncAwait(axiosTk.post(`${BASE_URL}/payCenter/aliPay/qr`, data));

@ -1,33 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 18:24:03
* @LastEditors: ch
* @LastEditTime: 2022-05-07 10:30:28
* @Description: file content
*/
import {axios} from "../axios";
import { ToAsyncAwait } from "../utils";
import ENV from '../config/env';
const BASE_URL = `${ENV.base_url}/mall/marketing`;
export const ApiGetHomeSeckill = () =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/activity/home`));
/**
* 获取当天秒杀时段
*/
export const ApiGetSeckillTimes = () =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/activity/time`));
/**
* 获取当天秒杀时段
*/
export const ApiGetSeckillGoods = (params) =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/activity/product`, { params }));
/**
* 获取当前服务器时间
*/
export const ApiGetCurrentTime = () =>
ToAsyncAwait(axios.get(`${BASE_URL}/app/activity/timestamp`));

@ -1,43 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-03 23:04:45
* @LastEditors: ch
* @LastEditTime: 2022-06-12 14:35:43
* @Description: file content
*/
let axios = null;
import { UUID_KEY } from "@/constants";
import { CreateUUID } from "@/plugins/utils";
export default function ({ app, $axios, store, req }) {
let uuid = store.state.uuid;
if (!uuid && req.headers.cookie) {
uuid = req.headers.cookie.split(';').find(i => i.includes(UUID_KEY));
uuid = uuid && uuid.replace(`${UUID_KEY}=`,'')
}
if (!uuid) {
uuid = CreateUUID(16, 2);
store.commit('setUUID', uuid);
}
$axios.onRequest( config =>{
config.headers.uid = uuid;
return config;
});
$axios.onResponse(response => {
const result = response.data;
if(response.status === 200){
if(result.code === 'SUCCESS'){
return result.data;
}
return Promise.reject(result);
}
return Promise.reject({message:'请求出错'});
});
$axios.defaults.timeout = 3000;
axios = $axios;
}
export { axios }

@ -1,54 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-04 17:11:07
* @LastEditors: ch
* @LastEditTime: 2022-06-29 16:01:55
* @Description: file content
*/
import { CreateUUID } from "@/plugins/utils";
import { UUID_KEY } from "@/constants";
let axiosTk = null;
export default function ({$axios, store, route, req}, inject) {
const $axiosTk = $axios.create();
let uuid = store.state.uuid;
if (!uuid && req.headers.cookie) {
uuid = req.headers.cookie.split(';').find(i => i.includes(UUID_KEY));
uuid = uuid && uuid.replace(`${UUID_KEY}=`,'')
}
if (!uuid) {
uuid = CreateUUID(16, 2);
store.commit('setUUID', uuid);
}
$axiosTk.defaults.timeout = 3000;
$axiosTk.onRequest( config =>{
config.headers.uid = uuid;
if(!store.state.token && !config.headers.notVerifyToken){
location.href = '/';
return Promise.reject({message : '要先登录才能操作哦~'});
}
delete config.headers.notVerifyToken;
config.headers.Authorization = store.state.token;
return config;
});
$axiosTk.onResponse(response => {
const result = response.data;
if(response.status === 200){
if(result.code === 'SUCCESS'){
return result.data;
}
if(result.code === 'TOKEN_FAIL'){
store.commit('setLoginOut');
store.commit('setLoginVisible');
}
return Promise.reject(result);
}
return Promise.reject({message:'请求出错'});
});
inject('$axiosTk', $axiosTk);
axiosTk = $axiosTk;
}
export {axiosTk}

@ -1,58 +0,0 @@
/*
* @Author: ch
* @Date: 2022-06-12 14:04:56
* @LastEditors: ch
* @LastEditTime: 2022-06-13 20:27:34
* @Description: file content
*/
import MsbIm from '@/plugins/msbIm' ;
import { ToAsyncAwait, FormatJsonSearch } from './utils';
import { ApiGetSoketTicket } from '@/plugins/api/im';
import ENV from '@/plugins/config/env';
const Im = new MsbIm({
reconnect: true,
});
let ImInit = null;
export default ({store }) => {
ImInit = async () => {
const { error, result } = await ApiGetSoketTicket();
if (error) {
return false;
}
const par = FormatJsonSearch({
client: result.client,
ticket: result.ticket,
// 1普通用户 2客服链接
connect: 1,
user: store.state.userInfo.id,
nickname: store.state.userInfo.nickname,
avatar : store.state.userInfo.avatar
})
return await ToAsyncAwait(Im.init({
url: `${ENV.imUrl}/ws${par}`
}))
};
Im.interceptors.dataChangeAfter = () => {
let data = Im.sessionData.find(i => {
return (i.type === 4 && (typeof i.payload === 'string' ? JSON.parse(i.payload).type === 'system' : false));
}) || {}
let msgCount = data.unreadCount || 0;
store.commit('setSocketMsgData', JSON.parse(JSON.stringify(data)));
store.commit('setUnreadCount', msgCount);
}
Im.interceptors.onClose = () => {
Im.setSessionData([]);
Im.setCurSessionId(null);
store.commit('setSocketMsgData', {});
store.commit('setUnreadCount', 0);
}
}
export {
Im,
ImInit
}

@ -1,480 +0,0 @@
/*
* @Author: ch
* @Date: 2022-05-18 14:54:47
* @LastEditors: ch
* @LastEditTime: 2022-06-14 11:49:08
* @Description: file content
*/
import { CreateUUID, FormatDate, ToAsyncAwait } from "@/plugins/utils";
import './potoReq';
import './protoRsp';
const connect = Symbol('connect');
const send = Symbol('send');
const onMessage = Symbol('onMessage');
const fromatPotoReq = (traceId, traceType, content) => {
let messageModel = new proto.ReqModel();
messageModel.setTraceid(traceId);
messageModel.setTracetype(traceType);
content && messageModel.setContent(JSON.stringify(content));
return messageModel.serializeBinary();
},
fromatPotoRsp = (data) => {
const res = proto.RspModel.deserializeBinary(new Uint8Array(data));
let ctx = res.getContent();
ctx = ctx ? JSON.parse(ctx) : {};
if (ctx.payload) {
ctx.payload = JSON.parse(ctx.payload);
}
return {
content: ctx,
traceId: res.getTraceid(),
traceType: res.getTracetype(),
code: res.getCode(),
message: res.getMessage(),
};
};
class MsbIm {
defaultOption = {
ioKey: 'traceId',
reconnect: true,
};
socket = null;
isOpen = false;
queue = {};
interceptors = {
dataChangeBefore: null,
dataChangeAfter: null,
onClose: null,
onMessage: null,
};
sessionData = [];
curSessionId = null;
constructor(option) {
this.option = {
...this.defaultOption,
...option,
};
}
/**
* 创建连接返回一个Promise 创建成功并成功打开连接算连接成功
* @param {*} option
*/
[connect](option) {
return new Promise((resolve, reject) => {
const open = () => {
console.log('[im] open');
this.isOpen = true;
resolve(this.socket);
};
const message = async (res) => {
const result = fromatPotoRsp(res.data);
this.interceptors.onMessage && this.interceptors.onMessage(result);
// 处理服务端主动推送的消息
this[onMessage](result);
// 如果再消息堆里有此消息回调,则执行回调,并删除
const cbk = this.queue[result[this.option.ioKey]];
if (cbk) {
cbk(result.code !== 200 ? { error: result } : { result: result });
delete this.queue[result[this.option.ioKey]];
}
};
const close = () => {
console.log('[im] close');
this.interceptors.onClose && this.interceptors.onClose();
};
let isUni = false;
try {
isUni = uni;
} catch (e) {
isUni = false;
}
if (isUni) {
this.socket = uni.connectSocket({
...this.option,
fail(e) {
reject(e);
},
});
this.socket.onOpen(() => {
open();
this.socket.onMessage((res) => {
message(res);
});
});
this.socket.onClose(() => {
close();
});
} else if (WebSocket) {
try {
this.socket = new WebSocket(this.option.url);
this.socket.binaryType = 'arraybuffer';
this.socket.onopen = () => {
open();
};
this.socket.onmessage = (res) => {
message(res);
};
this.socket.onclose = () => {
close();
};
} catch (e) {
reject(e);
}
}
});
}
/**
* 向服务端发送消息||请求返回一个Promise对象收到ioKey对应的消息会算一个同步完成
* @param {*} data
*/
[send](data) {
return new Promise((resolve, reject) => {
if (!this.isOpen) {
return reject('连接未打开');
}
this.queue[data[this.option.ioKey]] = ({ result, error }) => {
if (result) {
resolve(result);
} else {
reject(error);
}
};
const par = fromatPotoReq(data.traceId, data.traceType, data.content);
let isUni = false;
try {
isUni = uni;
} catch (e) {
isUni = false;
}
if (isUni) {
this.socket.send({
data: par,
fail(e) {
reject({ error: e });
},
});
} else if (WebSocket) {
this.socket.send(par);
}
});
}
/**
* 服务端推送消息只处理服务端主动推送的消息
* @param {*} data
*/
[onMessage](data) {
// 判断非服务端主动推送消息不做处理
if (data[this.option.ioKey] || data.code !== 200) {
return false;
}
console.log('[im] 主动接收的消息', data);
let ctx = data.content;
let historyData = [...this.sessionData],
newData = [];
const hisIndex = historyData.findIndex((i) => i.id === ctx.sessionId);
if (hisIndex >= 0) {
// 存在会话往现有会话增加一条消息,并修改最后一条消息为当前消息
const curHisData = historyData[hisIndex];
curHisData.messageList.push(ctx);
curHisData.lastMessage = ctx;
// 不在当前会话窗口则向会话消息加1条未读
if (ctx.sessionId !== this.curSessionId) {
curHisData.unreadCount++;
} else {
this.setRead({
content: {
sessionId: this.curSessionId,
},
});
}
newData = historyData;
} else {
// 会话列表不存在,则创建一个会话
newData = [
...historyData,
{
fromAvatar: ctx.session.fromAvatar,
fromId: ctx.fromId,
fromNickname: ctx.session.fromNickname,
id: ctx.sessionId,
lastMessage: ctx,
messageList: [ctx],
updateTimeStamp: ctx.createTimeStamp,
unreadCount: 1,
},
];
}
this.setSessionData(newData);
}
init(config) {
return new Promise((resolve, reject) => {
const heart = () => {
// 要优化 心跳没回复需要重连
setTimeout(async () => {
if (this.isOpen) {
await this[send]({
traceId: CreateUUID(),
traceType: 0,
content: { text: 'ping' },
});
}
heart();
}, 1000);
};
this.option = {
...this.option,
...config,
};
this[connect]()
.then((res) => {
resolve(res);
heart();
})
.catch((e) => {
console.log('eeeee', e);
});
});
}
/**
* 设置数据
*/
setSessionData(data) {
let newData = JSON.parse(JSON.stringify(data));
this.interceptors.dataChangeBefore && this.interceptors.dataChangeBefore(newData, this.sessionData);
this.sessionData = newData;
this.interceptors.dataChangeAfter && this.interceptors.dataChangeAfter(this.sessionData);
}
/**
* 设置当前聊天窗口
* Data为Session数据
* @param {*} data
*/
setCurSessionId(id) {
this.curSessionId = id;
}
/**
* 获取会话列表
* @param {*} params
*/
async getSessionList(params) {
const par = {
traceId: CreateUUID(),
traceType: 1,
...params,
};
console.log('[im] 获取会话列表--start', par);
let { error, result } = await ToAsyncAwait(this[send](par));
console.log('[im] 获取会话列表--end', result, error);
if (error) {
return Promise.reject(error);
}
const { content } = result;
// let newData = [];
content.sessionVOS.forEach((item) => {
if (item.lastMessage) {
item.lastMessage.payload = JSON.parse(item.lastMessage.payload || {});
}
let historyData = this.sessionData;
let hisIndex = historyData.findIndex((i) => i.id === item.id);
if (hisIndex < 0) {
item.messageList = [];
}
// let historyData = this.sessionData;
// let hisIndex = historyData.findIndex((i) => i.id === item.id);
// if (hisIndex >= 0) {
// historyData[hisIndex].lastMessage = item.lastMessage;
// historyData[hisIndex].unreadCount++;
// newData.push(historyData[hisIndex]);
// } else {
// item.messageList = [];
// newData = [...newData, item];
// }
});
this.setSessionData(content.sessionVOS);
return Promise.resolve(result);
}
/**
* 获取会话的历史消息记录
* @param {*} params
*/
async getHistoryMsg() {
const curSessionIdx = this.sessionData.findIndex((i) => i.id === this.curSessionId);
const curSession = this.sessionData[curSessionIdx];
console.log(curSession, this.curSessionId,'this.curSessionId');
const msgList = curSession.messageList || [];
const par = {
traceId: CreateUUID(),
traceType: 2,
content: {
sessionId: this.curSessionId,
topMessageId: msgList.length ? msgList[0].id : null,
},
};
console.log('[im] 获取会话历史消息--start', par);
const { error, result } = await ToAsyncAwait(this[send](par));
console.log('[im] 获取会话历史消息--end', result, error);
if (error) {
return Promise.reject(error);
}
const { content } = result;
if (content.length) {
let newData = this.sessionData;
content.forEach((item) => {
item.payload = JSON.parse(item.payload);
});
newData[curSessionIdx].messageList = content.concat(newData[curSessionIdx].messageList);
this.setSessionData(newData);
}
return Promise.resolve(result);
}
/**
* 会话已读
* @param {*} params
*/
async setRead(params) {
const par = {
traceId: CreateUUID(),
traceType: '6',
...params,
};
console.log('[im] 会话已读--start', par);
const { error, result } = await this[send](par);
console.log('[im] 会话已读--end', result, error);
let newData = this.sessionData.map((item) => {
if (item.id == params.content.sessionId) {
item.unreadCount = 0;
}
return item;
});
this.setSessionData(newData);
}
/**
* 发送消息
* @param {*} params
*/
async sendMsg(params) {
const index = this.sessionData.findIndex((i) => i.id === this.curSessionId);
let curSession = this.sessionData[index];
// 临时消息体
let par = {
...params,
traceId: CreateUUID(),
traceType: 3,
};
let msgCtx = {
...params.content,
...par,
createTimeStamp: new Date().getTime(),
sendStatus: 'loading',
};
if (typeof msgCtx.payload === 'string') {
msgCtx.payload = JSON.parse(msgCtx.payload);
}
// 点发送,立即把消息加入消息列表,标记为发送中状态
curSession.messageList.push(msgCtx);
this.setSessionData(this.sessionData);
// 超过时间未返回视为发送失败
this.timerStatus(msgCtx);
console.log('[im] 发送消息--start', par);
const { error, result } = await ToAsyncAwait(this[send](par));
console.log('[im] 发送消息--end', result, error);
// 接到通知,标记消息是否发送成功
for (let i = curSession.messageList.length; i--; ) {
const item = curSession.messageList[i];
if (item[this.option.ioKey] === par[this.option.ioKey]) {
curSession.messageList[i].sendStatus = msgCtx.sendStatus = error ? 'fail' : 'success';
break;
}
}
let newData = [...this.sessionData];
newData[index] = curSession;
this.setSessionData(newData);
if (error) {
return Promise.reject(error);
}
return Promise.resolve(result);
}
/**
* 发送失败时重新发送
* @param {*} params
*/
async resend(params) {
params.sendStatus = 'loading';
this.timerStatus(params);
console.log('[im] 重新发送消息--start', params);
const { error, result } = await ToAsyncAwait(
this[send]({
traceId: params.traceId,
traceType: params.traceType,
content: params.content,
})
);
console.log('[im] 重新发送消息--end', result, error);
params.createTimeStamp = result.createTimeStamp;
if (error) {
params.sendStatus = 'fail';
return Promise.reject(error);
}
params.sendStatus = 'success';
return Promise.resolve(result);
}
timerStatus(msg) {
setTimeout(() => {
if (msg.sendStatus === 'loading') {
msg.sendStatus = 'fail';
delete this.queue[msg.traceId];
}
}, 3000);
}
/**
* 主动创建会话
* @param {*} params
*/
async createSession(params) {
const par = {
traceId: CreateUUID(),
traceType: 9,
...params,
};
console.log('[im] 主动创建会话--start', par);
const { result, error } = await ToAsyncAwait(this[send](par));
console.log('[im] 主动创建会话--end', result, error);
if (error) {
return Promise.reject(error);
}
const { content } = result;
let historyData = this.sessionData;
let curSession = historyData.find((i) => i.id === content.id);
if (!curSession) {
curSession = {
...content,
unreadCount: 0,
messageList: [],
};
const newData = [...historyData, curSession];
this.setSessionData(newData);
}
return Promise.resolve(result);
}
close() {
this.socket.close();
this.socket = null;
this.isOpen = false;
this.setSessionData([]);
}
}
export default MsbIm;

@ -0,0 +1,3 @@
# ignore page inside ignore folder
pages/**/moudles/**
pages/layouts/moudles/**

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Before

Width:  |  Height:  |  Size: 756 B

After

Width:  |  Height:  |  Size: 756 B

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 762 B

Before

Width:  |  Height:  |  Size: 850 B

After

Width:  |  Height:  |  Size: 850 B

Before

Width:  |  Height:  |  Size: 613 B

After

Width:  |  Height:  |  Size: 613 B

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before

Width:  |  Height:  |  Size: 972 B

After

Width:  |  Height:  |  Size: 972 B

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 928 B

Before

Width:  |  Height:  |  Size: 763 B

After

Width:  |  Height:  |  Size: 763 B

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

Before

Width:  |  Height:  |  Size: 812 B

After

Width:  |  Height:  |  Size: 812 B

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 290 KiB

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Before

Width:  |  Height:  |  Size: 207 KiB

After

Width:  |  Height:  |  Size: 207 KiB

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Before

Width:  |  Height:  |  Size: 219 KiB

After

Width:  |  Height:  |  Size: 219 KiB

Before

Width:  |  Height:  |  Size: 199 KiB

After

Width:  |  Height:  |  Size: 199 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 445 B

After

Width:  |  Height:  |  Size: 445 B

Before

Width:  |  Height:  |  Size: 445 B

After

Width:  |  Height:  |  Size: 445 B

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Before

Width:  |  Height:  |  Size: 904 B

After

Width:  |  Height:  |  Size: 904 B

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 700 B

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

Before

Width:  |  Height:  |  Size: 671 B

After

Width:  |  Height:  |  Size: 671 B

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 179 KiB

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before

Width:  |  Height:  |  Size: 330 B

After

Width:  |  Height:  |  Size: 330 B

Before

Width:  |  Height:  |  Size: 653 B

After

Width:  |  Height:  |  Size: 653 B

Before

Width:  |  Height:  |  Size: 728 B

After

Width:  |  Height:  |  Size: 728 B

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 369 B

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 928 B

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before

Width:  |  Height:  |  Size: 134 B

After

Width:  |  Height:  |  Size: 134 B

Before

Width:  |  Height:  |  Size: 133 B

After

Width:  |  Height:  |  Size: 133 B

Before

Width:  |  Height:  |  Size: 135 B

After

Width:  |  Height:  |  Size: 135 B

Before

Width:  |  Height:  |  Size: 135 B

After

Width:  |  Height:  |  Size: 135 B

Before

Width:  |  Height:  |  Size: 540 B

After

Width:  |  Height:  |  Size: 540 B

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 553 B

Before

Width:  |  Height:  |  Size: 215 KiB

After

Width:  |  Height:  |  Size: 215 KiB

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 242 KiB

Before

Width:  |  Height:  |  Size: 358 B

After

Width:  |  Height:  |  Size: 358 B

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 661 B

After

Width:  |  Height:  |  Size: 661 B

Before

Width:  |  Height:  |  Size: 842 B

After

Width:  |  Height:  |  Size: 842 B

Before

Width:  |  Height:  |  Size: 841 B

After

Width:  |  Height:  |  Size: 841 B

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

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

Loading…
Cancel
Save