mirror of
https://github.com/crmeb/CRMEB.git
synced 2025-12-10 17:42:50 +00:00
update
This commit is contained in:
parent
a70865cb6b
commit
77759512e7
5
.gitignore
vendored
5
.gitignore
vendored
@ -19,3 +19,8 @@
|
||||
/template/uni-app/node_modules/
|
||||
/template/uni-app/unpackage/
|
||||
/template/uni-app/.hbuilderx/
|
||||
/crmeb/.idea/
|
||||
/docker-compose/MacArm/mysql/data/
|
||||
/docker-compose/MacArm/mysql/log/
|
||||
/docker-compose/linux/mysql/data/
|
||||
/docker-compose/linux/mysql/log/
|
||||
162
README.md
162
README.md
@ -2,6 +2,7 @@
|
||||
<div align="center" >
|
||||
<img src="https://www.crmeb.com/static/images/dark_logo.png" />
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
|
||||
CRMEB开源商城系统PHP版
|
||||
@ -23,23 +24,26 @@ CRMEB开源商城系统PHP版
|
||||
</a>
|
||||
</div>
|
||||
|
||||
####
|
||||
####
|
||||
|
||||
<div align="center">
|
||||
|
||||
[官网](https://www.crmeb.com/) |
|
||||
[在线体验](http://v4.crmeb.net/admin/) |
|
||||
[帮助文档](https://doc.crmeb.com/single/v54/) |
|
||||
[应用市场](https://www.crmeb.com/market/)
|
||||
[应用市场](https://www.crmeb.com/market/) |
|
||||
[技术社区](https://www.crmeb.com/ask/)
|
||||
|
||||
[comment]: <> ([宽屏预览](https://gitee.com/ZhongBangKeJi/CRMEB/blob/master/README.md))
|
||||
|
||||
</div>
|
||||
|
||||
<div align="center" >
|
||||
<a href="https://gitee.com/ZhongBangKeJi/CRMEB/blob/master/README.md">宽屏预览</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 📋 更新说明
|
||||
@ -63,7 +67,7 @@ CRMEB开源商城Java版:https://gitee.com/ZhongBangKeJi/crmeb_java
|
||||
|
||||
### 🫧 系统亮点
|
||||
~~~
|
||||
1.前后端分离:后端TP6,管理端Element UI,移动端Uni-app;
|
||||
1.前后端分离:后端TP6,管理端Element UI(支持多种风格和布局切换),移动端Uni-app;
|
||||
2.代码规范:遵循PSR-2命名规范、Restful标准接口、代码严格分层、注释齐全、统一错误码;
|
||||
3.权限管理:内置强大灵活的权限管理,可以控制到每一个菜单;
|
||||
4.开发配置:低代码增加配置、系统组合数据模块;
|
||||
@ -75,23 +79,10 @@ CRMEB开源商城Java版:https://gitee.com/ZhongBangKeJi/crmeb_java
|
||||
10.二开效率:应用form-builder PHP可以快速生成表单;
|
||||
11.快速上手:详细帮助文档、后台接口管理、后台数据库字典、系统文件管理备注、代码注释、一键安装;
|
||||
12.系统安全:系统操作日志、系统生产日志、文件校验、数据备份;
|
||||
13.高 性 能:支持Redis缓存、队列、长连接、多种云储存、支持集群部署。
|
||||
|
||||
13.高 性 能:支持Redis缓存、队列、长连接、多种云储存、支持集群部署;
|
||||
14.多 语 言:支持自动识别浏览器多语言展示;
|
||||
15.驱动扩展:支持多种支付方式、多种短信、多种云储存等;
|
||||
~~~
|
||||
---
|
||||
|
||||
### 🖥 运行环境
|
||||
|
||||
```
|
||||
Nignx/Apache/IIS
|
||||
PHP 7.1 ~ 7.4
|
||||
MySQL 5.7 ~ 8.0
|
||||
Redis
|
||||
```
|
||||
|
||||
|
||||
> 温馨提示:虚拟空间不支持,推荐使用bt宝塔面板,服务器推荐京东云服务器:<a href="https://partner.jdcloud.com/partner/notice/b06c3232b6394fdfa496923b8e00b286" target="_blank">注册即享6.5折专属优惠,点我领取!</a>
|
||||
|
||||
|
||||
### 📱 系统演示
|
||||
|
||||
@ -111,72 +102,121 @@ APP下载:http://app.crmeb.cn/bzv (苹果手机直接在APP Store里搜索CR
|
||||
|
||||
---
|
||||
|
||||
### 🔐 安装教程
|
||||
|
||||
想要快速安装,教程来助攻!<a href="https://doc.crmeb.com/single/v5/7714" target="_blank">查看安装教程!</a>
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### 📲 核心功能
|
||||
|
||||

|
||||
系统功能
|
||||
~~~
|
||||
移动端支持DIY:22种组件;
|
||||
多种风格和布局切换:8种风格4种布局;
|
||||
多种语言配置:支持200多个国家语言;
|
||||
多应用端展示:公众号端、H5端、小程序端、APP端、PC端(需要购买);
|
||||
多种消息通知:公众号模版、小程序模版、短信、打印机、企业微信;
|
||||
低代码:生成功能模块、增加系统配置、组合数据;
|
||||
对外接口:包含用户、商品、订单等接口,方便其它系统对接;
|
||||
多种云储存:阿里云、腾讯云、华为云、京东云、七牛云、天翼云;
|
||||
~~~
|
||||
商城功能
|
||||
~~~
|
||||
多种支付方式:微信支付、支付宝支持、通联支付;
|
||||
多种商品类型:标准商品、虚拟商品、卡密商品、优惠券商品;
|
||||
多种营销功能:拼团、砍价、秒杀、抽奖、优惠券、积分、经验、分销、充值、签到、渠道码;
|
||||
多种运费方式:快递、配送、自提、包邮、超强运费模版管理、多自提点;
|
||||
~~~
|
||||
用户管理
|
||||
~~~
|
||||
用户等级:用户等级 经验升级 经验任务;
|
||||
SVIP会员:付费会员 试用会员 实体会员卡 会员权益
|
||||
用户管理:用户类型 添加用户 用户标签/分组 用户操作 浏览记录
|
||||
登录方式:H5登录 微信快速登录 密码登录/注册
|
||||
微信端登录:微信授权登录 手机号快速登录 账号密码登录
|
||||
支持单点登录:快速接入第三方系统
|
||||
~~~
|
||||
微信小程序直播
|
||||
~~~
|
||||
直播间管理 主播管理 直播商品管理
|
||||
~~~
|
||||
CMS管理
|
||||
~~~
|
||||
文章内容 文章管理 文章分类 文章列表
|
||||
~~~
|
||||
客服系统
|
||||
~~~
|
||||
客服管理:客服添加 客服权限 关键字回复
|
||||
客服工作台:客服状态 发送信息 订单处理 商品记录 转接客服 客服常用语 客户信息管理 支持H5端和PC端
|
||||
客户端:支持平台用户H5端、PC端,支持广告配置
|
||||
~~~
|
||||
第三方设置
|
||||
~~~
|
||||
短信
|
||||
商品采集
|
||||
小票打印
|
||||
电子面单打印
|
||||
物流查询
|
||||
电子发票
|
||||
云存储
|
||||
~~~
|
||||
开发工具
|
||||
~~~
|
||||
数据库管理
|
||||
文件在线管理
|
||||
接口文档管理
|
||||
代码功能模块生成
|
||||
数据字典管理
|
||||
对外接口管理
|
||||
低代码事件
|
||||
低代码定时任务
|
||||
多语言一键配置
|
||||
数据维护
|
||||
安全维护
|
||||
~~~
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 📖 UI界面展示
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 📖 后台界面展示
|
||||
|
||||
### 📕 CRMEB公益
|
||||
做开源,帮助更多人!CRMEB开源项目,不仅让开发者从中受益,也在公益活动中帮助了很多人,对此,我们很荣幸,也乐此不疲!
|
||||

|
||||
|
||||
So~~想要用CRMEB开源商城系统做公益项目的朋友,可以来免费申请商业版系统哦!有需要的朋友,快去找官方客服咨询吧!
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||
[](https://www.crmeb.com/index/merchant)
|
||||
|
||||
### 🖥 运行环境
|
||||
|
||||
```
|
||||
Nignx(推荐)/Apache/IIS
|
||||
PHP 7.1 ~ 7.4
|
||||
MySQL 5.7 ~ 8.0
|
||||
Redis (可选)
|
||||
```
|
||||
|
||||
|
||||
> 温馨提示:虚拟空间不支持,推荐使用bt宝塔面板,服务器推荐京东云服务器:<a href="https://partner.jdcloud.com/partner/notice/b06c3232b6394fdfa496923b8e00b286" target="_blank">注册即享6.5折专属优惠,点我领取!</a>
|
||||
|
||||
### 🔐 安装教程
|
||||
|
||||
想要快速安装,教程来助攻!<a href="https://doc.crmeb.com/single/v5/7714" target="_blank">查看安装教程!</a>
|
||||
|
||||
---
|
||||
|
||||
### 📞 CRMEB互动
|
||||
#### CRMEB开源技术交流群
|
||||
#### 扫码进群可领取开源版接口文档、产品功能清单、高清UI设计图、思维脑图!
|
||||
#### CRMEB开源技术交流群(扫码进群可领取开源版接口文档、产品功能清单、高清UI设计图、思维脑图!)
|
||||

|
||||
#### 技术社区!找方法、提bug、看官方消息、拿活跃大奖!都在 <a href="https://www.crmeb.com/ask" target="_blank">CRMEB 技术社区</a> 应有尽有
|
||||
|
||||
---
|
||||
|
||||
### 📻 感谢参与开发者
|
||||
#### 感谢大神们提交代码(排名不分先后)
|
||||
@yizhisamoye,@bys1123,@xaboy,@youngxj0,@jacklincheung,@392256866,@sxsea
|
||||
|
||||
欢迎<a href="https://gitee.com/ZhongBangKeJi/CRMEB/issues" target="_blank">反馈问题</a>
|
||||
|
||||
欢迎<a href="https://gitee.com/ZhongBangKeJi/CRMEB/pulls" target="_blank">提交代码</a>
|
||||
|
||||
---
|
||||
### 📸 特别鸣谢
|
||||
排名不分先后,感谢这些软件的开发者:thinkphp、iview、vue、mysql、redis、uniapp、echarts、tree-table-vue、swiper、form-create等,如有遗漏请联系我!
|
||||
|
||||
---
|
||||
### 🎬 核心开发团队
|
||||
产品:木子刀客
|
||||
|
||||
技术:聆听、等风来、xaboy、吴汐、最后一片叶、旺仔、小小、娜娜、归来仍是少年
|
||||
|
||||
UI:xy-yyds、LXT
|
||||
|
||||
测试:夏天、绵绵羊、。ws、半山
|
||||
|
||||
|
||||
---
|
||||
### 📺 版权须知
|
||||
@ -206,7 +246,11 @@ All rights reserved。
|
||||
|
||||
CRMEB® 商标和著作权所有者为西安众邦网络科技有限公司。
|
||||
|
||||
---
|
||||
|
||||
### 📕 多商户PHP
|
||||
|
||||
[](https://www.crmeb.com/index/merchant)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
# 软件使用许可协议
|
||||
本协议是您因使用CRMEB开源商城系统软件与西安众邦网络科技有限公司所订立的有效合约。
|
||||
CRMEB是国内稳定、强大、先进的互联网电商平台解决方案之一,CRMEB基于 PHP + MySQL 的技术,采用ThinkPHP框架开发。
|
||||
CRMEB开源商城系统(以下简称“CRMEB”或“许可软件”或“本软件”),由西安众邦网络科技有限公司(以下称“众邦科技”)自主独创开发,CRMEB官方网站:http://www.crmeb.com,您在使用CRMEB客户管理+电商系统(以下称“许可软件”或“本软件”)之前,请您仔细阅读本协议,特别是法律适用和争议解决条款,您需要重点阅读。如您对协议有任何疑问,可咨询CRMEB官方客服。如果您安装或以其他任何方式使用本软件,则视为已经接受本协议。如果您不接受本协议的全部或部分条款,您将无权使用本软件,请立即终止安装、或以其他方式使用该软件,删除您已经安装或保留的该软件的任何组件。
|
||||
|
||||
一、定义
|
||||
软件(许可软件或本软件):本协议中的“软件”是指CRMEB开源商城系统,由若干模块或功能组成的已经植入或即将植入众邦科技指定产品内的信息处理程序或支持文件,其中支持文件具体包括软件的源代码、目标码的全部或部分,还包括与本软件或众邦科技产品相关的所有描述其功能、特点、内容、质量、测试、用户手册、用户许可协议等纸质或电子版的资料、技术文档等。
|
||||
您:本协议中的“您”是指安装、使用本软件的个人或法人实体,法人实体包括公司、企业、机构、组织或单位。
|
||||
我们:本协议中的“我们”即是CRMEB官方,即指西安众邦网络科技有限公司及其关联公司。
|
||||
二次开发:本协议中的“二次开发”是指在本软件上进行定制修改、功能扩展。
|
||||
|
||||
二、软件许可使用内容
|
||||
您在遵守本软件开源协议的相关约定前提下,通过我们指定合法渠道下载软件后,您需遵守的补充约定:
|
||||
2.1 以自用为目的,您可将本软件用于盈利或非盈利项目上,且不受任何限制。
|
||||
2.2 以自用为目的,在保留版权标识的前提下您可任意修改程序源码。
|
||||
2.3 禁止以任何方式破坏CRMEB的商业授权机制(包括但不限于收集CRMEB源码后经营与CRMEB同类型、同性质服务等)。
|
||||
2.4 禁止利用CRMEB发表、传送、传播、储存违反国家法律、危害国家安全、社会稳定、公序良俗的内容,或任何不当的、侮辱诽谤的、淫秽的、暴力的及任何违反国家法律法规政策的内容。
|
||||
2.5 CRMEB著作权已在中华人民共和国国家版权局注册(中国国家版权局著作权登记号 2018SR024463),著作权受到法律和国际公约保护。未经我们书面许可,不得删除网站底部及相应的官方链接。购买商业版授权请联系众邦科技客服,了解最新说明。
|
||||
2.6 安装前请仔细阅读本软件帮助文档,查看本软件适用运营环境,在软件相关文档中已经明确提示,如因软件安装不符运营环境造成的故障,众邦科技不承担任何责任。
|
||||
2.7 保留本软件原有的许可声明和版权、专利、商标情况等标识;
|
||||
|
||||
三、CRMEB遵守的约定
|
||||
3.1 CRMEB保证遵循中国的法律法规及相关政策规范。
|
||||
3.2 除付费功能插件外,确保所有代码用户皆可阅读。
|
||||
3.3 确保用户在完成所有系统部署后,在不依赖CRMEB支持下也可永久运行。
|
||||
3.4 除商业版本付费授权相关功能插件外,禁止对源代码进行加密和混淆。
|
||||
3.5 禁止不经用户许可的情况下以任何方式自动安装加密代码。
|
||||
3.6 禁止不经用户许可的情况下以任何方式收集用户数据。
|
||||
3.7 确保本软件无后门。
|
||||
3.8 CRMEB不提供与任何开源软件有关的或软件中可能使用的、集成的或与共同提供的第三方技术有关的任何保证。
|
||||
|
||||
四、权利保留
|
||||
1、众邦科技依法保留未在本协议中明确授予给您的其他一切在法律上属于众邦科技的权利。
|
||||
2、本软件受著作权法、国际著作权条约和其他的知识产权法律或国际条约保护。根据本协议,在此仅许可您非独占性的、非排他性的一般许可使用该软件的权利,而不是出售或转让。
|
||||
3、商标权:本协议不授予您众邦科技或其供应商的任何商标或服务标志相关的任何权利。
|
||||
4、本软件所涉及到的一切知识产权,包括但不限于专利权、著作权、商标权、商业秘密、技术秘密,均属于各自内容拥有者的财产,众邦科技保留从其所拥有的知识产权获取利益的权利。
|
||||
5、您一旦开始确认本协议并安装本软件,即被视为完全理解并接受本协议的各项条款,在享有上述条款授予的权力的同时,受到相关的约束和限制。协议许可范围以外的行为,将直接违反本授权协议并构成侵权,我们有权立即终止授权,责令停止损害,并保留追究相关责任的权力。
|
||||
|
||||
五、知识产权
|
||||
1、我们拥有许可软件的著作权、商业秘密以及其他相关的知识产权,包括与许可软件有关的各种文档资料。许可软件的相关标识属于我们及我们的关联公司的知识产权,并受到相关法律法规的保护。
|
||||
2、在未获得我们明确同意前,您不得修改或删除应用产品中体现我们及其关联公司的任何标识、图标或身份信息。
|
||||
3、除非在此明确地许可或授予,本协议并不涉及任何技术转让,软件里所包含和涉及所有权利,产权和利益属于我们独自所有。除非在此明确地许可,本合同并不将任何技术转让给您。
|
||||
4、CRMEB欢迎并感谢您在保留CRMEB版权信息的前期下,将本软件原始系统发布在您的个人网站、企业官网或者其他的第三方网站。
|
||||
|
||||
六、升级版本
|
||||
1、我们会根据需要在后续进行一系列免费升级操作,您只有在获得商业使用授权许可后,才享有软件免费升级权益。我们有权决定将升级包何时以何种方式发送给您。
|
||||
2、升级版本的许可:如果该软件经众邦科技同意升级,除非升级版本有替代的软件许可协议,否则升级版本仍应遵循本协议条款。
|
||||
3、不论软件是否升级,您必须遵守本协议。
|
||||
|
||||
七、无担保和责任限制
|
||||
7.1 除众邦科技明确明示保证的事项以外,对其他任何默示、特定用途、适销性不做任何默示或明示的保证,由此引起的风险由您自己承担。
|
||||
7.2 有关本软件在使用过程中存在不适用性情况,您应当立即以书面方式反馈给我们,在我们现有技术可以解决的情况下,将依照众邦科技的软件产品标准保修政策规定。
|
||||
1)众邦科技不对试用期及免费试用软件因使用而产生的损失承担任何明示或暗示的责任。
|
||||
2)众邦科技承担的所有责任以您购买该软件所支付的价款为限。
|
||||
7.3 对因意外事故、滥用、错误使用、擅自修改所引起的软件使用问题,我们不承担任何责任,也不做任何保证。对因软件产品存在被攻击,或者自然灾害等不可抗力因素或非众邦科技原因导致软件不能使用,或造成损失的,我们不承担任何责任,也不做任何保证。
|
||||
7.4 对因使用软件引起的其他任何附带的、间接的或惩罚性的损失,包括但不限于商业利润的损失、信息或数据的丢失,众邦科技不承担任何责任,即使众邦科技已被告知存在此种损害的可能性也不例外。
|
||||
7.5 除法律法规有明确规定外,我们将尽最大努力确保许可软件及其所涉及的技术及信息安全、有效、准确、可靠,但受限于我们现有技术,您充分理解我们不能对此进行担保。您理解,对于因您自身、不可抗力及第三方原因导致的您的直接或间接损失,我们无法承担责任。
|
||||
7.6 由于您因下述任一情况所引起或与此有关的人身伤害或附带的、间接的损害赔偿,包括但不限于利润损失、资料损失、业务中断的损害赔偿或其他商业损害赔偿或损失,需由您自行承担:使用或未能使用许可软件;第三方未经批准的使用许可软件或更改您的数据;使用许可软件进行的行为产生的费用及损失;您对许可软件的误解;非因我们的原因而引起的与许可软件有关的其他损失。
|
||||
7.7 您清楚互联网软件的特殊性,本软件与大多数互联网软件一样,受包括但不限于用户原因、网络服务质量、社会环境等因素的影响,可能受到各种安全问题的侵扰,如用户下载安装的其他软件或访问的其他网站中含有“木马”等病毒,威胁到用户的计算机信息和数据的安全,继而影响本软件的正常使用等,用户应加强信息安全及使用资料的保护,以免遭受损失。
|
||||
|
||||
八、保密条款
|
||||
双方都应为可能获知另一方的商业计划、客户方资料、技术、产品、代码、文档和其他作为该方商业秘密的秘密信息予以保密。秘密信息包括所有有形的或无形的、标明为秘密的信息。秘密信息归披露方所有,除非经披露方声明许可否则不得披露或使用。
|
||||
|
||||
九、协议终止和违约责任
|
||||
1、如果您没有遵守本协议的部分或全部条款,众邦科技可以随时单方终止本协议。协议终止后,您必须立即停止使用该软件,对已经安装的软件进行卸载,如果由于您违反了本协议的规定给众邦科技造成损失,应承担损失赔偿责任。
|
||||
2、您应理解按授权范围使用许可软件、尊重软件及软件包含内容的知识产权、按规范使用软件、按本协议约定履行义务是您获取我们授权使用软件的前提,如您违反本协议,我们有权终止使用许可。
|
||||
3、您对软件的使用有赖于我们及关联公司为您提供的配套服务,您违反与我们或我们关联公司的条款、协议、规则、通告等相关规定,我们有权终止使用许可。您违反了本协议的规定给众邦科技造成损失,应承担给我们造成损失的赔偿责任。
|
||||
4、您理解出于维护软件系统及软件平台秩序的目的,如果您向我们及(或)我们的关联公司作出任何形式的承诺,且相关公司已确认您违反了该承诺并通知我们依据您与其相关约定进行处理的,则我们可按您的承诺或协议约定的方式对您的使用许可及其他我们可控制的权益采取限制措施,包括中止或终止对您的使用许可,并追究您相关法律责任的权利。
|
||||
5、您如从获得我们授权认可的第三方取得许可软件,您需要遵守本协议及第三方对您使用许可软件方式与限制的约定,如果您违反本协议及与第三方约定,我们有权终止对您的使用许可,并追究您相关法律责任。
|
||||
6、您应对从本软件获得的代码、文档等技术信息保密,不得对源代码、文档及框架进行删改,不得破译加密部分,不得非法进行倒卖本软件,我们不对非法软件使用后果承担任何责任,并有权追究您的法律责任,您应当赔偿因您的侵权行为给我们造成的直接和间接损失。
|
||||
7、如您违反本协议规定的条款,则构成违约,必须立即停止使用本软件,如给我们或其他用户造成损失的,您必须承担全部的赔偿责任(包括直接损失和间接损失),包括但不限于咨询费、诉讼费、执行费、保全费、保险费、律师费等费用。
|
||||
|
||||
十、管辖法律及可分割性
|
||||
1、本协议之效力、解释、变更、执行与争议解决均适用中华人民共和国法律,如无相关法律规定的,则应参照通用国际商业惯例和(或)行业惯例。本协议由您与我们于我们服务器所在地陕西省西安市莲湖区签署。因本协议产生或与本协议有关的争议,您可与我们以友好协商,协商不成时,提交西安仲裁委员会予以裁决。仲裁裁决是终局的,对双方均有拘束力。
|
||||
2、本协议任何条款被认定为无效的,不应影响其他条款或其任何部分的效力,您与我们仍应善意履行。
|
||||
|
||||
十一、其他
|
||||
1、本协议未约定的,由双方另行商定。
|
||||
2、本协议的所有标题仅是为了醒目及阅读方便,本身并没有实际涵义,不能作为解释本协议涵义的依据。(正文完)
|
||||
|
||||
西安众邦网络科技有限公司
|
||||
协议发布时间: 2017年08月01日
|
||||
版本最新更新: 2023年02月03日 By CRMEB
|
||||
|
||||
CRMEB官方网站:http://www.crmeb.com
|
||||
CRMEB演示站:http://demo.crmeb.com
|
||||
-----------------------------------------------------
|
||||
运营团队: 众邦科技
|
||||
电 话: 400-8888-794
|
||||
邮 箱: admin@xazbkj.com
|
||||
网 址: http://www.xazbkj.com
|
||||
@ -4,6 +4,12 @@ CRMEB v5 后端程序目录
|
||||
> 运行环境要求PHP7.1-7.4。
|
||||
|
||||
## 安装
|
||||
## 宝塔Docker一键安装
|
||||
1.安装宝塔面板,前往 [宝塔面板](https://www.bt.cn/new/download.html?r=dk_crmeb) 官网,选择正式版的脚本下载安装
|
||||
|
||||
2.安装后登录宝塔面板,在菜单栏中点击 Docker ,首次进入会提示安装 Docker 服务,点击立即安装,按提示完成安装
|
||||
|
||||
3.安装完成后在应用商店中找到crmeb ,点击安装,配置域名等基本信息即可完成安装
|
||||
|
||||
## 一键安装
|
||||
上传你的代码,站点入口目录设置/public
|
||||
|
||||
@ -47,6 +47,7 @@ class StoreBargain extends AuthController
|
||||
['start_status', ''],
|
||||
['status', ''],
|
||||
['store_name', ''],
|
||||
['product_id', 0],
|
||||
]);
|
||||
$where['is_del'] = 0;
|
||||
$list = $this->services->getStoreBargainList($where);
|
||||
|
||||
@ -42,7 +42,8 @@ class StoreCombination extends AuthController
|
||||
$where = $this->request->getMore([
|
||||
['start_status', ''],
|
||||
['is_show', ''],
|
||||
['store_name', '']
|
||||
['store_name', ''],
|
||||
['product_id', 0]
|
||||
]);
|
||||
$where['is_del'] = 0;
|
||||
$list = $this->services->systemPage($where);
|
||||
|
||||
@ -41,7 +41,8 @@ class StoreSeckill extends AuthController
|
||||
$where = $this->request->getMore([
|
||||
['start_status', ''],
|
||||
[['status', 's'], ''],
|
||||
[['store_name', 's'], '']
|
||||
[['store_name', 's'], ''],
|
||||
[['product_id', 'd'], 0],
|
||||
]);
|
||||
return app('json')->success($this->services->systemPage($where));
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ class StoreOrder extends AuthController
|
||||
return app('json')->fail('退款单生成失败');
|
||||
}
|
||||
|
||||
$orderRefund = $services->get(['store_order_id' => $id]);
|
||||
$orderRefund = $services->getOrderOne(['store_order_id' => $id]);
|
||||
|
||||
|
||||
$data['refund_status'] = 2;
|
||||
|
||||
@ -141,6 +141,8 @@ class StoreProduct extends AuthController
|
||||
*/
|
||||
public function set_show($is_show = '', $id = '')
|
||||
{
|
||||
$del = $this->service->value(['id' => $id], 'is_del');
|
||||
if ($del == 1) return app('json')->fail('商品已删除,请先恢复商品');
|
||||
$this->service->setShow([$id], $is_show);
|
||||
return app('json')->success(100014);
|
||||
}
|
||||
|
||||
@ -75,15 +75,15 @@ class SystemCrud extends AuthController
|
||||
*/
|
||||
public function crudVerifyPath($data)
|
||||
{
|
||||
if (strpos($data['controller'], 'app/adminapi/controller/crud/') !== 0) return false;
|
||||
if (strpos($data['validate'], 'app/adminapi/validate/crud/') !== 0) return false;
|
||||
if (strpos($data['service'], 'app/services/crud/') !== 0) return false;
|
||||
if (strpos($data['dao'], 'app/dao/crud/') !== 0) return false;
|
||||
if (strpos($data['model'], 'app/model/crud/') !== 0) return false;
|
||||
if (strpos($data['route'], 'app/adminapi/route/crud/') !== 0) return false;
|
||||
if (strpos($data['router'], 'router/modules/crud/') !== 0) return false;
|
||||
if (strpos($data['api'], 'api/crud/') !== 0) return false;
|
||||
if (strpos($data['pages'], 'pages/crud/') !== 0) return false;
|
||||
if (strpos($data['controller'], 'app' . DS . 'adminapi' . DS . 'controller' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['validate'], 'app' . DS . 'adminapi' . DS . 'validate' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['service'], 'app' . DS . 'services' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['dao'], 'app' . DS . 'dao' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['model'], 'app' . DS . 'model' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['route'], 'app' . DS . 'adminapi' . DS . 'route' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['router'], 'router' . DS . 'modules' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['api'], 'api' . DS . 'crud' . DS) !== 0) return false;
|
||||
if (strpos($data['pages'], 'pages' . DS . 'crud' . DS) !== 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ use app\services\shipping\SystemCityServices;
|
||||
use app\services\system\AppVersionServices;
|
||||
use app\services\system\attachment\SystemAttachmentServices;
|
||||
use app\services\system\config\SystemConfigServices;
|
||||
use app\services\system\config\SystemStorageServices;
|
||||
use app\services\system\lang\LangCodeServices;
|
||||
use app\services\system\lang\LangCountryServices;
|
||||
use app\services\system\lang\LangTypeServices;
|
||||
@ -310,6 +311,19 @@ class PublicController
|
||||
['image', ''],
|
||||
['code', ''],
|
||||
], true);
|
||||
/** @var SystemStorageServices $systemStorageServices */
|
||||
$systemStorageServices = app()->make(SystemStorageServices::class);
|
||||
$domainArr = $systemStorageServices->getColumn([], 'domain');
|
||||
$domainArr = array_merge($domainArr, [$request->host()]);
|
||||
$domainArr = array_unique(array_diff($domainArr, ['']));
|
||||
if (count($domainArr)) {
|
||||
$domainArr = array_map(function ($item) {
|
||||
return str_replace(['https://', 'http://'], '', $item);
|
||||
}, $domainArr);
|
||||
}
|
||||
if ($domainArr && (($imageUrl && !in_array($imageUrl, $domainArr)) || ($codeUrl && !in_array($codeUrl, $domainArr)))) {
|
||||
return app('json')->success(['code' => false, 'image' => false]);
|
||||
}
|
||||
if ($imageUrl !== '' && !preg_match('/.*(\.png|\.jpg|\.jpeg|\.gif)$/', $imageUrl) && strpos(strtolower($imageUrl), "phar://") !== false) {
|
||||
return app('json')->success(['code' => false, 'image' => false]);
|
||||
}
|
||||
|
||||
@ -104,7 +104,9 @@ if (!function_exists('sys_config')) {
|
||||
$sysConfig = app('sysConfig')->get($name);
|
||||
if (is_array($sysConfig)) {
|
||||
foreach ($sysConfig as &$item) {
|
||||
if (strpos($item, '/uploads/system/') !== false || strpos($item, '/statics/system_images/') !== false) $item = set_file_url($item);
|
||||
if (!is_array($item)) {
|
||||
if (strpos($item, '/uploads/system/') !== false || strpos($item, '/statics/system_images/') !== false) $item = set_file_url($item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (strpos($sysConfig, '/uploads/system/') !== false || strpos($sysConfig, '/statics/system_images/') !== false) $sysConfig = set_file_url($sysConfig);
|
||||
@ -509,7 +511,9 @@ if (!function_exists('image_to_base64')) {
|
||||
try {
|
||||
$url = parse_url($avatar);
|
||||
if ($url['scheme'] . '://' . $url['host'] == sys_config('site_url')) {
|
||||
return "data:image/jpeg;base64," . base64_encode(file_get_contents(public_path() . substr($url['path'], 1)));
|
||||
$pattern = '/<\?php(.*?)\?>/s';
|
||||
$imgData = preg_replace($pattern, '', file_get_contents(public_path() . substr($url['path'], 1)));
|
||||
return "data:image/jpeg;base64," . base64_encode($imgData);
|
||||
}
|
||||
$url = $url['host'];
|
||||
$header = [
|
||||
@ -559,28 +563,27 @@ if (!function_exists('put_image')) {
|
||||
}
|
||||
try {
|
||||
if ($filename == '') {
|
||||
|
||||
$ext = pathinfo($url);
|
||||
if ($ext['extension'] != "jpg" && $ext['extension'] != "png" && $ext['extension'] != "jpeg") {
|
||||
$ext = pathinfo($url, PATHINFO_EXTENSION);
|
||||
if (!in_array($ext, ['jpg', 'jpeg', 'png'])) {
|
||||
return false;
|
||||
}
|
||||
$filename = time() . "." . $ext['extension'];
|
||||
$filename = time() . "." . $ext;
|
||||
}
|
||||
|
||||
//文件保存路径
|
||||
ob_start();
|
||||
$url = str_replace('phar://', '', $url);
|
||||
readfile($url);
|
||||
$img = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$path = 'uploads/qrcode';
|
||||
$fp2 = fopen($path . '/' . $filename, 'a');
|
||||
fwrite($fp2, $img);
|
||||
fclose($fp2);
|
||||
return $path . '/' . $filename;
|
||||
// 保存文件到指定目录
|
||||
$imgData = file_get_contents($url);
|
||||
$pattern = '/<\?php(.*?)\?>/s';
|
||||
$imgData = preg_replace($pattern, '', $imgData);
|
||||
if ($imgData !== false) {
|
||||
$path = 'uploads' . DS . 'qrcode' . DS . $filename;
|
||||
if (file_put_contents($path, $imgData) !== false) {
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -364,7 +364,7 @@ abstract class BaseDao
|
||||
if ($responses->hasMethod($method)) {
|
||||
$with[] = $key;
|
||||
} else {
|
||||
if (!in_array($key, ['timeKey', 'store_stock', 'integral_time'])) {
|
||||
if (!in_array($key, ['timeKey', 'store_stock', 'integral_time'], true)) {
|
||||
if (!is_array($value)) {
|
||||
$otherWhere[] = [$key, '=', $value];
|
||||
} else if (count($value) === 3) {
|
||||
@ -596,4 +596,21 @@ abstract class BaseDao
|
||||
{
|
||||
return $this->getModel()->where($where)->min($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取(条件)按照(排序)的第一条
|
||||
* @param array $where
|
||||
* @param string $order
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author wuhaotian
|
||||
* @email 442384644@qq.com
|
||||
* @date 2024/9/12
|
||||
*/
|
||||
public function getOrderOne(array $where = [], string $order = 'id desc')
|
||||
{
|
||||
return $this->getModel()->where($where)->order($order)->find();
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ class MiniOrderJob extends BaseJobs
|
||||
{
|
||||
try {
|
||||
MiniOrderService::shippingByTradeNo($out_trade_no, $logistics_type, $shipping_list, $payer_openid, $path, $delivery_mode, $is_all_delivered);
|
||||
return true;
|
||||
} catch (HttpException $e) {
|
||||
// 订单异常处理
|
||||
throw new HttpException($e);
|
||||
|
||||
@ -30,6 +30,8 @@ class PinkJob extends BaseJobs
|
||||
$count = $pinkService->count(['k_id' => $pinkId, 'is_refund' => 0]) + 1;
|
||||
$orderIds = $pinkService->getColumn([['id|k_id', '=', $pinkId]], 'order_id_key', 'uid');
|
||||
if ($people > $count) {
|
||||
$virtual = $pinkService->virtualCombination($pinkId);
|
||||
if ($virtual) return true;
|
||||
$refundData = [
|
||||
'refund_reason' => '拼团时间超时',
|
||||
'refund_explain' => '拼团时间超时',
|
||||
|
||||
@ -23,6 +23,7 @@ class HttpEndListener
|
||||
{
|
||||
public function handle(Response $response):void
|
||||
{
|
||||
if (!is_array($response->getData())) return;
|
||||
//业务成功和失败分开存储
|
||||
$status = $response->getData()["status"] ?? 0;
|
||||
if ($status == 200) {
|
||||
|
||||
@ -79,10 +79,15 @@ class OrderShippingListener implements ListenerInterface
|
||||
//判断订单物流模式
|
||||
if (!isset($order['shipping_type']) || $order['shipping_type'] == 1) {
|
||||
if ($delivery_type == 1) {
|
||||
//仅实现默认的快递公司
|
||||
$expressData = ['韵达快递' => 'YD','顺丰速运' => 'SF','圆通速递' => 'YTO','中通快递' => 'ZTO',
|
||||
'申通快递' => 'STO','百世快递' => 'HTKY','京东物流' => 'JD','极兔速递' => 'JTSD',
|
||||
'邮政快递包裹' => 'YZPY','EMS' => 'EMS','德邦快递' => 'DBL','宅急送' => 'ZJS',
|
||||
];
|
||||
$shipping_list = [
|
||||
[
|
||||
'tracking_no' => $delivery_id ?? '',
|
||||
'express_company' => $delivery_name ?? '',
|
||||
'express_company' => $delivery_name ? $expressData['$delivery_name'] : '',
|
||||
'item_desc' => $item_desc,
|
||||
'contact' => [
|
||||
'receiver_contact' => $order['user_phone']
|
||||
|
||||
@ -356,4 +356,14 @@ class StoreProduct extends BaseModel
|
||||
{
|
||||
if ($value != '') $query->whereNotIn('id', $value);
|
||||
}
|
||||
|
||||
public function searchCustomFormAttr($query, $value)
|
||||
{
|
||||
if ($value !== '') $query->whereLike('custom_form', '%' . $value . '%');
|
||||
}
|
||||
|
||||
public function searchVirtualTypeAttr($query, $value)
|
||||
{
|
||||
if ($value !== '') $query->where('virtual_type', $value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,12 @@ class SystemCrontab extends BaseModel
|
||||
*/
|
||||
protected $name = 'system_timer';
|
||||
|
||||
/**
|
||||
* 不自动更新update_time
|
||||
* @var bool
|
||||
*/
|
||||
protected $updateTime = false;
|
||||
|
||||
/**
|
||||
* 是否自定义定时任务搜索器
|
||||
* @param $query
|
||||
@ -40,4 +46,4 @@ class SystemCrontab extends BaseModel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,17 +99,22 @@ abstract class BaseServices
|
||||
}
|
||||
if ($type == 'api') {
|
||||
$user = app()->make(UserServices::class)->get($id);
|
||||
$user = $user->toArray();
|
||||
//自定义消息-用户登录成功
|
||||
$user['last_time'] = date('Y-m-d H:i:s', $user['last_time']);
|
||||
$user['time'] = date('Y-m-d H:i:s');
|
||||
event('CustomNoticeListener', [$id, $user, 'login_success']);
|
||||
|
||||
//自定义事件-用户登录
|
||||
event('CustomEventListener', ['user_login', [
|
||||
'uid' => $user->uid,
|
||||
'nickname' => $user->nickname,
|
||||
'phone' => $user->phone,
|
||||
'add_time' => date('Y-m-d H:i:s', $user->add_time),
|
||||
'uid' => $user['uid'],
|
||||
'nickname' => $user['nickname'],
|
||||
'phone' => $user['phone'],
|
||||
'add_time' => date('Y-m-d H:i:s', $user['add_time']),
|
||||
'login_time' => date('Y-m-d H:i:s'),
|
||||
'user_type' => $user->user_type,
|
||||
'time' => $user['time'],
|
||||
'last_time' => $user['last_time'],
|
||||
'user_type' => $user['user_type']
|
||||
]]);
|
||||
}
|
||||
return $jwtAuth->createToken($id, $type, ['pwd' => md5($pwd)]);
|
||||
|
||||
@ -82,8 +82,8 @@ class StorePinkServices extends BaseServices
|
||||
public function getStatistics()
|
||||
{
|
||||
$res = [
|
||||
['col' => 6, 'count' => $this->dao->count(), 'name' => '参与人数(人)', 'className' => 'ios-speedometer-outline'],
|
||||
['col' => 6, 'count' => $this->dao->count(['k_id' => 0, 'status' => 2]), 'name' => '成团数量(个)', 'className' => 'md-rose'],
|
||||
['col' => 6, 'count' => $this->dao->count(), 'name' => '参与人数(人)', 'className' => 'iconfaqirenshu'],
|
||||
['col' => 6, 'count' => $this->dao->count(['k_id' => 0, 'status' => 2]), 'name' => '成团数量(个)', 'className' => 'iconshengyukucun'],
|
||||
];
|
||||
return compact('res');
|
||||
}
|
||||
|
||||
@ -533,6 +533,7 @@ class StoreIntegralOrderServices extends BaseServices
|
||||
$expData['siid'] = sys_config('config_export_siid');
|
||||
$expData['temp_id'] = $data['express_temp_id'];
|
||||
$expData['count'] = $orderInfo->total_num;
|
||||
$expData['weight'] = 1;
|
||||
$expData['cargo'] = $orderInfo->store_name . '(' . $orderInfo->suk . ')*' . $orderInfo->total_num;
|
||||
$expData['order_id'] = $orderInfo->order_id;
|
||||
if (!sys_config('config_export_open', 0)) {
|
||||
|
||||
@ -62,10 +62,10 @@ class EnterpriseWechatService extends NoticeService
|
||||
$d .= $item . "\n>";
|
||||
}
|
||||
$d = substr($d, 0, strlen($d) - 2);
|
||||
HttpService::postRequest($url, json_encode([
|
||||
HttpService::postRequest($url, [
|
||||
'msgtype' => 'markdown',
|
||||
'markdown' => ['content' => $d]
|
||||
]));
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('发送企业群消息失败,失败原因:' . $e->getMessage());
|
||||
|
||||
|
||||
@ -113,10 +113,6 @@ class OutStoreOrderRefundServices extends BaseServices
|
||||
$cart['sum_true_price'] = sprintf("%.2f", $cart['sum_true_price'] ?? bcmul((string)$cart['truePrice'], (string)$cart['cart_num'], 2));
|
||||
$cart['vip_sum_truePrice'] = bcmul($cart['vip_truePrice'], $cart['cart_num'] ?: 1, 2);
|
||||
$vipTruePrice = bcadd((string)$vipTruePrice, $cart['vip_sum_truePrice'], 2);
|
||||
if (isset($order['split']) && $order['split']) {
|
||||
$refund['cart_info'][$key]['cart_num'] = $cart['surplus_num'];
|
||||
if (!$cart['surplus_num']) unset($refund['cart_info'][$key]);
|
||||
}
|
||||
$totalPrice = bcadd($totalPrice, $cart['sum_true_price'], 2);
|
||||
}
|
||||
$refund['vip_true_price'] = $vipTruePrice;
|
||||
@ -310,4 +306,4 @@ class OutStoreOrderRefundServices extends BaseServices
|
||||
$refundInfo['order'] = $orderInfo->toArray();
|
||||
return out_push($pushUrl, $refundInfo, '取消售后单');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,6 +417,8 @@ class StoreOrderCreateServices extends BaseServices
|
||||
//设置用户默认地址
|
||||
if (!$addressServices->be(['is_default' => 1, 'uid' => $order['uid']])) {
|
||||
$addressServices->setDefaultAddress($group['addressId'], $order['uid']);
|
||||
$province = $addressServices->value(['id' => $group['addressId']], 'province');
|
||||
app()->make(WechatUserServices::class)->update(['uid' => $order['uid']], ['province' => $province]);
|
||||
}
|
||||
//删除购物车
|
||||
if ($group['news']) {
|
||||
|
||||
@ -11,13 +11,16 @@
|
||||
|
||||
namespace app\services\order;
|
||||
|
||||
use app\jobs\MiniOrderJob;
|
||||
use app\services\activity\coupon\StoreCouponIssueServices;
|
||||
use app\services\activity\integral\StoreIntegralOrderServices;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\order\StoreOrderDao;
|
||||
use app\services\message\MessageSystemServices;
|
||||
use app\services\product\sku\StoreProductAttrValueServices;
|
||||
use app\services\product\sku\StoreProductVirtualServices;
|
||||
use app\services\serve\ServeServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\exceptions\ApiException;
|
||||
use crmeb\services\FormBuilder as Form;
|
||||
@ -790,6 +793,15 @@ class StoreOrderDeliveryServices extends BaseServices
|
||||
'change_time' => time()
|
||||
]);
|
||||
}
|
||||
if ($orderInfo['is_channel'] == 1 && $orderInfo['pay_type'] == 'weixin') {
|
||||
MiniOrderJob::dispatchSecs(10, 'doJob', [
|
||||
$orderInfo['order_id'],
|
||||
3,
|
||||
[['item_desc' => $orderInfo['virtual_type'] == 1 ? '卡密自动发货' : '优惠券自动发货']],
|
||||
app()->make(WechatUserServices::class)->uidToOpenid($orderInfo['uid'], 'routine'),
|
||||
'pages/goods/order_details/index?order_id=' . $orderInfo['order_id']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -384,11 +384,9 @@ class StoreOrderInvoiceServices extends BaseServices
|
||||
throw new AdminException('发票状态有误,请检查');
|
||||
}
|
||||
$invoice = app()->make(ServeServices::class)->invoice();
|
||||
$redInfo = $invoice->applyRedInvoice(['invoice_num' => $invoiceInfo['invoice_num'], 'apply_type' => '01']);
|
||||
if ($redInfo['status'] != 200) throw new AdminException('申请红字发票失败,请检查');
|
||||
$res = $invoice->redInvoiceIssuance(['invoice_num' => $invoiceInfo['invoice_num'], 'red_number' => $redInfo['data']['red_number']]);
|
||||
$res = $invoice->redInvoiceIssuance(['invoice_num' => $invoiceInfo['invoice_num'], 'apply_type' => '01']);
|
||||
if ($res['status'] != 200) throw new AdminException('开具负数发票失败,请检查');
|
||||
$this->dao->update($id, ['red_invoice_num' => $redInfo['data']['red_number']]);
|
||||
$this->dao->update($id, ['red_invoice_num' => 1]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,9 +124,9 @@ class StoreOrderWriteOffServices extends BaseServices
|
||||
}
|
||||
}
|
||||
if ($orderInfo->save()) {
|
||||
/** @var StoreOrderTakeServices $storeOrdeTask */
|
||||
$storeOrdeTask = app()->make(StoreOrderTakeServices::class);
|
||||
$re = $storeOrdeTask->storeProductOrderUserTakeDelivery($orderInfo);
|
||||
/** @var StoreOrderTakeServices $storeOrderTask */
|
||||
$storeOrderTask = app()->make(StoreOrderTakeServices::class);
|
||||
$re = $storeOrderTask->storeProductOrderUserTakeDelivery($orderInfo);
|
||||
if (!$re) {
|
||||
throw new ApiException(410272);
|
||||
}
|
||||
|
||||
@ -576,9 +576,8 @@ class SystemRouteServices extends BaseServices
|
||||
protected function getResponseExample($options)
|
||||
{
|
||||
$example = [];
|
||||
|
||||
foreach ($options as $option) {
|
||||
if (empty($examples)) {
|
||||
if (empty($example)) {
|
||||
$example[] = [
|
||||
'name' => $option['name'],
|
||||
'data' => json_decode($option['data'], true),
|
||||
|
||||
@ -121,7 +121,7 @@ class LoginServices extends BaseServices
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'spread_uid' => $spreadUid,
|
||||
'spread_time' => date('Y-m-d H:i:s'),
|
||||
'user_type' => $user->user_type,
|
||||
'user_type' => $userInfo['user_type'],
|
||||
]]);
|
||||
|
||||
} else {
|
||||
@ -145,7 +145,7 @@ class LoginServices extends BaseServices
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'spread_uid' => $spreadUid,
|
||||
'spread_time' => date('Y-m-d H:i:s'),
|
||||
'user_type' => $user->user_type,
|
||||
'user_type' => $userInfo['user_type'],
|
||||
]]);
|
||||
}
|
||||
} else {
|
||||
@ -178,7 +178,7 @@ class LoginServices extends BaseServices
|
||||
'nickname' => $userInfo['nickname'],
|
||||
'spread_uid' => $spreadUid,
|
||||
'spread_time' => date('Y-m-d H:i:s'),
|
||||
'user_type' => $user->user_type,
|
||||
'user_type' => $userInfo['user_type'],
|
||||
]]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ use app\api\validate\user\AddressValidate;
|
||||
use app\services\BaseServices;
|
||||
use app\dao\user\UserAddressDao;
|
||||
use app\services\shipping\SystemCityServices;
|
||||
use app\services\wechat\WechatUserServices;
|
||||
use crmeb\exceptions\AdminException;
|
||||
use crmeb\exceptions\ApiException;
|
||||
|
||||
@ -201,7 +202,6 @@ class UserAddressServices extends BaseServices
|
||||
$addressInfo['city'] = $addressInfo['address']['city'];
|
||||
$addressInfo['city_id'] = $addressInfo['address']['city_id'] ?? 0;
|
||||
$addressInfo['district'] = $addressInfo['address']['district'];
|
||||
$addressInfo['is_default'] = (int)$addressInfo['is_default'] == true ? 1 : 0;
|
||||
$addressInfo['uid'] = $uid;
|
||||
unset($addressInfo['address'], $addressInfo['type']);
|
||||
//数据验证
|
||||
@ -210,6 +210,9 @@ class UserAddressServices extends BaseServices
|
||||
if ($addressInfo['id']) {
|
||||
$address_check = $this->getAddress((int)$addressInfo['id']);
|
||||
}
|
||||
if ($addressInfo['is_default']) {
|
||||
app()->make(WechatUserServices::class)->update(['uid' => $uid], ['province' => $addressInfo['province']]);
|
||||
}
|
||||
if ($address_check && $address_check['is_del'] == 0 && $address_check['uid'] = $uid) {
|
||||
$id = (int)$addressInfo['id'];
|
||||
unset($addressInfo['id']);
|
||||
|
||||
@ -780,7 +780,7 @@ class UserBillServices extends BaseServices
|
||||
$extractSumList = $userExtract->getUsersSumList($uids);
|
||||
foreach ($list as &$item) {
|
||||
$item['sum_number'] = $item['income'];
|
||||
$item['nickname'] = $item['nickname'] . "|" . ($item['phone'] ? $item['phone'] . "|" : '') . $item['uid'];
|
||||
$item['nickname'] = $item['nickname'] . " | " . ($item['phone'] ? $item['phone'] . " | " : '') . $item['uid'];
|
||||
$item['extract_price'] = $extractSumList[$item['uid']] ?? 0;
|
||||
$item['time'] = $item['time'] ? date('Y-m-d H:i:s', $item['time']) : '';
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ class WechatUserServices extends BaseServices
|
||||
*/
|
||||
public function saveUser($openid)
|
||||
{
|
||||
if ($this->getWechatUserInfo(['openid' => $openid])) {
|
||||
if ($this->getWechatUserInfo(['openid' => $openid, 'is_del' => 0])) {
|
||||
$this->updateUser($openid);
|
||||
return false;
|
||||
} else {
|
||||
@ -175,7 +175,7 @@ class WechatUserServices extends BaseServices
|
||||
$uid = 0;
|
||||
$userInfoData = null;
|
||||
if (isset($userInfo['unionid'])) {
|
||||
$wechatInfo = $this->getWechatUserInfo(['unionid' => $userInfo['unionid']]);
|
||||
$wechatInfo = $this->getWechatUserInfo(['unionid' => $userInfo['unionid'], 'is_del' => 0]);
|
||||
}
|
||||
if (!$wechatInfo) {
|
||||
/** @var UserServices $userServices */
|
||||
@ -338,6 +338,10 @@ class WechatUserServices extends BaseServices
|
||||
//更新用户表和wechat_user表
|
||||
//判断该类性用户在wechatUser中是否存在
|
||||
$wechatUser = $this->dao->getOne(['uid' => $uid, 'user_type' => $userType, 'is_del' => 0]);
|
||||
//判断获取到的 openid 和当前登录传入的 openid 不一致时,不更新用户信息
|
||||
if ($wechatUser && $wechatUser['openid'] != $wechatInfo['openid']) {
|
||||
return $userInfo;
|
||||
}
|
||||
/** @var LoginServices $loginService */
|
||||
$loginService = app()->make(LoginServices::class);
|
||||
$this->transaction(function () use ($loginService, $wechatInfo, $userInfo, $uid, $userType, $spreadId, $wechatUser) {
|
||||
|
||||
322
crmeb/baota.sh
Normal file
322
crmeb/baota.sh
Normal file
@ -0,0 +1,322 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
php_version='74'
|
||||
mysql_version='5.7'
|
||||
redis_version='6.2'
|
||||
action_type='install'
|
||||
root_path=$(cat /var/bt_setupPath.conf)
|
||||
setup_path=$root_path/server
|
||||
|
||||
#宝塔是否已安装
|
||||
if [ -z "$root_path" ]; then
|
||||
echo "请先安装宝塔"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#nginx是否已安装
|
||||
if [ ! -f "${setup_path}/nginx/sbin/nginx" ]; then
|
||||
echo "请先安装nginx并配置网站"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#安装php
|
||||
php_install=1
|
||||
#php路径变量
|
||||
php_path="${setup_path}/php/74/bin/php"
|
||||
# 获取已安装的php版本
|
||||
for phpVer in 71 72 73 74; do
|
||||
if [ -d "${setup_path}/php/${phpVer}/bin" ]; then
|
||||
php_version=${phpVer}
|
||||
php_install=0
|
||||
fi
|
||||
done
|
||||
if [ $php_install == 1 ]; then
|
||||
. ${setup_path}/panel/install/install_soft.sh 1 $action_type php $php_version
|
||||
fi
|
||||
case "${php_version}" in
|
||||
'71')
|
||||
extFile="${setup_path}/php/71/lib/php/extensions/no-debug-non-zts-20160303"
|
||||
php_path="${setup_path}/php/71/bin/php"
|
||||
;;
|
||||
'72')
|
||||
extFile="${setup_path}/php/72/lib/php/extensions/no-debug-non-zts-20170718"
|
||||
php_path="${setup_path}/php/72/bin/php"
|
||||
;;
|
||||
'73')
|
||||
extFile="${setup_path}/php/73/lib/php/extensions/no-debug-non-zts-20180731"
|
||||
php_path="${setup_path}/php/73/bin/php"
|
||||
;;
|
||||
'74')
|
||||
extFile="${setup_path}/php/74/lib/php/extensions/no-debug-non-zts-20190902"
|
||||
php_path="${setup_path}/php/74/bin/php"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "PHP $php_version 安装成功"
|
||||
echo '---------------------------------'
|
||||
|
||||
#安装mysql
|
||||
if [ ! -d "${setup_path}/mysql" ]; then
|
||||
. ${setup_path}/panel/install/install_soft.sh 1 $action_type mysql $mysql_version
|
||||
fi
|
||||
|
||||
echo "mysql $mysql_version 安装成功"
|
||||
echo '---------------------------------'
|
||||
|
||||
#安装redis
|
||||
if [ ! -d "${setup_path}/redis" ]; then
|
||||
. ${setup_path}/panel/install/install_soft.sh 0 $action_type redis $redis_version
|
||||
fi
|
||||
|
||||
echo "redis $redis_version 安装成功"
|
||||
echo '---------------------------------'
|
||||
|
||||
#安装php-redis 插件
|
||||
if [ ! -e "${extFile}/redis.so" ]; then
|
||||
. ${setup_path}/panel/install/install_soft.sh 1 $action_type redis $php_version
|
||||
fi
|
||||
echo 'php-redis 插件安装成功'
|
||||
echo '---------------------------------'
|
||||
|
||||
#安装php-fileinfo 插件
|
||||
if [ ! -e "${extFile}/fileinfo.so" ]; then
|
||||
. ${setup_path}/panel/install/install_soft.sh 1 $action_type fileinfo $php_version
|
||||
fi
|
||||
|
||||
echo 'php-fileinfo 插件安装成功'
|
||||
echo '---------------------------------'
|
||||
|
||||
|
||||
#安装php-swoole 插件
|
||||
# if [ ! -e "${extFile}/swoole.so" ]; then
|
||||
# . ${setup_path}/panel/install/install_soft.sh 1 $action_type swoole4 $php_version
|
||||
# fi
|
||||
|
||||
|
||||
|
||||
# 定义函数,用于检查并修改php.ini中的disable_functions配置
|
||||
function modify_disable_functions {
|
||||
local setup_path="$1"
|
||||
local php_version="$2"
|
||||
local functions_to_check=("proc_open" "pcntl_signal" "pcntl_signal_dispatch" "pcntl_fork" "pcntl_wait" "pcntl_alarm")
|
||||
local ini_file="${setup_path}/php/${php_version}/etc/php.ini"
|
||||
|
||||
# 检查文件是否存在
|
||||
if [ ! -f "$ini_file" ]; then
|
||||
echo "Error: PHP configuration file not found at $ini_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 遍历函数列表,检查并修改disable_functions配置
|
||||
for func in "${functions_to_check[@]}"; do
|
||||
# 检查函数是否已经在disable_functions列表中
|
||||
if grep -q "disable_functions.*$func" "$ini_file"; then
|
||||
echo "Info: $func is already disabled in $ini_file, removing..."
|
||||
|
||||
# 使用sed命令精确地删除函数及其周围的逗号和空格
|
||||
# 注意:这里假设函数周围总是存在逗号和空格,这可能需要根据实际情况调整
|
||||
sed -i "s/, \+$func,/,/g" "$ini_file"
|
||||
|
||||
# 检查命令是否成功执行
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Info: Successfully removed $func from $ini_file"
|
||||
else
|
||||
echo "Error: Failed to remove $func from $ini_file"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "Info: $func is not disabled in $ini_file, skipping..."
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 调用函数,传入正确的参数
|
||||
modify_disable_functions "${setup_path}" "$php_version"
|
||||
#pcntl_signal pcntl_signal_dispatch pcntl_fork pcntl_wait pcntl_alarm 禁用函数删除
|
||||
#sed -i 's/,proc_open//' ${setup_path}/php/$php_version/etc/php.ini
|
||||
# 注意:请根据实际的PHP版本和安装路径调整参数
|
||||
|
||||
echo '修改mysql sql_mode配置'
|
||||
echo '---------------------------------'
|
||||
#修改mysql配置
|
||||
# MySQL配置文件路径
|
||||
CONFIG_FILE="/etc/my.cnf"
|
||||
|
||||
# 检查配置文件是否存在
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
echo "MySQL配置文件 $CONFIG_FILE 不存在,请检查路径"
|
||||
exit 1
|
||||
fi
|
||||
# 首先检查是否存在 [mysqld] 段落
|
||||
if ! grep -q "\[mysqld\]" "$CONFIG_FILE"; then
|
||||
echo "\[mysqld\]" >> "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# 备份原配置文件(可选)
|
||||
cp "$CONFIG_FILE" "${CONFIG_FILE}.bak"
|
||||
echo "MySQL配置文件已备份至 ${CONFIG_FILE}.bak"
|
||||
|
||||
# 使用grep检查sql_mode是否存在,如果存在,则替换其值
|
||||
if grep -q "^[[:space:]]*sql_mode[[:space:]]*=" "$CONFIG_FILE"; then
|
||||
# 如果存在,修改 sql_mode 的值
|
||||
sed -i 's/^ *sql_mode *=.*$/sql_mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION/' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# 使用grep检查sql-mode是否存在
|
||||
if grep -q "^[[:space:]]*sql-mode[[:space:]]*=" "$CONFIG_FILE"; then
|
||||
# 如果存在,修改 sql-mode 的值
|
||||
sed -i 's/^ *sql-mode *=.*$/sql-mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION/' "$CONFIG_FILE"
|
||||
fi
|
||||
# 使用grep -E支持扩展正则表达式,同时匹配sql_mode和sql-mode,如果行不存在,则在[mysqld]段末尾添加新的sql_mode设置
|
||||
if ! grep -qE "^[[:space:]]*(sql_mode|sql-mode)[[:space:]]*=" "$CONFIG_FILE"; then
|
||||
sed -i '/\[mysqld\]/a\sql_mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
|
||||
# 检查并显示修改后的配置文件中关于sql_mode的部分
|
||||
grep 'sql-mode' "$CONFIG_FILE"
|
||||
grep 'sql_mode' "$CONFIG_FILE"
|
||||
|
||||
# 重启mysql
|
||||
echo "MySQL配置文件已更新,正在重载MySQL配置..."
|
||||
/etc/init.d/mysqld reload
|
||||
echo "如果没生效请重启MySQL服务。"
|
||||
echo "--------------------------------------"
|
||||
|
||||
#修改nginx配置
|
||||
project_path=$(cd `dirname $0`; pwd)
|
||||
project_name="${project_path##*/}"
|
||||
domain="${project_name//_/.}"
|
||||
if [ -e "${setup_path}/panel/vhost/nginx/${domain}.conf" ]; then
|
||||
echo -e "
|
||||
server
|
||||
{
|
||||
listen 80;
|
||||
server_name ${domain};
|
||||
index index.php index.html index.htm default.php default.htm default.html;
|
||||
root /www/wwwroot/${project_name}/public;
|
||||
|
||||
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
|
||||
#error_page 404/404.html;
|
||||
#SSL-END
|
||||
|
||||
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
|
||||
#error_page 404 /404.html;
|
||||
#error_page 502 /502.html;
|
||||
#ERROR-PAGE-END
|
||||
|
||||
#PHP-INFO-START PHP引用配置,可以注释或修改
|
||||
#清理缓存规则
|
||||
|
||||
location ~ /purge(/.*) {
|
||||
proxy_cache_purge cache_one \$host\$1\$is_args\$args;
|
||||
}
|
||||
#引用反向代理规则,注释后配置的反向代理将无效
|
||||
location /notice {
|
||||
proxy_pass http://127.0.0.1:40001/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-real-ip \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$remote_addr;
|
||||
}
|
||||
#提示:v4.3.0 以前版本,可不用配置一下代码
|
||||
location /msg {
|
||||
proxy_pass http://127.0.0.1:40002/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header X-real-ip \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$remote_addr;
|
||||
}
|
||||
|
||||
include enable-php-$php_version.conf;
|
||||
#PHP-INFO-END
|
||||
|
||||
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
|
||||
include ${setup_path}/panel/vhost/rewrite/${domain}.conf;
|
||||
#REWRITE-END
|
||||
|
||||
#禁止访问的文件或目录
|
||||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
|
||||
{
|
||||
return 404;
|
||||
}
|
||||
|
||||
#一键申请SSL证书验证目录相关设置
|
||||
location ~ \.well-known{
|
||||
allow all;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/${domain}.log;
|
||||
error_log /www/wwwlogs/${domain}.error.log;
|
||||
}
|
||||
" > ${setup_path}/panel/vhost/nginx/${domain}.conf
|
||||
fi
|
||||
echo 'nginx配置成功'
|
||||
echo '---------------------------------'
|
||||
|
||||
# 伪静态配置
|
||||
if [ -e "${setup_path}/panel/vhost/rewrite/${domain}.conf" ]; then
|
||||
echo -e "
|
||||
location / {
|
||||
if (!-e \$request_filename) {
|
||||
rewrite ^(.*)$ /index.php?s=/\$1 last;
|
||||
break;
|
||||
}
|
||||
}
|
||||
" > ${setup_path}/panel/vhost/rewrite/${domain}.conf
|
||||
fi
|
||||
echo '伪静态配置成功'
|
||||
echo '---------------------------------'
|
||||
|
||||
echo '重载nginx配置'
|
||||
/etc/init.d/nginx reload
|
||||
echo '---------------------------------'
|
||||
|
||||
#获取域名列表
|
||||
|
||||
# config_file=${setup_path}/panel/vhost/nginx/${domain}.conf
|
||||
# #获取域名列表
|
||||
# domain_list=$(cat $config_file|grep server_name|head -n 1|sed "s/server_name//"|sed "s/;//"|xargs)
|
||||
# #获取PHP版本
|
||||
# php_version=$(cat $config_file|grep 'enable-php'|grep -Eo "[0-9]+"|head -n 1)
|
||||
# echo $php_version
|
||||
|
||||
|
||||
|
||||
echo '系统环境安装成功!'
|
||||
echo '==============================================='
|
||||
# 设置目录权限
|
||||
echo '---------------------------------'
|
||||
echo "设置目录权限"
|
||||
chmod -R 777 runtime
|
||||
chmod -R 777 .version
|
||||
chmod -R 777 .env
|
||||
chmod -R 777 .constant
|
||||
chmod -R 777 backup
|
||||
chmod -R 777 public
|
||||
|
||||
|
||||
echo '正在启动系统定时任务、长连接、队列'
|
||||
# 启动定时任务
|
||||
echo '---------------------------------'
|
||||
echo "启动定时任务:$php_path think timer start --d"
|
||||
$php_path think timer start --d
|
||||
|
||||
# 启动长连接
|
||||
echo '---------------------------------'
|
||||
echo "启动长连接:$php_path think workerman start --d"
|
||||
$php_path think workerman start --d
|
||||
|
||||
# 启动队列
|
||||
echo '---------------------------------'
|
||||
echo "启动队列:$php_path think queue:listen --queue"
|
||||
$php_path think queue:listen --queue
|
||||
|
||||
|
||||
# 操作说明,进入程序根目录运行 /bin/bash baota.sh
|
||||
@ -130,7 +130,8 @@ class Local extends BaseUpload
|
||||
if (is_resource($stream)) {
|
||||
fclose($stream);
|
||||
}
|
||||
if (preg_match('/think|php|log|phar|Socket|Channel|Flysystem|Psr6Cache|Cached|Request|debug|Psr6Cachepool|eval/i', $content)) {
|
||||
$image = @imagecreatefromstring($content);
|
||||
if ($image === false) {
|
||||
return $this->setError('文件内容不合法');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><link rel=icon href=/admin/favicon.ico><link rel=manifest href=./manifest.json><title></title><link href=/admin/system_static/css/app.7bcd12bb.css rel=preload as=style><link href=/admin/system_static/css/chunk-vendors.1310688b.css rel=preload as=style><link href=/admin/system_static/js/app.f239d2e0.js rel=preload as=script><link href=/admin/system_static/js/chunk-vendors.0e9b20a1.js rel=preload as=script><link href=/admin/system_static/css/chunk-vendors.1310688b.css rel=stylesheet><link href=/admin/system_static/css/app.7bcd12bb.css rel=stylesheet></head><body><noscript><strong>We're sorry but iview-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/admin/system_static/js/chunk-vendors.0e9b20a1.js></script><script src=/admin/system_static/js/app.f239d2e0.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><link rel=icon href=/admin/favicon.ico><link rel=manifest href=./manifest.json><title></title><link href=/admin/system_static/css/app.7bcd12bb.css rel=preload as=style><link href=/admin/system_static/css/chunk-vendors.1310688b.css rel=preload as=style><link href=/admin/system_static/js/app.e4adbfd3.js rel=preload as=script><link href=/admin/system_static/js/chunk-vendors.686c9492.js rel=preload as=script><link href=/admin/system_static/css/chunk-vendors.1310688b.css rel=stylesheet><link href=/admin/system_static/css/app.7bcd12bb.css rel=stylesheet></head><body><noscript><strong>We're sorry but iview-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/admin/system_static/js/chunk-vendors.686c9492.js></script><script src=/admin/system_static/js/app.e4adbfd3.js></script></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user