master
wangxinglong 2022-02-28 18:04:28 +08:00
parent 6c80493328
commit 9482c9059d
23 changed files with 1108 additions and 1904 deletions

View File

@ -21,6 +21,7 @@ class Index extends Base
public function index() public function index()
{ {
return $this->redirect("/manager");
try { try {
//banner //banner
$this->data['slide'] = Slide::findList([["position","=",SlidePosition::home_position]])['list']; $this->data['slide'] = Slide::findList([["position","=",SlidePosition::home_position]])['list'];

View File

@ -1,30 +1,14 @@
<?php <?php
namespace app\controller\manager; namespace app\controller\manager;
use app\exception\RepositoryException; use app\exception\RepositoryException;
use app\model\AccountDataLog;
use app\model\AccountDataOperationLog;
use app\model\AccountLevel;
use app\model\AccountOperateLog;
use app\model\AccountTagPivot;
use app\model\CategoryConfig as CategoryConfigModel;
use app\model\CustomerReceive;
use app\model\AccountTag;
use app\model\Account as AccountModel; use app\model\Account as AccountModel;
use app\model\Order;
use app\model\Staff;
use app\model\Activity;
use app\repository\AccountRepository; use app\repository\AccountRepository;
use app\repository\OrderRepository;
use app\service\Math;
use Exception; use Exception;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException; use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Log;
use think\response\Json; use think\response\Json;
use think\response\View; use think\response\View;
@ -36,7 +20,7 @@ use think\response\View;
*/ */
class Account extends Base class Account extends Base
{ {
protected $noNeedLogin = ['getStaffList', 'getAccountList']; protected $noNeedLogin = [];
/** /**
* 详情 * 详情
@ -50,39 +34,7 @@ class Account extends Base
public function detail(): View public function detail(): View
{ {
$id = input('id/d', 0); $id = input('id/d', 0);
$item = AccountRepository::getInstance()->findById($id, [], function ($q) { $item = AccountRepository::getInstance()->findById($id);
return $q->with(['serviceList']);
});
$statusList = [
Order::STATUS_SHIPPED, Order::STATUS_PAID, Order::STATUS_COMPLETED
];
$consumption = OrderRepository::getInstance()->userOrderList($id, [], 1, 0, $statusList);
$orderNum = 0;
$orderScoreNum = 0;
$totalPrice = 0;
$totalScore = 0;
$totalCoin = 0;
$consumption->each(function ($item) use (&$totalPrice, &$totalScore, &$totalCoin, &$orderScoreNum, &$orderNum) {
if ($item->is_score == AccountModel::COMMON_ON) {
$orderScoreNum += 1;
} else {
$orderNum += 1;
}
$totalPrice += $item->price;
$totalScore += $item->score;
$totalCoin += $item->coin;
});
$item['total_price'] = Math::fen2Yuan($totalPrice);
$item['total_score'] = $totalScore;
$item['total_coin'] = $totalCoin;
$item['order_num'] = $orderNum;
$item['order_score_num'] = $orderScoreNum;
$item['order_newest'] = $consumption->toArray()[0] ?? [];
$item['customer_service'] = $item->serviceList->name ?? '';
$item['source_text'] = AccountRepository::getInstance()->getSourceDetail($id);
$item['channel_text'] = AccountModel::channelTextList()[$item['channel']] ?? '';
$this->data['item'] = $item; $this->data['item'] = $item;
return $this->view(); return $this->view();
@ -182,30 +134,16 @@ class Account extends Base
$size = input('size/d', 20); $size = input('size/d', 20);
$searchParams = input('searchParams'); $searchParams = input('searchParams');
$search = []; $search = [];
$other = [];
if ($searchParams) { if ($searchParams) {
foreach ($searchParams as $key => $param) { foreach ($searchParams as $key => $param) {
if ($key == 'tag' && !empty($param)) {
$other['tag_id'] = $param;
continue;
}
if ($param || $param == '0') { if ($param || $param == '0') {
$search[] = [$key, 'like', '%'.$param.'%']; $search[] = [$key, 'like', '%'.$param.'%'];
} }
} }
} }
$search[] = ['phone_active', '=', AccountModel::COMMON_ON];
// 后台绑定的账号
$accountId = $this->auth['account_id'] ?? 0;
try { try {
$items = AccountRepository::getInstance()->customerList($search, [], $accountId, $page, $size, function ($q) use ($other) { $items = AccountRepository::getInstance()->getAndHandleAccountList($search, [], $page, $size);
return $q->when(isset($other['tag_id']), function ($query) use ($other) {
$query->leftJoin('account_tag_pivot atp', 'atp.account_id = id')->where('atp.tag_id', $other['tag_id']);
});
});
return $this->json(0, '操作成功', $items); return $this->json(0, '操作成功', $items);
} catch (RepositoryException $e) { } catch (RepositoryException $e) {
return $this->json(4001, $e->getMessage()); return $this->json(4001, $e->getMessage());
@ -214,523 +152,7 @@ class Account extends Base
} }
} }
$this->data['channelList'] = AccountModel::channelTextList();
$this->data['customerList'] = Staff::getCustomerServiceList();
$this->data['tagList'] = AccountTag::getTags();
return $this->view(); return $this->view();
} }
/**
* 分配员工
*
* @return View|Json
* @throws Exception
*/
public function staff()
{
$id = input('id/s', '');
if ($this->request->isPost()) {
$ids = input('ids/s');
$staffId = input('staff_id/d', 0);
if (empty($ids)) {
return $this->json(4001, '请选择要操作的用户');
}
if (!$staffId) {
return $this->json(4001, '请选择分配的员工');
}
$ids = explode(',', $ids);
try {
CustomerReceive::allotServiceByBatch($ids, $staffId);
return $this->json(0, '操作成功');
} catch (RepositoryException $e) {
return $this->json(4001, $e->getMessage());
} catch (Exception $e) {
Log::error('分配指定员工失败'.$e->getMessage());
return $this->json(5001, '分配指定员工失败');
}
}
$staffList = Staff::getCustomerServiceList();
// 分配的是客服分组下所有客服
$this->data['servicerList'] = json_encode($staffList, JSON_UNESCAPED_UNICODE);
$this->data['id'] = $id;
return $this->view();
}
/**
* 分配客户标签
*
* @return View|Json
* @throws Exception
*/
public function tag()
{
$id = input('id/s', '');
if ($this->request->isPost()) {
$ids = input('ids/s');
$tagId = input('tag_id/s');
if (empty($ids)) {
return $this->json(4001, '请选择要操作的用户');
}
if (empty($tagId)) {
return $this->json(4001, '请选择分配的标签');
}
$ids = explode(',', $ids);
$tags = explode(',', $tagId);
Db::startTrans();
try {
// 删除所有人标签
AccountTagPivot::whereIn('account_id', $ids)->delete();
// 新增标签
$insert = [];
foreach ($ids as $id) {
foreach ($tags as $tag) {
$arr = [];
$arr['account_id'] = $id;
$arr['tag_id'] = $tag;
$insert[] = $arr;
}
}
(new AccountTagPivot())->saveAll($insert);
Db::commit();
return $this->json(0, '操作成功');
} catch (RepositoryException $e) {
Db::rollback();
return $this->json(4001, $e->getMessage());
} catch (Exception $e) {
Db::rollback();
Log::error('分配客户标签失败'.$e->getMessage());
return $this->json(5001, '分配客户标签失败');
}
}
$tagList = AccountTag::order('sort', 'desc')->order('id', 'asc')->select()->toArray();
// 分配的是线上客服
$this->data['tagList'] = json_encode($tagList, JSON_UNESCAPED_UNICODE);
$this->data['id'] = $id;
return $this->view();
}
/**
* 分配客户来源
*
* @return View|Json
* @throws Exception
*/
public function source()
{
$id = input('id/s', '');
if ($this->request->isPost()) {
$ids = input('ids/s');
$channel = input('channel/s');
if (empty($ids)) {
return $this->json(4001, '请选择要操作的用户');
}
if (empty($channel)) {
return $this->json(4001, '请选择分配的客户来源');
}
$value = $channel == AccountModel::CHANNEL_MEMBER ? input('type_staff') : input('type_'.$channel);
$ids = explode(',', $ids);
Db::startTrans();
try {
$field = 'id,channel,inviter_account_id,inviter_parent_id,source_code';
$accountList = AccountModel::whereIn('id', $ids)->column($field, 'id');
$update = [];//更新account表
$insert = [];//插入account_operate_log表
switch ($channel) {
case AccountModel::CHANNEL_NORMAL:
// 设为自然流量 清空上级邀请人和上上级邀请人
$update = ['inviter_account_id' => 0, 'inviter_parent_id' => 0, 'channel' => $channel, 'source_code' => null];
break;
case AccountModel::CHANNEL_CUSTOMER:
case AccountModel::CHANNEL_MEMBER:
// 客户分享或员工分享 修改上级邀请人ID
$update = ['inviter_account_id' => $value, 'channel' => $channel, 'source_code' => null];
break;
case AccountModel::CHANNEL_ACTIVITY:
// 活码分享
$update = ['inviter_account_id' => 0, 'source_code' => $value, 'channel' => $channel];
break;
}
$now = date('Y-m-d H:i:s');
$createdBy = $this->auth['user_id'] ?? 0;
foreach ($ids as $id) {
$log = [];
$originalSource = $accountList[$id] ?? [];
switch ($channel) {
case AccountModel::CHANNEL_NORMAL:
$log['description'] = sprintf("从原始来源【channel=%s,inviter_account_id=%s,source_code=%s】变更为新来源【channel=%s,inviter_account_id=%s,source_code=%s】",
$originalSource['channel'] ?? '', $originalSource['inviter_account_id'] ?? 0,
$originalSource['source_code'] ?? '', $channel, 0, null);
break;
case AccountModel::CHANNEL_CUSTOMER:
case AccountModel::CHANNEL_MEMBER:
$log['description'] = sprintf("从原始来源【channel=%s,inviter_account_id=%s,source_code=%s】变更为新来源【channel=%s,inviter_account_id=%s,source_code=%s】",
$originalSource['channel'] ?? '', $originalSource['inviter_account_id'] ?? 0,
$originalSource['source_code'] ?? '', $channel, $value, null);
break;
case AccountModel::CHANNEL_ACTIVITY:
$log['description'] = sprintf("从原始来源【channel=%s,inviter_account_id=%s,source_code=%s】变更为新来源【channel=%s,inviter_account_id=%s,source_code=%s】",
$originalSource['channel'] ?? '', $originalSource['inviter_account_id'] ?? 0,
$originalSource['source_code'] ?? '', $channel, 0, $value);
break;
}
$log['type'] = AccountOperateLog::TYPE_CHANGE_SOURCE;
$log['account_id'] = $id;
$log['created_at'] = $now;
$log['created_by'] = $createdBy;
$insert[] = $log;
}
(new AccountOperateLog())->saveAll($insert);
(new AccountModel())->whereIn('id', $ids)->save($update);
Db::commit();
return $this->json(0, '操作成功');
} catch (RepositoryException $e) {
Db::rollback();
return $this->json(4001, $e->getMessage());
} catch (Exception $e) {
Db::rollback();
Log::error('分配客户标签失败'.$e->getMessage());
return $this->json(5001, '分配客户标签失败');
}
}
// 客服来源
$this->data['channelList'] = AccountModel::channelTextList();
$this->data['id'] = $id;
return $this->view();
}
/**
* 到店设置
*
* @return View|Json
* @throws Exception
*/
public function sign()
{
$id = input('id/s', '');
if ($this->request->isPost()) {
$ids = input('ids/s');
$sign = input('sign/d');
if (empty($ids)) {
return $this->json(4001, '请选择要操作的用户');
}
if (!in_array($sign, [AccountModel::COMMON_ON, AccountModel::COMMON_OFF])) {
return $this->json(4001, '请选择是否到店');
}
$ids = explode(',', $ids);
Db::startTrans();
try {
(new AccountModel())->whereIn('id', $ids)->save(['is_sign' => $sign]);
Db::commit();
return $this->json(0, '操作成功');
} catch (Exception $e) {
Db::rollback();
Log::error('是否到店操作失败'.$e->getMessage());
return $this->json(5001, '是否到店操作失败');
}
}
$this->data['id'] = $id;
return $this->view();
}
/**
* 获取员工列表
*
* @return Json
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException|Exception
*/
public function getStaffList(): Json
{
if ($this->request->isPost()) {
$keyword = input('keyword/s', '');
$type = input('type/s', '');//员工类型标识 如在线客服=customer-online
$page = input('page/d', 1);
$size = input('size/d', 0);
$id = input('id/d', 0);
$relationIds = [];//已选记录
if ($id > 0 && $activity = Activity::findById($id)) {
$relationIds = explode(',', $activity['account_id']);
}
$res = Staff::getStaff($type, $keyword, $page, $size);
if ($res['total'] > 0) {
$res['list'] = $res['list']->toArray();
foreach ($res['list'] as &$item) {
if (count($relationIds) > 0 && in_array($item['id'], $relationIds)) {
$item['selected'] = true;
}
}
}
return $this->json(0, '操作成功', $res);
}
return $this->json(4001, '非法请求');
}
/**
* 获取客户列表
*
* @return Json
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException|Exception
*/
public function getAccountList(): Json
{
if ($this->request->isPost()) {
$keyword = input('keyword/s', '');
$page = input('page/d', 1);
$size = input('size/d', 10);
$id = input('id', '');
$relationIds = explode(',', $id);//已选记录
$where = [];
$where[] = ['is_staff', '=', AccountModel::COMMON_OFF];
if (!empty($keyword)) {
$where[] = ['nickname|real_name|mobile', 'like', '%'.$keyword.'%'];
}
$res = AccountModel::findList($where, ['id', 'nickname', 'real_name', 'mobile'], $page, $size);
if ($res['total'] > 0 && $relationIds) {
$res['list'] = $res['list']->toArray();
foreach ($res['list'] as &$item) {
$item['name_text'] = sprintf("昵称:%s;真实姓名:%s,手机号:%s", $item['nickname'], $item['real_name'], $item['mobile']);
if (count($relationIds) > 0 && in_array($item['id'], $relationIds)) {
$item['selected'] = true;
}
}
}
return $this->json(0, '操作成功', $res);
}
return $this->json(4001, '非法请求');
}
/**
* 充值孔雀币
* */
public function rechargeCoin()
{
$id = input('id/s');
if ($this->request->isPost()) {
$ids = input('ids/s');
if (empty($ids)) {
return $this->json("4003", "请选择用户");
}
$ids = explode(",", $ids);
if (count($ids) > 1000) {
return $this->json("4003", "一次最多选择1000条");
}
$coin = input("coin/d", 1, "abs");
$Account = AccountRepository::getInstance()->getModel()
->where("id", "in", $ids)->lock(true)
->select();
Db::startTrans();
try {
AccountRepository::getInstance()->getModel()->where("id", "in", $ids)->inc("coin", $coin)->update();
$time = date("Y-m-d H:i:s");
$dataLog = [];
$dataOperationLog = [];
$Account->each(function ($item) use ($coin, $time, &$dataLog, &$dataOperationLog) {
$dataLog[] = [
"account_id" => $item["id"],
"operator" => ($this->auth['nickname'] ?? ""),
"operator_id" => $this->auth['user_id'] ?? 0,
"name" => "后台充值孔雀币",
"num" => $coin,
"type" => AccountDataLog::TYPE_COIN,
"action" => AccountDataLog::ACTION_ADMIN_RECHARGE,
"created_at" => $time,
"surplus" => ($item["coin"] + $coin),
];
$dataOperationLog[] = [
"account_id" => $item["id"],
"operator" => ($this->auth['nickname'] ?? ""),
"num" => $coin,
"remark" => "后台充值孔雀币",
"type" => AccountDataLog::TYPE_COIN,
"created_at" => $time,
];
});
AccountDataLog::insertAll($dataLog);
AccountDataOperationLog::insertAll($dataOperationLog);
Db::commit();
return $this->json();
} catch (Exception $e) {
Db::rollback();
return $this->json("5003", "充值失败-1:".$e->getMessage());
} catch (RepositoryException $e) {
Db::rollback();
return $this->json("5003", "充值失败-2:".$e->getMessage());
}
}
$this->data['id'] = $id;
return $this->view();
}
/**
* 用户等级管理
* */
public function accountLevel()
{
if ($this->request->isPost()) {
$page = input('page/d', 1);
$limit = input('size/d', 10);
$items = AccountLevel::findList([], [], $page, $limit, null, ["value" => "desc"]);
$items["list"]->each(function (&$item) {
if (empty($item["rights"])) {
return;
}
$str = "";
foreach (explode(",", $item["rights"]) as $ritem) {
foreach (AccountLevel::$rightsArray as $mitem) {
if ($mitem["key"] == $ritem) {
$str .= $mitem["title"]." ";
}
}
}
$item->rights = $str;
});
return $this->json(0, '操作成功', $items);
}
return $this->view();
}
/**
* 添加用户等级管理
* */
public function addAccountLevel()
{
if ($this->request->isPost()) {
$item = input('post.');
$rule = [
'name|名称' => 'require',
'value|成长值' => 'require',
];
$validate = $this->validateByApi($item, $rule);
if ($validate !== true) {
return $validate;
}
try {
AccountLevel::create($item);
return $this->json();
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
//权益列表
$rightsArray = AccountLevel::$rightsArray;
$this->data['rightsJson'] = json_encode($rightsArray);
return $this->view();
}
/**
* 添加用户等级管理
* */
public function delAccountLevel()
{
if ($this->request->isPost()) {
$id = input('id/d');
$item = AccountLevel::findById($id);
if (empty($item)) {
return $this->json(4001, "信息不存在");
}
AccountLevel::destroy($id);
return $this->json();
}
}
/**
* 编辑用户等级管理
* */
public function editAccountLevel()
{
$id = input("id/d");
$info = AccountLevel::findById($id);
if ($this->request->isPost()) {
if (empty($info)) {
return $this->json(4001, "信息不存在");
}
$item = $this->request->only(["name", "rights", "poster", "value", "content"]);
$rule = [
'name|名称' => 'require',
'value|成长值' => 'require',
];
$validate = $this->validateByApi($item, $rule);
if ($validate !== true) {
return $validate;
}
try {
AccountLevel::updateById($id, $item);
return $this->json();
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
if (empty($info)) {
return $this->error("信息不存在");
}
$this->data['item'] = $info;
//权益列表
$rightsArray = AccountLevel::$rightsArray;
$selectd = [];
if (!empty($info['rights'])) {
$selectd = explode(",", $info['rights']);
}
$this->data['rightsJson'] = AccountLevel::xmSelectJson($selectd);
return $this->view();
}
} }

View File

@ -0,0 +1,25 @@
<?php
namespace app\controller\manager;
use app\model\ActivityTemplateType as ActivityTemplateTypeModel;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\response\Json;
use think\response\View;
/**
* 抽奖模板分类
*
* Class ActivityTemplateType
* @package app\controller\manager
*/
class Activity extends Base
{
}

View File

@ -0,0 +1,186 @@
<?php
namespace app\controller\manager;
use app\model\ActivityTemplate as ActivityTemplateModel;
use app\model\ArchivesModelField;
use app\model\System;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\facade\Config as CConfig;
use think\response\Json;
use think\response\View;
/**
* 抽奖模板分类
*
* Class ActivityTemplateType
* @package app\controller\manager
*/
class ActivityTemplate extends Base
{
protected function initialize()
{
parent::initialize();
CConfig::load('extra/upload', 'system_upload');
if(empty(config('system_upload'))){
$this->data['uploadConfig'] = System::findById(1);
}else{
$this->data['uploadConfig'] = config('system_upload');
}
}
/**
* 删除
*
* @return Json
*/
public function del(): Json
{
if ($this->request->isPost()) {
$ids = input('post.ids/a', []);
if (empty($ids)) {
$ids[] = input('post.id/d');
}
ActivityTemplateModel::deleteByIds($ids);
return $this->json();
}
return $this->json(4001, '非法请求!');
}
/**
* 编辑
*
* @return Json|View
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws Exception
*/
public function edit()
{
$id = input('id/d', 0);
if (!$info = ActivityTemplateModel::findById($id)) {
return $this->json(4001, '记录不存在');
}
if ($this->request->isPost()) {
$item = input('post.');
$validate = $this->validateByApi($item, [
'name' => 'require',
]);
if ($validate !== true) {
return $validate;
}
try {
$info->save($item);
return $this->json();
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
$this->data['item'] = $info;
return $this->view();
}
/**
* 单个字段编辑
*
* @return Json
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws Exception
*/
public function modify(): Json
{
if ($this->request->isPost()) {
$item = input('post.');
$validate = $this->validateByApi($item, [
'field' => 'require',
'value' => 'require',
]);
if ($validate !== true) {
return $validate;
}
if (!$info = ActivityTemplateModel::findById($item['id'])) {
return $this->json(4001, '记录不存在');
}
$update = [$item['field'] => $item['value']];
try {
$info->save($update);
return $this->json();
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
return $this->json(4000, '非法请求');
}
/**
* 添加
*
* @return Json|View
* @throws Exception
*/
public function add()
{
if ($this->request->isPost()) {
$item = input('post.');
$validate = $this->validateByApi($item, [
'name' => 'require',
]);
if ($validate !== true) {
return $validate;
}
$tag = ActivityTemplateModel::findOne(["name"=>$item["name"]]);
if(!empty($tag)){
return $this->json(0, "success", ["id" => $tag["id"]]);
}
try {
$item['create_time'] = date('Y-m-d H:i:s');
$id = ActivityTemplateModel::insertGetId($item);
return $this->json(0, "success", ["id" => $id]);
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
return $this->view();
}
/**
* 列表
*
* @return View|Json
* @throws Exception
*/
public function index()
{
if ($this->request->isPost()) {
$page = input('page/d', 1);
$limit = input('size/d', 20);
$items = ActivityTemplateModel::findList([], [], $page, $limit, function ($q) {
return $q->order('id', 'desc');
});
return $this->json(0, '操作成功', $items);
}
return $this->view();
}
}

View File

@ -0,0 +1,173 @@
<?php
namespace app\controller\manager;
use app\model\ActivityTemplateType as ActivityTemplateTypeModel;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\response\Json;
use think\response\View;
/**
* 抽奖模板分类
*
* Class ActivityTemplateType
* @package app\controller\manager
*/
class ActivityTemplateType extends Base
{
/**
* 删除
*
* @return Json
*/
public function del(): Json
{
if ($this->request->isPost()) {
$ids = input('post.ids/a', []);
if (empty($ids)) {
$ids[] = input('post.id/d');
}
ActivityTemplateTypeModel::deleteByIds($ids);
return $this->json();
}
return $this->json(4001, '非法请求!');
}
/**
* 编辑
*
* @return Json|View
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws Exception
*/
public function edit()
{
$id = input('id/d', 0);
if (!$info = ActivityTemplateTypeModel::findById($id)) {
return $this->json(4001, '记录不存在');
}
if ($this->request->isPost()) {
$item = input('post.');
$validate = $this->validateByApi($item, [
'name' => 'require',
]);
if ($validate !== true) {
return $validate;
}
try {
$info->save($item);
return $this->json();
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
$this->data['item'] = $info;
return $this->view();
}
/**
* 单个字段编辑
*
* @return Json
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws Exception
*/
public function modify(): Json
{
if ($this->request->isPost()) {
$item = input('post.');
$validate = $this->validateByApi($item, [
'field' => 'require',
'value' => 'require',
]);
if ($validate !== true) {
return $validate;
}
if (!$info = ActivityTemplateTypeModel::findById($item['id'])) {
return $this->json(4001, '记录不存在');
}
$update = [$item['field'] => $item['value']];
try {
$info->save($update);
return $this->json();
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
return $this->json(4000, '非法请求');
}
/**
* 添加
*
* @return Json|View
* @throws Exception
*/
public function add()
{
if ($this->request->isPost()) {
$item = input('post.');
$validate = $this->validateByApi($item, [
'name' => 'require',
]);
if ($validate !== true) {
return $validate;
}
$tag = ActivityTemplateTypeModel::findOne(["name"=>$item["name"]]);
if(!empty($tag)){
return $this->json(0, "success", ["id" => $tag["id"]]);
}
try {
$item['create_time'] = date('Y-m-d H:i:s');
$id = ActivityTemplateTypeModel::insertGetId($item);
return $this->json(0, "success", ["id" => $id]);
} catch (ValidateException $e) {
return $this->json(4001, $e->getError());
}
}
return $this->view();
}
/**
* 列表
*
* @return View|Json
* @throws Exception
*/
public function index()
{
if ($this->request->isPost()) {
$page = input('page/d', 1);
$limit = input('size/d', 20);
$items = ActivityTemplateTypeModel::findList([], [], $page, $limit, function ($q) {
return $q->order('sort', 'desc')->order('id', 'asc');
});
return $this->json(0, '操作成功', $items);
}
return $this->view();
}
}

View File

@ -1,26 +0,0 @@
<?php
namespace app\controller\manager;
class map extends Base
{
/**
* 商家列表列表
*
* @return Json|View
* @throws Exception
*/
public function index()
{
return $this->view();
}
}

9
app/model/Activity.php Normal file
View File

@ -0,0 +1,9 @@
<?php
namespace app\model;
//抽奖
class Activity extends Base
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace app\model;
//抽奖模板
class ActivityTemplate extends Base
{
}

View File

@ -0,0 +1,9 @@
<?php
namespace app\model;
//抽奖模板类型
class ActivityTemplateType extends Base
{
}

View File

@ -1,59 +1,11 @@
<?php <?php
namespace app\repository; namespace app\repository;
use app\exception\RepositoryException; use app\exception\RepositoryException;
use app\exception\TraitException;
use app\model\Account;
use app\model\Account as AccountModel;
use app\model\AccountDataLog;
use app\model\AccountFootmarks;
use app\model\AccountLevel;
use app\model\AccountRecord;
use app\model\AccountRule;
use app\model\Activity;
use app\model\Archives;
use app\model\ArchivesCategory;
use app\model\Channel;
use app\model\CustomerReceive;
use app\model\Diary;
use app\model\DoctorRelation;
use app\model\Message as MessageModel;
use app\model\ShareRegLog;
use app\model\Staff;
use app\service\ExtraConfig;
use app\service\File;
use app\service\GdTool;
use app\service\Repository; use app\service\Repository;
use app\traits\account\AccountAddressTrait;
use app\traits\account\AccountCoinTrait;
use app\traits\account\AccountCoinWithdrawalTrait;
use app\traits\account\AccountDataLogTrait;
use app\traits\account\AccountLevelTrait;
use app\traits\account\AccountMessageTrait;
use app\traits\account\AccountRecordTrait;
use app\traits\account\AccountScoreTrait;
use app\traits\account\AppointmentTrait;
use app\traits\account\CouponTrait;
use app\traits\account\TagTrait;
use app\traits\account\FeedbackTrait;
use app\traits\SignInTrait;
use app\traits\worker\DoctorTrait;
use app\traits\worker\StaffTrait;
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh;
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;
use Endroid\QrCode\Writer\PngWriter;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use think\Collection;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use think\facade\Config;
use think\facade\Config as CConfig;
use think\facade\Db;
use think\Model; use think\Model;
/** /**
@ -85,7 +37,7 @@ class AccountRepository extends Repository
* @throws DbException * @throws DbException
* @throws ModelNotFoundException * @throws ModelNotFoundException
*/ */
public function infoByPhone(string $phone, array $fields = []): ?Model public function findByPhone(string $phone, array $fields = []): ?Model
{ {
$where[] = ['mobile', '=', $phone]; $where[] = ['mobile', '=', $phone];
return $this->findOneByWhere($where, $fields); return $this->findOneByWhere($where, $fields);
@ -101,7 +53,7 @@ class AccountRepository extends Repository
* @throws DbException * @throws DbException
* @throws ModelNotFoundException * @throws ModelNotFoundException
*/ */
public function infoByUsername(string $username, array $fields = []): ?Model public function findByUsername(string $username, array $fields = []): ?Model
{ {
$where[] = ['username', '=', $username]; $where[] = ['username', '=', $username];
return $this->findOneByWhere($where, $fields); return $this->findOneByWhere($where, $fields);
@ -169,500 +121,13 @@ class AccountRepository extends Repository
return $this->model->where('coding', $coding)->find(); return $this->model->where('coding', $coding)->find();
} }
/**
* 修改密码
*
* @param int $accountId
* @param string $oldPwd
* @param string $newPwd
* @return bool
* @throws RepositoryException
*/
public function modifyPwd(int $accountId, string $oldPwd, string $newPwd): bool
{
if (!$user = $this->findById($accountId)) {
throw new RepositoryException('用户不存在');
}
if ($user['password'] != md5($oldPwd)) {
throw new RepositoryException('原密码错误');
}
$user->password = md5($newPwd);
return $user->save();
}
/********************************************** /**********************************************
* TODO 分割线,上述与本项目无关的代码需要清除 * TODO 分割线,上述与本项目无关的代码需要清除
*********************************************/ *********************************************/
/**
* 修改用户数据
*
* @param int $accountId
* @param array $fieldsKV 修改内容:键值对
* @return mixed
* @throws RepositoryException
*/
public function accountEditInfo(int $accountId, array $fieldsKV)
{
$allowFields = ['headimgurl', 'real_name', 'nickname', 'mobile', 'gender', 'province', 'city', 'county', 'birthday'];
$fieldsKV = arrayKeysFilter($fieldsKV, $allowFields);
if (isset($fieldsKV['mobile']) && !empty($fieldsKV['mobile'])) {
if (!checkMobile($fieldsKV['mobile'])) {
throw new RepositoryException('手机号不正确');
}
}
if (!$account = $this->findById($accountId)) {
throw new RepositoryException('用户信息错误');
}
return $account->save($fieldsKV);
}
/**
* 统计用户分销人数(二级)
*/
public function shareAccountCount(int $accountId): array
{
$data = [
'first' => 0,
'second' => 0,
'total' => 0,
];
try {
$data['first'] = ShareRegLog::where('inviter_account_id', $accountId)->where('is_active', ShareRegLog::COMMON_ON)->count();
$data['second'] = ShareRegLog::where('inviter_parent_account_id', $accountId)->where('is_active', ShareRegLog::COMMON_ON)->count();
$data['total'] = $data['first'] + $data['second'];
} catch (Exception $e) {
}
return $data;
}
/**
* 添加分享注册关系绑定日志
*
* @param int $accountId
* @param int $inviterId
* @param string $grade 分享绑定关系层级
* @param bool $accountActive 是否为有效用户
* @return bool
*/
public function addShareRegLogBak(int $accountId, int $inviterId, string $grade, bool $accountActive = true): bool
{
if ($accountId <= 0 || $inviterId <= 0) {
return false;
}
Db::startTrans();
try {
$shareConf = ExtraConfig::share();
$score = $shareConf[$grade] ?? 0;
$regLog = ShareRegLog::where('reg_account_id', $accountId)
->where('inviter_account_id', $inviterId)
->find();
$isCreate = false;
$isUpdate = false;
if ($accountActive) {
if (!$regLog) {
$isCreate = true;
} elseif ($regLog['score'] == 0) {
// 用户激活后,获得积分
$isUpdate = true;
}
} else {
if ($regLog) {
throw new RepositoryException('已有绑定记录!');
} else {
// 未有效激活的用户,相关绑定的人员只有在该用户成功激活后才能获得积分
$score = 0;
$isCreate = true;
}
}
switch ($grade) {
case self::SHARE_CURRENT:
$grade = ShareRegLog::SHARE_GRADE_FIRST;
break;
case self::SHARE_PARENT:
$grade = ShareRegLog::SHARE_GRADE_SECOND;
break;
case self::SHARE_SERVICE:
$grade = ShareRegLog::SHARE_GRADE_SERVICE;
break;
default:
return false;
}
if ($isCreate) {
ShareRegLog::create([
'reg_account_id' => $accountId,
'inviter_account_id' => $inviterId,
'grade' => $grade,
'score' => $score,
'created_at' => date('Y-m-d H:i:s')
]);
} elseif ($isUpdate) {
$regLog->save(['score' => $score]);
}
if ($isCreate || $isUpdate) {
$inviter = $this->model->where('id', $inviterId)->lock(true)->find();
if ($inviter) {
Account::updateById($inviterId, [
'score' => $inviter['score'] + $score
]);
}
}
Db::commit();
} catch (RepositoryException | Exception $e) {
Db::rollback();
return false;
}
return true;
}
/**
* 注册时邀请关系绑定
* 存在邀请人时。邀请人、邀请人当前的客服、邀请人的邀请人三者均可获得相应积分
*
* @param int $regAccountId 注册人ID
* @param int $inviterId 邀请人ID
* @param int $inviterParentAid 邀请人的邀请人ID
* @param int $serviceId 邀请人的当前客服ID
* @return bool
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function addShareRegLog(int $regAccountId, int $inviterId, int $inviterParentAid = 0, int $serviceId = 0): bool
{
if ($regAccountId <= 0 || $inviterId <= 0) {
return false;
}
$shareConf = ExtraConfig::share();
if (ShareRegLog::where('reg_account_id', $regAccountId)->find()) {
return true;
}
ShareRegLog::create([
'reg_account_id' => $regAccountId,
'inviter_account_id' => $inviterId,
'inviter_parent_account_id' => $inviterParentAid,
'inviter_service_account_id' => $serviceId,
'score' => $shareConf[self::SHARE_CURRENT] ?? 0,
'parent_score' => $shareConf[self::SHARE_PARENT] ?? 0,
'service_score' => $shareConf[self::SHARE_SERVICE] ?? 0,
'is_active' => ShareRegLog::COMMON_OFF,
'created_at' => date('Y-m-d H:i:s'),
]);
return true;
}
/**
* 分享注册激活 【手机绑定时激活】
* 激活时1、日志变更 2、积分发放【邀请人、邀请人上级、邀请人客服】 3、积分日志添加
*
* @param int $regAccountId
* @return bool
*/
public function activeShareRegLog(int $regAccountId): bool
{
if ($regAccountId <= 0) {
return false;
}
Db::startTrans();
try {
if (!$regLog = ShareRegLog::where('reg_account_id', $regAccountId)->find()) {
return false;
}
if ($regLog['is_active'] == ShareRegLog::COMMON_ON) {
return true;
}
ShareRegLog::where('reg_account_id', $regAccountId)->save(
['is_active' => ShareRegLog::COMMON_ON, 'activated_at' => date('Y-m-d H:i:s')]
);
$accountFields = ['id', 'score'];
// 邀请人积分添加
if ($regLog['score'] > 0) {
$inviter = Account::findById($regLog['inviter_account_id'], $accountFields);
AccountDataLog::log($regLog['inviter_account_id'], '分享注册', $regLog['score'],
AccountDataLog::TYPE_SCORE, AccountDataLog::ACTION_SHARE_REG,
$inviter['score'], '系统自动发放');
$inviter->save(
['score' => Db::raw('`score` + '.$regLog['score'])]
);
}
// 邀请人父级积分添加
if ($regLog['inviter_parent_account_id'] > 0 && $regLog['parent_score'] > 0) {
$inviterParent = Account::findById($regLog['inviter_parent_account_id'], $accountFields);
AccountDataLog::log($regLog['inviter_parent_account_id'], '分享注册-下级分享', $regLog['parent_score'],
AccountDataLog::TYPE_SCORE, AccountDataLog::ACTION_SHARE_REG_CHILD,
$inviterParent['score'], '系统自动发放');
$inviterParent->save(
['score' => Db::raw('`score` + '.$regLog['parent_score'])]
);
}
// 邀请人的客服积分添加
if ($regLog['inviter_service_account_id'] > 0 && $regLog['service_score']) {
$inviterService = Account::findById($regLog['inviter_service_account_id'], $accountFields);
AccountDataLog::log($regLog['inviter_service_account_id'], '分享注册-分享人客服获得积分', $regLog['service_score'],
AccountDataLog::TYPE_SCORE, AccountDataLog::ACTION_SHARE_REG_SERVICE,
$inviterService['score'], '系统自动发放');
$inviterService->save(
['score' => Db::raw('`score` + '.$regLog['service_score'])]
);
}
Db::commit();
} catch (Exception $e) {
self::log($e);
Db::rollback();
return false;
}
return true;
}
/**
* 查看分享绑定的用户信息
*
* @param int $accountId
* @param string $grade
* @param int $page
* @param int $size
* @return array|null
*/
public function shareUsers(int $accountId, string $grade, int $page = 1, int $size = 10): ?array
{
$data = [
'total' => 0,
'current' => $page,
'size' => $size,
'list' => new Collection(),
];
try {
if (!in_array($grade, [self::SHARE_GRADE_FIRST, self::SHARE_GRADE_SECOND])) {
throw new RepositoryException('层级参数错误');
}
$fields = ['id', 'real_name', 'nickname', 'headimgurl', 'invite_source', 'phone_active'];
$whereMap = [];
switch ($grade) {
case self::SHARE_GRADE_FIRST:
$whereMap[] = ['inviter_account_id', '=', $accountId];
break;
case self::SHARE_GRADE_SECOND:
$whereMap[] = ['inviter_parent_account_id', '=', $accountId];
break;
}
$whereMap[] = ['is_active', '=', self::BOOL_TRUE];
$orders = ['id' => 'desc'];
$data = ShareRegLog::findList($whereMap, [], $page, $size, function ($q) use ($fields) {
return $q->with([
'account' => function ($q2) use ($fields) {
$q2->field($fields);
}
]);
}, $orders);
$inviteSourceTextList = self::inviteSourceList();
foreach ($data['list'] as $item) {
$item['desc'] = '';
$item['grade'] = $grade;
if ($grade == self::SHARE_GRADE_SECOND) {
$item['score'] = $item['parent_score'];
}
if ($grade == self::SHARE_GRADE_SERVICE) {
$item['score'] = $item['service_score'];
}
unset($item['parent_score']);
unset($item['service_score']);
$regAccount = $item['account'];
if ($regAccount) {
$regAccount['invite_source_desc'] = '';
if ($regAccount['invite_source'] != self::INVITE_SOURCE_DEF) {
$regAccount['invite_source_desc'] = $inviteSourceTextList[$regAccount['invite_source']] ?? '';
}
$regAccount['headimgurl'] = File::convertCompleteFileUrl($regAccount['headimgurl']);
}
$item['account'] = $regAccount;
}
} catch (RepositoryException | Exception $e) {
}
return $data;
}
/**
* 用户行为记录统计
* 点赞、收藏、分享等
* @param string $type
* @param string $action
* @param int $accountId
* @return int
*/
public function countRecordByAction(string $type, string $action, int $accountId = 0): int
{
if (!in_array($type, AccountRecord::allowTypes())) {
return 0;
}
if (!in_array($action, AccountRecord::allowActions())) {
return 0;
}
return AccountRecord::countByAction($type, $action, $accountId);
}
/**
* 获取用户绑定的客服人员Id
*/
public function getBoundServiceAId(int $accountId)
{
try {
return CustomerReceive::getBoundService($accountId);
} catch (Exception $e) {
return 0;
}
}
/**
* 获取用户绑定的客服人员
*/
public function getBoundService(int $customerAId, string $action)
{
try {
return CustomerReceive::where('customer_aid', $customerAId)
->where('action', $action)
->find();
} catch (Exception $e) {
return null;
}
}
/**
* 获取客户接待流转记录
*
* @param int $customerAId
* @param array $actions
* @return CustomerReceive[]|array|Collection
*/
public function findListCustomerReceive(int $customerAId, array $actions)
{
try {
return CustomerReceive::where('customer_aid', $customerAId)
->whereIn('action', $actions)
->select();
} catch (Exception $e) {
return new Collection();
}
}
// 足迹列表
public function footmarks(int $accountId, int $customerId = 0, string $keyword = '', int $page = 1, int $size = 20): array
{
$customerIds = [];
if (!$account = Account::findById($accountId)) {
throw new RepositoryException('账号信息不存在');
}
if (!$account->is_staff) {
throw new RepositoryException('您不是员工');
}
$exclude = $accountId == $customerId ? 0 : $accountId;
$rules = AccountRepository::getInstance()->getAccountRules($accountId);
$ruleChildren = in_array(AccountRule::RULE_FOOTMARKS, $rules);// 查看下级客户
$ruleAll = in_array(AccountRule::RULE_VIEW_ALL_FOOTMARKS, $rules); // 查看所有足迹
// 查看指定人足迹 检查该员工是否可查看
if (!$ruleChildren && !$ruleAll) {
throw new RepositoryException('权限不足');
}
if ($customerId > 0) {
$customerIds[] = $customerId;
}
if ($ruleAll) {
$accountId = 0;// 查看全部权限 则不指定员工account_id
}
return AccountFootmarks::fetch($accountId, $customerIds, $keyword, $page, $size, $exclude);
}
/**
* 客户列表
*
* @param array $where
* @param array $field
* @param int $accountId
* @param int $page
* @param int $size
* @param callable|null $call
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function customerList(array $where = [], array $field = [], int $accountId = 0, int $page = 1, int $size = 20, callable $call = null): array
{
if ($accountId > 0) {
if (!$staff = Staff::findOne(['account_id' => $accountId])) {
throw new RepositoryException('你不是员工');
}
$staffRules = explode(',', $staff['rules']);
if (!in_array('customer-list', $staffRules)) {
throw new RepositoryException('请获取客户列表查看权限');
}
// 是否具有查看所有用户权限
if (!in_array('view-all-customer-list', $staffRules)) {
// 查看自己的客户
// 获取指定用户的客户 TODO 此处若下级过多 会有性能影响
$customerIds = CustomerReceive::getChildrenIds($accountId);
$where[] = ['id', 'in', $customerIds];
}
}
return $this->getAndHandleAccountList($where, $field, $page, $size, $call);
}
/** /**
* 获取并处理用户列表 【后台用户列表】 * 获取并处理用户列表 【后台用户列表】
@ -680,391 +145,11 @@ class AccountRepository extends Repository
*/ */
public function getAndHandleAccountList(array $where, array $field, int $page = 1, int $size = 20, callable $call = null): ?array public function getAndHandleAccountList(array $where, array $field, int $page = 1, int $size = 20, callable $call = null): ?array
{ {
$items = self::findList($where, $field, $page, $size, function ($q) use ($call) { return self::findList($where, $field, $page, $size, function ($q) use ($call) {
if ($call !== null) { if ($call !== null) {
$q = $call($q); $q = $call($q);
} }
return $q return $q->order('id', 'desc');
->with(['tags', 'staff', 'customer', 'serviceList'])
->order('id', 'desc');
}); });
$levelList = AccountRepository::getInstance()->getLevelList();
$items['list']->each(function ($item) use ($levelList) {
$item->channel_text = $this->model::channelTextList()[$item['channel']] ?? '未知来源';
$item->share_source = $item->is_staff > 0 ? ($item->staff->name ?? '') : ($item->customer->nickname ?? '');
$item->is_sign_text = $item->is_sign ? '是' : '否';
$item->tag = $item->tags->column('name');
$item->service = $item->serviceList->name ?? '';
$item->service_name = $item->serviceList->name ?? '';
$item->source_detail = AccountRepository::getInstance()->getSourceDetail($item->id);
$item->levelInfo = AccountRepository::getInstance()->getCurrentLevel($item->coin_total, $levelList);
$genderText = '保密';
if ($item->gender == 1) {
$genderText = '男';
}
if ($item->gender == 2) {
$genderText = '女';
}
$item->gender_text = $genderText;
});
return $items;
}
/**
* 获取账号详细来源
*
* @param int $accountId
* @return string
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function getSourceDetail(int $accountId): string
{
if (!$account = $this->findById($accountId)) {
return '';
}
switch ($account['channel']) {
case AccountModel::CHANNEL_NORMAL:
return '自然流量进入';
case AccountModel::CHANNEL_MEMBER:
// 员工信息
if (!$source = Staff::findOne(['account_id' => $account['inviter_account_id']])) {
//员工不存在 查找用户信息
if (!$source = AccountModel::findById($account['inviter_account_id'])) {
//用户不存在
$member = '用户已不存在';
} else {
$member = $source['name'];
}
} else {
$member = $source['name'];
}
return sprintf("员工【%s】分享进入", $member);
case AccountModel::CHANNEL_CUSTOMER:
//客户不存在
$ddd = $account['inviter_account_id'];
if (!$source = AccountModel::findById($account['inviter_account_id'])) {
//用户不存在
$member = '客户已不存在';
} else {
$member = $source['nickname'].':'.$source['mobile'];
}
return sprintf("客户【%s】分享进入", $member);
case AccountModel::CHANNEL_ACTIVITY:
//活码
if (!$source = Activity::findOne(['code' => $account['source_code']])) {
//用户不存在
$member = '活码已不存在';
} else {
$member = $source['name'];
}
return sprintf("通过活码【%s】进入", $member);
default:
return AccountModel::channelTextList()[$account['channel']] ?? '未知渠道';
} }
} }
/**
* 个人海报模板列表
*
* @param int $accountId
* @param int $page
* @param int $size
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function poster(int $accountId, int $page = 1, int $size = 10): array
{
if (!$account = Account::findById($accountId)) {
throw new RepositoryException('请先登录');
}
$list = [];
// 获取可用的会员海报
$levelPoster = AccountLevel::where('value', '<', $account['coin_total'])->order('value', 'desc')->column('poster');
foreach ($levelPoster as $poster) {
$list = array_merge($list, explode(',', $poster));
}
// 获取基础海报列表
Config::load('extra/mini_program', 'mini_program');
$conf = config('mini_program');
$basePoster = $conf['poster'] ?? [];
$list = array_merge($list, $basePoster);
$list = array_filter($list);
return [
'total' => count($list),
'current' => $page,
'size' => $size,
'list' => array_slice($list, ($page - 1) * $size, $size),
];
}
/**
* @throws RepositoryException
*/
public function posterInfo(int $accountId, string $posterSrc, string $domain)
{
$bgImg = $posterSrc;
$bgImg = empty($bgImg) ? '' : File::convertCompleteFileUrl($bgImg);
try {
if (!$account = AccountRepository::getInstance()->findById($accountId)) {
throw new RepositoryException('请先登录');
}
$inviteCode = $account['invite_code'] ?: md5($account['id']);
$inviteUrl = $domain.'/share?invite_code='.$inviteCode;
$logoImg = app()->getRootPath().'public/static/images/icon-logo.jpg';
$result = Builder::create()
->writer(new PngWriter())
->writerOptions([])
->data($inviteUrl)
->encoding(new Encoding('UTF-8'))
->errorCorrectionLevel(new ErrorCorrectionLevelHigh())
->size(300)
->margin(10)
->roundBlockSizeMode(new RoundBlockSizeModeMargin())
->logoPath($logoImg)
->logoResizeToHeight(100)
->logoResizeToWidth(100)
->logoPunchoutBackground(true)
->build();
$dataUri = $result->getDataUri();
return GdTool::generatePoster($dataUri, $bgImg);
} catch (Exception $e) {
AccountRepository::log('个人海报生成失败', $e);
throw $e;
}
}
/**
* 获取个人日记
*
* @param int $accountId
* @param int $page
* @param int $size
* @return array
* @throws Exception
*/
public function diary(int $accountId, int $page = 1, int $size = 10): array
{
$where = [];
$where[] = ['publish_account', '=', $accountId];
// $where[] = ['diary_check', '=', Archives::COMMON_ON];
$field = [];
return Archives::findList($where, $field, $page, $size, null, ['sort' => 'desc', 'id' => 'desc']);
}
/**
* 日记添加
*
* @param array $params
* @return bool
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function diarySave(array $params): bool
{
$id = $params['id'] ?? 0;
$now = date('Y-m-d H:i:s');
if ($id > 0) {
// 修改
$item = Archives::findById($id);
if ($item) {
$item->save($params);
} else {
$id = 0;
}
}
$doctorArr = [];
if (isset($params['doctor_id'])) {
$doctorArr = explode(',', $params['doctor_id']);
}
// 新建日记
if ($id <= 0) {
$params['category_id'] = ArchivesCategory::where('name', ArchivesCategory::NAME_DIARY)->value('id');
$params['created_at'] = $now;
$params['published_at'] = $now;
$params['created_by'] = $params['publish_account'];
$diaryCollection = $this->getDiaryCollection($params['publish_account']);
if (!$diaryCollection) {
$diaryCollection = $this->createDiaryCollection($params['publish_account'], $params['disease_id'], $doctorArr);
}
$params['diary_id'] = $diaryCollection['id'];
$archives = Archives::create($params);
$id = $archives['id'];
}
if ($doctorArr) {
//关联医生
DoctorRelation::associateDoctor($doctorArr, $id, DoctorRelation::TYPE_CONTENT);
}
return true;
}
/**
* 删除日记
*
* @param array $ids
* @return bool
*/
public function diaryDel(array $ids): bool
{
Archives::whereIn('id', $ids)->delete();
// 删除关联医生
DoctorRelation::whereIn('relation_id', $ids)->where('type', DoctorRelation::TYPE_CONTENT)->delete();
return true;
}
/**
* 日记详情
*
* @param int $id
* @return array|Model|null
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function diaryInfo(int $id)
{
return Archives::findById($id);
}
/**
* 获取用户日记合集
*
* @param int $accountId
* @return array|Diary|Model|null
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function getDiaryCollection(int $accountId)
{
if (!$diary = Diary::where('account_id', $accountId)->find()) {
return null;
}
return $diary;
}
/**
* 创建日记合集
*
* @param int $accountId
* @param int $diseaseId
* @param array $doctorIds 关联医生
* @return Diary|Model
* @throws RepositoryException
*/
public function createDiaryCollection(int $accountId, int $diseaseId, array $doctorIds = [])
{
if (!$account = AccountRepository::getInstance()->findById($accountId)) {
throw new RepositoryException('用户信息错误');
}
$now = date('Y-m-d H:i:s');
$diary = Diary::create([
'title' => '日记合集-'.$account['nickname'],
'disease_id' => $diseaseId,
'user' => $account['nickname'],
'headimg' => $account['headimgurl'],
'created_at' => $now,
'published_at' => $now,
'account_id' => $accountId,
]);
if ($doctorIds) {
DoctorRelation::associateDoctor($doctorIds, $diary['id'], DoctorRelation::TYPE_DIARY);
}
return $diary;
}
/**
* 创建消息 支持推送订阅消息和短信 支持批量
*
* @param array $item
* item[title]: 是生生世世 消息标题
* item[type]: notice 消息类型 此处固定为notice 通知
* item[target]: part 目标类型 all=所有人 part=部分人
* item[subscribe_temp_id]: d0efR-Ga27c6eIvx9mAwJcnAqzhM_Sq68XiFvjvlBJM 订阅消息模版ID
* item[subscribe_data][thing1]: 事实上 订阅消息内容 subscribe_data根据模版变动参数
* item[subscribe_data][time4]: 坎坎坷坷
* item[subscribe_data][thing5]: 哈对方的身份
* item[sms_temp_id]: SMS_231436568 短信模版ID
* item[content]: 收拾收拾 通知内容
*
* @param array $targetList [13,15] 发送人ID列表
* @throws GuzzleException
*/
public function createMessage(array $item, array $targetList)
{
$repo = AccountRepository::getInstance();
try {
$type = $item['type'] ?? '';
$target = $item['target'] ?? '';
$subscribeData = $item['subscribe_data'] ?? [];
$smsData = $item['sms_data'] ?? [];
$item["send_at"] = date('Y-m-d H:i:s');
$item["content"] = $item['content'];
$item['is_push'] = MessageModel::COMMON_ON;
$item['to_subscribe'] = (int) !empty($item['subscribe_temp_id']);
$item['to_sms'] = (int) !empty($item['sms_temp_id']);
$item['subscribe_data'] = json_encode($subscribeData, JSON_UNESCAPED_UNICODE);
$item['sms_data'] = json_encode($smsData, JSON_UNESCAPED_UNICODE);
$message = $repo->addMessage($type, $target, $targetList, $item);
} catch (Exception $e) {
AccountRepository::log('创建消息通知失败 ', $e);
}
try {
if ($item['to_sms']) {
// 批量发送短信
$res = AccountRepository::getInstance()->smsSend($message->id, $item['sms_temp_id'], $targetList, $smsData);
// var_dump($res);
}
} catch (Exception $e) {
AccountRepository::log('短信发送失败 ', $e);
}
try {
if ($item['to_subscribe'] > 0) {
// 订阅消息发送
AccountRepository::getInstance()->subscribeSend($message->id, $item['subscribe_temp_id'],
$targetList, $subscribeData,
\app\model\Config::MINI_PATH_MESSAGE_CENTER);
}
} catch (Exception $e) {
AccountRepository::log('订阅消息发送失败 ', $e);
}
}
}

View File

@ -46,19 +46,13 @@ layui.use(['laytpl', 'table', 'jquery', 'form', 'miniTab', 'xmSelect', 'laydate'
cols: [[ cols: [[
{type: 'checkbox'}, {type: 'checkbox'},
{field: 'id', minWidth: 50, title: '编号'}, {field: 'id', minWidth: 50, title: '编号'},
{field: 'nickname', minWidth: 150, title: '昵称'}, {field: 'nickname', title: '昵称'},
{field: 'real_name', minWidth: 150, title: '真实姓名'}, {field: 'real_name', title: '真实姓名'},
{field: 'mobile', minWidth: 150, title: '电话'}, {field: 'mobile',title: '电话'},
{field: 'channel_text', minWidth: 150, title: '客户来源'}, {field: 'created_at', title: '注册时间'},
{field: 'source_detail', minWidth: 200, title: '详细来源'}, {field: 'score', title: '积分'},
{field: 'service_name', minWidth: 150, title: '所属客服'}, {field: 'balance', title: '余额'},
{field: 'tag', minWidth: 150, title: '客户标签'}, {templet: '#row-operate',minWidth: 150, title: '操作'},
{field: 'created_at', minWidth: 200, title: '注册时间'},
{field: 'is_sign_text', minWidth: 100, title: '是否到店'},
{field: 'score', minWidth: 100, title: '积分'},
{field: 'coin', minWidth: 100, title: '孔雀币'},
{field: 'gender_text', minWidth: 100, title: '性别'},
{templet: '#row-operate', fixed: "right", minWidth: 250, title: '操作'},
]], ]],
done: function () { done: function () {
Tools.setInsTb(insTb); Tools.setInsTb(insTb);
@ -136,292 +130,4 @@ layui.use(['laytpl', 'table', 'jquery', 'form', 'miniTab', 'xmSelect', 'laydate'
}); });
} }
/*** index end ***/ /*** index end ***/
if ($('.location-staff-page').length > 0) {
let staffList = $('#staff-list');
let dataOne = staffList.data('data') ? staffList.data('data') : [];
xmSelect.render({
el: '#staff-list',
paging: true,
autoRow: true,
radio: true,
clickClose: true,
name: 'staff_id',
tips: '请选择员工',
direction: 'auto',
height: 'auto',
prop: {
name: 'name',
value: 'id',
},
model: {
icon: 'hidden',
},
theme: {
color: '#1e84ff',
},
data: dataOne
});
}
if ($('.location-source-page').length > 0) {
form.on('select(channel-select)', function (data) {
//切换
$('.channel-div').hide();//全部隐藏
$('.current-channel-' + data.value).show();
})
xmSelect.render({
el: '#staff-list',
autoRow: true,
radio: true,
clickClose: true,
page: true,
name: 'type_staff',
tips: '请选择员工',
direction: 'auto',
height: 'auto',
model: {
icon: 'hidden',
},
prop: {
name: 'name',
value: 'account_id',
},
filterable: true,
toolbar: {show: true},
remoteSearch: true,
remoteMethod: function (val, cb, show) {
$.post('/manager/account/get-staff-list', {keyword: val}, function (res) {
if (res.code === 0) {
cb(res.data.list);
}
});
},
theme: {
color: '#1e84ff',
},
});
xmSelect.render({
el: '#customer-list',
autoRow: true,
radio: true,
clickClose: true,
name: 'type_customer',
tips: '请选择客户',
direction: 'auto',
height: 'auto',
model: {
icon: 'hidden',
},
template({ item, sels, name, value }){
return item.nickname + '<span style="position: absolute; right: 10px; color: #8799a3">真实姓名:'+item.real_name +
'手机号:'+item.mobile+
'</span>'
},
prop: {
name: 'nickname',
value: 'id',
},
filterable: true,
toolbar: {show: true},
remoteSearch: true,
remoteMethod: function (val, cb, show) {
$.post('/manager/account/get-account-list', {keyword: val}, function (res) {
if (res.code === 0) {
cb(res.data.list);
}
});
},
theme: {
color: '#1e84ff',
},
});
xmSelect.render({
el: '#activity-list',
autoRow: true,
radio: true,
clickClose: true,
name: 'type_activity',
tips: '请选择活动',
direction: 'auto',
height: 'auto',
model: {
icon: 'hidden',
},
prop: {
name: 'name',
value: 'code',
},
filterable: true,
toolbar: {show: true},
remoteSearch: true,
remoteMethod: function (val, cb, show) {
$.post('/manager/activity/get-activity-list', {keyword: val}, function (res) {
if (res.code === 0) {
cb(res.data.list);
}
});
},
theme: {
color: '#1e84ff',
},
});
}
if ($('.location-tag-page').length > 0) {
let tagList = $('#tag-list');
let dataOne = tagList.data('data') ? tagList.data('data') : [];
var xmSelectObj = xmSelect.render({
el: '#tag-list',
paging: true,
autoRow: true,
name: 'tag_id',
tips: '请选择客户标签',
direction: 'auto',
height: 'auto',
prop: {
name: 'name',
value: 'id',
},
model: {
icon: 'hidden',
},
theme: {
color: '#1e84ff',
},
on: function(data){
//可以return一个数组, 代表想选中的数据
//arr: 当前多选已选中的数据
var arr = data.arr;
//change, 此次选择变化的数据,数组
var change = data.change;
//isAdd, 此次操作是新增还是删除
var isAdd = data.isAdd;
if(isAdd){
for(j = 0,len=change.length; j < len; j++) {
if(change[j].add != undefined && change[j].add==true){
console.log( change[j].name);
$.ajax('/manager/account-tag/add', {
data: {name: change[j].name},
async: false,
dataType: 'json',//服务器返回json格式数据
type: 'post',//HTTP请求类型
timeout: 10000,//超时时间设置为10秒
success: function (res) {
console.log(res)
if (res.code == 0) {
let id = res.data.id;
var name = change[j].name
var value = change[j].value
arr.find(function(item){
if(item.name == name){
item.id = id;
item.value = value;
}
});
layer.msg("创建新标签成功");
//返回一个创建成功的对象, val是搜索的数据, arr是搜索后的当前页面数据
}else{
layer.msg("创建新标签失败");
}
},
error: function (xhr, type, errorThrown) {
}
});
}
}
}
console.log(arr);
xmSelectObj.setValue(arr)
},
filterable: true,
create: function(val, arr){
if(arr.length === 0){
return {
name: "新增_" + val,
id: val,
value:val,
add:true
}
}
},
data: dataOne
});
}
if ($('.location-detail-page').length > 0) {
miniTab.listen();
laydate.render({
elem: '#publish-date',
});
// 渲染表格
let listUrl = $('#table-container-detail').data('url');
let insTb = table.render({
elem: '#table-container-detail',
toolbar: '#toolbar-tpl-detail',
defaultToolbar: ['filter', 'exports', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可
title: '搜索'
, layEvent: 'search'
, icon: 'layui-icon-search'
}],
url: listUrl,
method: 'post',
even: true,
limits: [10, 20, 50, 100, 200, 500, 1000, 2000],
request: {
pageName: 'page',
limitName: 'size',
},
parseData: function (res) {
return {
"code": res.code, //解析接口状态
"msg": res.msg, //解析提示文本
"count": res.data.total, //解析数据长度
"data": res.data.list //解析数据列表
};
},
page: true,
cols: [[
{type: 'checkbox'},
{field: 'id', minWidth: 50, title: '编号'},
{field: 'created_at', minWidth: 200, title: '时间'},
{field: 'nickname', minWidth: 150, title: '用户'},
{field: 'real_name', minWidth: 150, title: '真实姓名'},
{field: 'mobile', minWidth: 150, title: '电话'},
{templet: '#row-action', minWidth: 200, title: '浏览'},
{field: 'event', minWidth: 80, title: '操作触发'},
]],
done: function () {
Tools.setInsTb(insTb);
}
});
// 监听搜索操作
form.on('submit(data-search-btn)', function (data) {
// 打开新的窗口
//执行搜索重载
table.reload('table-container-detail', {
page: {curr: 1}
, where: {searchParams: data.field}
}, 'data');
return false;
});
}
}); });

View File

@ -0,0 +1,134 @@
layui.use(['jquery', 'laytpl', 'table', 'form', 'miniTab'], function () {
let $ = layui.jquery,
form = layui.form,
table = layui.table,
layer = layui.layer,
miniTab = layui.miniTab;
let modifyUrl = $('#row-modify').data('url');
/**** index begin ***/
//index页面
if ($('.location-index-page').length > 0) {
miniTab.listen();
// 渲染表格
let listUrl = $('#table-container').data('url');
let insTb = table.render({
elem: '#table-container',
toolbar: '#toolbar-tpl',
defaultToolbar: [],
url: listUrl,
method: 'post',
request: {
pageName: 'page',
limitName: 'size',
},
parseData: function (res) {
return {
"code": res.code, //解析接口状态
"msg": res.msg, //解析提示文本
"count": res.data.total, //解析数据长度
"data": res.data.list //解析数据列表
};
},
page: true,
cols: [[
{type: 'checkbox'},
{field: 'name', minWidth: 200, title: '名称'},
{field: 'type_text', title: '类型'},
{field: 'lottery_method_text', title: '开奖方式'},
{field: 'sort', align: 'center', title: '排序', edit: 'text'},
{templet: '#row-operate', align: 'center', title: '操作'}
]],
done: function () {
}
});
//监听单元格编辑
table.on('edit(table-container)', function (obj) {
$.post(modifyUrl, {id: obj.data.id, field: obj.field, value: obj.value}, function (res) {
layer.msg(res.msg)
if (res.code === 0) {
insTb.reload();
}
})
});
//监听工具条 注意区别toolbar和tool toolbar是表头上的工具条 tool是行中的工具条
table.on('toolbar(table-container)', function (obj) {
let layEvent = obj.event;
if (layEvent === 'del') {
let checkStatus = table.checkStatus('table-container');
if (checkStatus.data.length <= 0) {
layer.msg('请先选择数据');
return false;
}
let selected = checkStatus.data;
let ids = [];
let url = $($(this).context).data('href')
$.each(selected, function (index, val) {
ids.push(val.id);
})
del(url, ids);
return false;
}
if (layEvent === 'refresh') {
insTb.reload();
return false;
}
if (layEvent === 'add') {
let url = $($(this).context).data('href')
let title = $($(this).context).data('title')
openLayer(url, title);
return false;
}
});
//删除
function del(url, ids) {
let index = layer.confirm('确认删除吗?', {
btn: ['确认', '取消'], //按钮
title: '操作提示',
}, function () {
$.post(url, {ids: ids}, function (res) {
layer.msg(res.msg)
if (res.code === 0) {
insTb.reload();
}
})
}, function () {
layer.close(index)
return false;
});
}
//监听工具条
table.on('tool(table-container)', function (obj) {
let data = obj.data;
let layEvent = obj.event;
let url = $($(this).context).data('href');
let title = $($(this).context).data('title');
if (layEvent === 'del') {
let ids = [data.id];
del(url, ids);
return false;
}
if (layEvent === 'edit') {
openLayer(url, title);
return false;
}
});
}
/*** index end ***/
if ($('.location-rule-page').length > 0) {
}
});

View File

@ -0,0 +1,132 @@
layui.use(['jquery', 'laytpl', 'table', 'form', 'miniTab'], function () {
let $ = layui.jquery,
form = layui.form,
table = layui.table,
layer = layui.layer,
miniTab = layui.miniTab;
let modifyUrl = $('#row-modify').data('url');
/**** index begin ***/
//index页面
if ($('.location-index-page').length > 0) {
miniTab.listen();
// 渲染表格
let listUrl = $('#table-container').data('url');
let insTb = table.render({
elem: '#table-container',
toolbar: '#toolbar-tpl',
defaultToolbar: [],
url: listUrl,
method: 'post',
request: {
pageName: 'page',
limitName: 'size',
},
parseData: function (res) {
return {
"code": res.code, //解析接口状态
"msg": res.msg, //解析提示文本
"count": res.data.total, //解析数据长度
"data": res.data.list //解析数据列表
};
},
page: true,
cols: [[
{type: 'checkbox'},
{field: 'name', minWidth: 200, title: '名称'},
{field: 'sort', align: 'center', title: '排序', edit: 'text'},
{templet: '#row-operate', align: 'center', title: '操作'}
]],
done: function () {
}
});
//监听单元格编辑
table.on('edit(table-container)', function (obj) {
$.post(modifyUrl, {id: obj.data.id, field: obj.field, value: obj.value}, function (res) {
layer.msg(res.msg)
if (res.code === 0) {
insTb.reload();
}
})
});
//监听工具条 注意区别toolbar和tool toolbar是表头上的工具条 tool是行中的工具条
table.on('toolbar(table-container)', function (obj) {
let layEvent = obj.event;
if (layEvent === 'del') {
let checkStatus = table.checkStatus('table-container');
if (checkStatus.data.length <= 0) {
layer.msg('请先选择数据');
return false;
}
let selected = checkStatus.data;
let ids = [];
let url = $($(this).context).data('href')
$.each(selected, function (index, val) {
ids.push(val.id);
})
del(url, ids);
return false;
}
if (layEvent === 'refresh') {
insTb.reload();
return false;
}
if (layEvent === 'add') {
let url = $($(this).context).data('href')
let title = $($(this).context).data('title')
openLayer(url, title);
return false;
}
});
//删除
function del(url, ids) {
let index = layer.confirm('确认删除吗?', {
btn: ['确认', '取消'], //按钮
title: '操作提示',
}, function () {
$.post(url, {ids: ids}, function (res) {
layer.msg(res.msg)
if (res.code === 0) {
insTb.reload();
}
})
}, function () {
layer.close(index)
return false;
});
}
//监听工具条
table.on('tool(table-container)', function (obj) {
let data = obj.data;
let layEvent = obj.event;
let url = $($(this).context).data('href');
let title = $($(this).context).data('title');
if (layEvent === 'del') {
let ids = [data.id];
del(url, ids);
return false;
}
if (layEvent === 'edit') {
openLayer(url, title);
return false;
}
});
}
/*** index end ***/
if ($('.location-rule-page').length > 0) {
}
});

View File

@ -0,0 +1,155 @@
layui.use(['laytpl', 'table', 'jquery', 'form', 'miniTab', 'tree', 'xmSelect', 'laydate','upload'], function () {
let $ = layui.jquery,
layer = layui.layer,
upload = layui.upload;
let image_exts = $('#image_exts').data('exts') ? $('#image_exts').data('exts') : "jpg|png|gif|bmp|jpeg";//图片上传后缀
// 删除时间
$('body').on('click', '.upload-file-div-close', function () {
$(this).parent().remove()
});
// 根据input 刷新预览图片列表
function initPreviewList() {
let input = $('.upload-file-value');
if (input.length > 0) {
input.each(function () {
let that = $(this);
let fileList = that.val();
let fileArr = [];
let html = '';
if (fileList) {
fileArr = fileList.split(',');
}
if (fileArr.length > 0) {
$.each(fileArr, function (index, item) {
let ext = item.split('.');
src = getFileRequestUrl(item);
let aLink = getFileRequestUrl(item);
html += `<li class="layui-col-xs12 layui-col-md2 preview-li">
<a href="${aLink}" target="_blank" class="preview-li-img">
<img src="${src}" data-img="${item}">
</a>
<a href="javascript:;" class="layui-btn layui-btn-xs layui-btn-danger del-preview-img">
<i class="fa fa-trash-o"></i>
</a>
</li>`;
})
}
that.parents('.upload-file-div').find('.preview-list').html(html);
})
}
}
//渲染节点
function renderImgListNode(id) {
// 多个上传组件 多个实例
upload.render({
elem: '#ImgListNode-upload-btn-' + id
, url: '/manager/upload/image'
, auto: true
, field: 'image_image'
, accept: 'images'
, acceptMime: 'images/*'
, exts: image_exts
, size: 50 * 1204
, number: 0
, multiple: false
, data: {}
, before: function (obj) {
layer.load(2);
}
, done: function (res, index, upload) { //每个文件提交一次触发一次。详见“请求成功的回调”
layer.closeAll('loading'); //关闭loading
let item = this.item;
let div = item.parents('.upload-file-div');
let existsNotice = item.data('notice-exists');//已存在文件是否提示 默认不提示
let callback = item.data('callback');//上传成功执行函数
if (callback) {
eval(callback);
}
// 200=已存在文件 0=新上传成功
if (res.code === 0 || res.code === 200) {
let inputValue = '';
inputValue += res.data.src;
$(div).find('.upload-file-value').val(inputValue);
initPreviewList();
if (existsNotice && res.code === 200) {
layer.alert(res.msg);
}
} else {
layer.msg(res.msg);
}
}
});
}
function setImgListNode(key){
let html = ` <div class="layui-row upload-file-div">
<div class=" layui-col-xs12 layui-col-md4">
<input class="layui-input upload-file-value" name="winner[${key}][avatar]" type="text" value="">
<div class="layui-form-mid layui-word-aux">中奖者头像请上传合适尺寸</div>
</div>
<div class="layui-col-xs12 layui-col-md3">
<span>
<button type="button" class="layui-btn layui-btn-danger " id="ImgListNode-upload-btn-${key}">
<i class="fa fa-upload"></i>
</button>
</span>
<span><button type="button" class="layui-btn layui-btn-primary upload-choose-btn"
data-url="/manager/attachment/image"
data-type="image"
data-multiple="false">
<i class="fa fa-list"></i>
</button></span>
</div>
<ul class="layui-row layui-col-xs12 layui-col-md9 preview-list layui-col-space5"></ul>
<div class="layui-row">
<div class="layui-inline">
<label class="layui-form-label">奖品标题</label>
<div class="layui-input-inline">
<input type="text" name="winner[${key}][prize_title]" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">中奖者昵称</label>
<div class="layui-input-inline">
<input type="text" name="winner[${key}][winner_title]" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">排序</label>
<div class="layui-input-inline">
<input type="number" name="winner[${key}][sort]" class="layui-input">
</div>
</div>
</div>
<button class="layui-btn upload-file-div-close">删除</button>
</div>`;
$("#img_list").append(html);
renderImgListNode(key);
ImgListNodeKey++;
}
$(function () {
if(addImgListNode == true){
//添加第一个节点
setImgListNode(ImgListNodeKey);
}
//增加节点绑定
$("#addrImgListNode").on("click",function () {
setImgListNode(ImgListNodeKey)
});
initPreviewList();
})
});

View File

@ -12,7 +12,7 @@ layui.use(['laytpl', 'table', 'jquery', 'form', 'miniTab', 'tree', 'xmSelect', '
let menuList = parentMenu.data('menu') ? parentMenu.data('menu') : []; let menuList = parentMenu.data('menu') ? parentMenu.data('menu') : [];
let showList = parentMenu.data('show') ? parentMenu.data('show') : [];//各栏目 可展示字段列表 let showList = parentMenu.data('show') ? parentMenu.data('show') : [];//各栏目 可展示字段列表
let image_exts = $('#image_exts').data('exts') ? parentMenu.data('exts') : "jpg|png|gif|bmp|jpeg";//图片上传后缀 let image_exts = $('#image_exts').data('exts') ? $('#image_exts').data('exts') : "jpg|png|gif|bmp|jpeg";//图片上传后缀
xmSelect.render({ xmSelect.render({
el: '#parent-menu', el: '#parent-menu',
paging: false, paging: false,

View File

@ -0,0 +1,148 @@
{layout name="manager/layout" /}
<style>
.upload-file-div{position: relative}
.upload-file-div-close{position: absolute;right: 0;top: 0;}
</style>
<div id="image_exts" data-exts="{:str_replace(',','|',$uploadConfig['img_type'])}"></div>
<div class="layuimini-container location-operate-page">
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">名称</label>
<div class="layui-input-block">
<input type="text" name="name" lay-verify="required" lay-reqtext="名称不能为空" placeholder="请输入名称" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-row ">
<label class="layui-form-label">封面:</label>
<div class="layui-inline layui-col-xs12 layui-col-md8">
<div class="layui-row upload-file-div">
<div class=" layui-col-xs12 layui-col-md8">
<input class="layui-input upload-file-value" name="cover" type="text" value="">
<div class="layui-form-mid layui-word-aux">图片尺寸:请上传合适尺寸</div>
</div>
<div class="layui-col-xs12 layui-col-md3">
<span>
<button type="button" class="layui-btn layui-btn-danger upload-btn">
<i class="fa fa-upload"></i> 上传
</button>
</span>
<span><button type="button" class="layui-btn layui-btn-primary upload-choose-btn"
data-url="/manager/attachment/image" data-type="image"
data-multiple="false"><i class="fa fa-list"></i> 选择</button></span>
</div>
<ul class="layui-row layui-col-xs12 layui-col-md9 preview-list layui-col-space5"></ul>
</div>
</div>
</div>
<!-- 抽奖说明 -->
<div class="layui-form-item layui-form-text field-div current-field-summary">
<label class="layui-form-label">抽奖说明</label>
<div class="layui-input-block editor-text">
<!-- <div class="editor"></div>-->
<textarea name="explain" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">微信客服</label>
<div class="layui-input-block">
<input type="text" name="wechat_waiter_number" placeholder="请输入名称" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-row ">
<label class="layui-form-label">微信客服头像:</label>
<div class="layui-inline layui-col-xs12 layui-col-md8">
<div class="layui-row upload-file-div">
<div class=" layui-col-xs12 layui-col-md8">
<input class="layui-input upload-file-value" name="wechat_waiter_avatar" type="text" value="">
<div class="layui-form-mid layui-word-aux">图片尺寸:请上传合适尺寸</div>
</div>
<div class="layui-col-xs12 layui-col-md3">
<span>
<button type="button" class="layui-btn layui-btn-danger upload-btn">
<i class="fa fa-upload"></i> 上传
</button>
</span>
<span><button type="button" class="layui-btn layui-btn-primary upload-choose-btn"
data-url="/manager/attachment/image" data-type="image"
data-multiple="false"><i class="fa fa-list"></i> 选择</button></span>
</div>
<ul class="layui-row layui-col-xs12 layui-col-md9 preview-list layui-col-space5"></ul>
</div>
</div>
</div>
<div class="layui-form-item layui-row ">
<label class="layui-form-label">参与者头像列表:</label>
<div class="layui-inline layui-col-xs12 layui-col-md8">
<div class="layui-row upload-file-div">
<div class=" layui-col-xs12 layui-col-md8">
<input class="layui-input upload-file-value" name="wechat_waiter_avatar" type="text"
value="">
<div class="layui-form-mid layui-word-aux">图片尺寸:请上传合适尺寸</div>
</div>
<div class="layui-col-xs12 layui-col-md3">
<span>
<button type="button" class="layui-btn layui-btn-danger upload-btn"
data-multiple="true">
<i class="fa fa-upload"></i> 上传
</button>
</span>
<span><button type="button" class="layui-btn layui-btn-primary upload-choose-btn"
data-url="/manager/attachment/image" data-type="image"
data-multiple="true"
><i class="fa fa-list"></i> 选择</button></span>
</div>
<ul class="layui-row layui-col-xs12 layui-col-md9 preview-list layui-col-space5"></ul>
</div>
</div>
</div>
<div class="layui-form-item " >
<label class="layui-form-label">中奖者:</label>
<div class="layui-inline layui-col-md8 " >
<div id="img_list">
</div>
<div class="layui-input-block">
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
<legend> <button class="layui-btn " id="addrImgListNode">增加一个节点</button></legend>
</fieldset>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" data-url="/manager/activity-template/add" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
</div>
<script>
addImgListNode=true;
var ImgListNodeKey = {$maxKey??0};//初始值
</script>
<script src="__MANAGER__/js/add_activity.js?v={:mt_rand()}"></script>

View File

@ -0,0 +1,19 @@
{layout name="manager/layout" /}
<div class="layuimini-container location-operate-page">
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">名称</label>
<div class="layui-input-block">
<input type="text" name="name" lay-verify="required" value="{$item.name ?? ''}" lay-reqtext="名称不能为空" placeholder="请输入名称" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" data-url="/manager/activity-template/edit?id={$item.id}" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,27 @@
{layout name="manager/layout" /}
<div class="layuimini-container location-index-page">
<div class="layuimini-main">
<div>
<table id="table-container" class="layui-table" data-url="/manager/activity-template" lay-filter="table-container"></table>
</div>
</div>
</div>
<!-- 隐藏列 -->
<!-- 编辑单元格提交url -->
<input type="hidden" id="row-modify" data-url="/manager/activity-template/modify">
<!-- 操作列 -->
<script type="text/html" id="row-operate">
<a class="layui-btn layui-btn-primary layui-btn-xs" data-href="/manager/activity-template/edit.html?id={{d.id}}" data-title="编辑" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" data-href="/manager/activity-template/del.html" lay-event="del">删除</a>
</script>
<!-- toolbar -->
<script type="text/html" id="toolbar-tpl">
<a class="layui-btn layui-btn-sm layui-btn-sm" data-table-refresh lay-event="refresh"><i class="fa fa-refresh"></i></a>
<a class="layui-btn layui-btn-normal layui-btn-sm" data-href="/manager/activity-template/add.html" data-title="添加" lay-event="add"><i class="fa fa-plus"></i> 添加</a>
<a class="layui-btn layui-btn-danger layui-btn-sm" data-href="/manager/activity-template/del.html" lay-event="del"><i class="fa fa-trash-o"></i> 删除</a>
</script>
<script src="__MANAGER__/js/activity_template.js?v={:mt_rand()}"></script>

View File

@ -0,0 +1,19 @@
{layout name="manager/layout" /}
<div class="layuimini-container location-operate-page">
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">名称</label>
<div class="layui-input-block">
<input type="text" name="name" lay-verify="required" lay-reqtext="名称不能为空" placeholder="请输入名称" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" data-url="/manager/activity-template-type/add" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
{layout name="manager/layout" /}
<div class="layuimini-container location-operate-page">
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">名称</label>
<div class="layui-input-block">
<input type="text" name="name" lay-verify="required" value="{$item.name ?? ''}" lay-reqtext="名称不能为空" placeholder="请输入名称" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" data-url="/manager/activity-template-type/edit?id={$item.id}" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,27 @@
{layout name="manager/layout" /}
<div class="layuimini-container location-index-page">
<div class="layuimini-main">
<div>
<table id="table-container" class="layui-table" data-url="/manager/activity-template-type" lay-filter="table-container"></table>
</div>
</div>
</div>
<!-- 隐藏列 -->
<!-- 编辑单元格提交url -->
<input type="hidden" id="row-modify" data-url="/manager/activity-template-type/modify">
<!-- 操作列 -->
<script type="text/html" id="row-operate">
<a class="layui-btn layui-btn-primary layui-btn-xs" data-href="/manager/activity-template-type/edit.html?id={{d.id}}" data-title="编辑" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" data-href="/manager/activity-template-type/del.html" lay-event="del">删除</a>
</script>
<!-- toolbar -->
<script type="text/html" id="toolbar-tpl">
<a class="layui-btn layui-btn-sm layui-btn-sm" data-table-refresh lay-event="refresh"><i class="fa fa-refresh"></i></a>
<a class="layui-btn layui-btn-normal layui-btn-sm" data-href="/manager/activity-template-type/add.html" data-title="添加" lay-event="add"><i class="fa fa-plus"></i> 添加</a>
<a class="layui-btn layui-btn-danger layui-btn-sm" data-href="/manager/activity-template-type/del.html" lay-event="del"><i class="fa fa-trash-o"></i> 删除</a>
</script>
<script src="__MANAGER__/js/activity_template_type.js?v={:mt_rand()}"></script>

View File

@ -296,6 +296,7 @@
</div> </div>
</div> </div>
@ -307,7 +308,6 @@
</div> </div>
</div> </div>
<div class="addImgListNode"></div>
<script> <script>
addImgListNode=true; addImgListNode=true;
var ImgListNodeKey = {$maxKey??0};//初始值 var ImgListNodeKey = {$maxKey??0};//初始值

View File

@ -1,75 +0,0 @@
{layout name="manager/layout" /}
<div class="layuimini-container location-operate-page">
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<!-- 经纬度 -->
<div class="layui-form-item">
<label class="layui-form-label required">经纬度</label>
<div class="layui-input-block">
<div class="layui-input-inline">
<input type="number" name="lng" value="{$item.lng ?? ''}" id="longitude" placeholder="请填写经度" lay-reqtext="经度不能为空" lay-verify="required" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="number" name="lat" value="{$item.lat ?? ''}" id="latitude" placeholder="请填写纬度" lay-reqtext="纬度不能为空" lay-verify="required" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline"><button class="layui-btn-normal layui-btn" id="locationBtn">定位</button></div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" data-url="/manager/map/index" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
</div>
<script src="__STATIC__/common/jquery-3.4.1.min.js"></script>
<script>
layui.use(['layer','form','jquery','location'],function(){
let $ = layui.jquery;
let form = layui.form;
let location = layui.location;
let lng = $('#longitude').val();
let lat = $('#latitude').val();
lng = lng.length > 0 ? lng : '116.404';
lat = lat.length > 0 ? lat : '39.915';
let locationData = {lng: lng,lat: lat};
location.render("#locationBtn",{
type: 1,
apiType: "gaodeMap",
coordinate: "gaodeMap",
mapType: 0,
zoom: 15,
title: '区域定位',
init: function(){
// 打开地图时 延迟一定时间搜索
$('body').on('click', '#locationBtn', function () {
let address = $("input[name='address']").val();
setTimeout(function () {
$('#ew-map-select-input-search').val(address).trigger('input');
}, 1500)
})
return {longitude: $("#longitude").val()?$("#longitude").val():locationData.lng,latitude: $("#latitude").val()?$("#latitude").val():locationData.lat};
},
success: function (data) {
$("#longitude").val(data.lng);
$("#latitude").val(data.lat);
},
onClickTip: function (data) {
console.log(data);
}
});
});
</script>