This commit is contained in:
2025-10-29 15:32:26 +08:00
parent d90614805b
commit b7462657cd
78921 changed files with 2753938 additions and 71 deletions

View File

@@ -0,0 +1,88 @@
<?php
/**
*/
namespace addon\form\api\controller;
use app\api\controller\BaseApi;
use addon\form\model\Form as FormModel;
use app\model\goods\Goods;
class Form extends BaseApi
{
/**
* 获取商品表单数据
* @return false|string
*/
public function goodsForm()
{
if (!addon_is_exit('form', $this->site_id)) return $this->response( $this->success([]) );
$goods_id = $this->params['goods_id'] ?? 0;
$condition = [
['g.site_id', '=', $this->site_id ],
['g.goods_id', '=', $goods_id ],
['g.form_id', '>', 0 ],
['f.is_use', '=', 1 ]
];
$data = (new Goods())->getGoodsInfo($condition, 'f.json_data', 'g', [ ['form f', 'g.form_id = f.id', 'left'] ])['data'];
if (!empty($data)) {
return $this->response( $this->success( json_decode($data['json_data'], true) ) );
}
return $this->response( $this->success($data) );
}
/**
* 获取表单信息
* @return false|string
*/
public function info(){
$form_id = $this->params['form_id'] ?? 0;
$uniacid = $this->params['uniacid'] ?? 0;
$condition = [
['site_id', '=', $uniacid ],
['id', '=', $form_id ],
['is_use', '=', 1 ],
['form_type', '=', 'custom' ]
];
$data = (new FormModel())->getFormInfo($condition, 'json_data,form_name');
file_put_contents(__DIR__ . '/debug.txt', var_export($data,true));
if (!empty($data['data'])) {
$data['data']['json_data'] = json_decode($data['data']['json_data'], true);
// $data['data']['title'] = model('form')->getValue(['id'=>$form_id]);
}
return $this->response($data);
}
/**
* 添加表单数据
* @return false|string
*/
public function create(){
// $token = $this->checkToken();
// if ($token['code'] < 0) return $this->response($token);
$form_id = $this->params['form_id'] ?? 0;
$form_data = $this->params[ 'form_data' ] ?? '[]';
$uniacid = $this->params['uniacid'] ?? 0;
$data = [
'site_id' => $uniacid,
'form_id' => $form_id,
// 'member_id' => $this->member_id,
'relation_id' => 0,
'form_data' => json_decode($form_data, true),
'scene' => 'custom'
];
$res = (new FormModel())->addFormData($data);
return $this->response($res);
}
}

View File

@@ -0,0 +1,17 @@
<?php
return [
'REQUEST_FENXIAO_NAME' => -1,
'REQUEST_QRCODE_PARAM' => -1,
'REQUEST_MONEY' => -1,
'REQUEST_FENXIAO_ORDER_ID' => -1,
'REQUEST_SOURCE_MEMBER' => -1,
'REQUEST_LEVEL_ID' => -1,
'MEMBER_NOT_IS_FENXIAO' => -1,
'FENXIAO_NOT_EXIST' => -1,
'REQUEST_FENXIAO_ID' => -1,
'REQUEST_COLLECT_ID' => -1,
'GOODS_COLLECT_IS_EXIST' => -1,
'APPLYING' => 1,
'ALREADY_DISTRIBUTOR' => 1
];

View File

@@ -0,0 +1,4 @@
<?php
return [
];

View File

@@ -0,0 +1,17 @@
<?php
return [
'REQUEST_FENXIAO_NAME' => '缺少参数fenxiao_name',
'REQUEST_QRCODE_PARAM' => '缺少参数qrcode_param',
'REQUEST_MONEY' => '缺少参数money',
'REQUEST_FENXIAO_ORDER_ID' => '缺少参数fenxiao_order_id',
'REQUEST_SOURCE_MEMBER' => '缺少参数source_member',
'REQUEST_LEVEL_ID' => '缺少参数level_id',
'MEMBER_NOT_IS_FENXIAO' => '该会员还不是分销商',
'FENXIAO_NOT_EXIST' => '分销商不存在',
'REQUEST_FENXIAO_ID' => '缺少参数fenxiao_id',
'REQUEST_COLLECT_ID' => '缺少参数collect_id',
'GOODS_COLLECT_IS_EXIST' => '已关注该分销商品',
'APPLYING' => '审核中',
'ALREADY_DISTRIBUTOR' => '已是分销商'
];

View File

@@ -0,0 +1,47 @@
<?php
/**
*/
return [
// 自定义模板页面类型,格式:[ 'title' => '页面类型名称', 'name' => '页面标识', 'path' => '页面路径', 'value' => '页面数据json格式' ]
'template' => [],
// 后台自定义组件——装修
'util' => [],
// 自定义页面路径
'link' => [
[
'name' => 'DIY_FORM',
'title' => '自定义表单',
'parent' => 'INTERACTION_PROMOTION',
'wap_url' => '',
'web_url' => '',
'sort' => 4
]
],
// 自定义图标库
'icon_library' => [],
// uni-app 组件,格式:[ 'name' => '组件名称/文件夹名称', 'path' => '文件路径/目录路径' ]多个逗号隔开自定义组件名称前缀必须是diy-,也可以引用第三方组件
'component' => [],
// uni-app 页面,多个逗号隔开
'pages' => [],
// 模板信息,格式:'title' => '模板名称', 'name' => '模板标识', 'cover' => '模板封面图', 'preview' => '模板预览图', 'desc' => '模板描述'
'info' => [],
// 主题风格配色格式可以自由定义扩展【在uni-app中通过this.themeStyle... 获取定义的颜色字段例如this.themeStyle.main_color】
'theme' => [],
// 自定义页面数据,格式:[ 'title' => '页面名称', 'name' => "页面标识", 'value' => [页面数据json格式] ]
'data' => []
];

View File

@@ -0,0 +1,23 @@
<?php
// 事件定义文件
return [
'bind' => [
],
'listen' => [
//展示活动
'ShowPromotion' => [
'addon\form\event\ShowPromotion',
],
'OrderPayment' => [
'addon\form\event\OrderPayment',
],
'OrderCreateAfter' => [
'addon\form\event\OrderCreateAfter',
]
],
'subscribe' => [
],
];

View File

@@ -0,0 +1,21 @@
<?php
/**
*/
return [
'name' => 'form',
'title' => '系统表单',
'description' => '表单自定义信息收集',
'type' => 'system', //插件类型 system :系统插件(自动安装), business:业务插件 promotion:营销插件 tool:工具插件
'status' => 1,
'author' => '',
'version' => '5.3.1',
'version_no' => '525231212001',
'content' => '',
];

View File

@@ -0,0 +1,80 @@
<?php
// +----------------------------------------------------------------------
// | 平台端菜单设置
// +----------------------------------------------------------------------
return [
[
'name' => 'SYSTEM_FORM',
'title' => '系统表单',
'url' => 'form://shop/form/lists',
'parent' => 'PROMOTION_TOOL',
'is_show' => 1,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_select' => '',
'sort' => 1,
'child_list' => [
[
'name' => 'FORM_ADD',
'title' => '添加表单',
'url' => 'form://shop/form/addform',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
],
[
'name' => 'FORM_EDIT',
'title' => '编辑表单',
'url' => 'form://shop/form/editform',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
],
[
'name' => 'FORM_DELETE',
'title' => '删除表单',
'url' => 'form://shop/form/deleteform',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
],
[
'name' => 'FORM_IS_USE',
'title' => '表单是否启用',
'url' => 'form://shop/form/editisuse',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
],
[
'name' => 'FORM_DATA',
'title' => '表单数据',
'url' => 'form://shop/form/formdata',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
],
[
'name' => 'FORM_DATA_EXPORT',
'title' => '表单数据详情',
'url' => 'form://shop/form/exportform',
'is_show' => 0,
'is_control' => 1,
'is_icon' => 0,
'picture' => '',
'picture_selected' => '',
],
]
],
];

View File

@@ -0,0 +1,27 @@
<?php
/**
*/
namespace addon\form\event;
/**
* 应用安装
*/
class Install
{
/**
* 执行安装
*/
public function handle()
{
return success();
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
*/
namespace addon\form\event;
use addon\form\model\Form;
/**
* 订单待付款
*/
class OrderCreateAfter
{
/**
* @return multitype:number unknown
*/
public function handle($data)
{
/** @var \app\model\order\OrderCreate $order_object */
$order_object = $data['order_object'];
$form_data = $order_object->param['form_data'] ?? [];
if ($form_data) {
$site_id = $order_object->site_id;
$order_id = $order_object->order_id;
$member_id = $order_object->member_id;
// 添加订单表单
$form = new Form();
if (isset($form_data[ 'form_data' ])) {
$res = $form->addFormData([
'site_id' => $site_id,
'form_id' => $form_data[ 'form_id' ],
'member_id' => $member_id,
'relation_id' => $order_id,
'form_data' => $form_data[ 'form_data' ],
'scene' => 'order'
]);
if ($res[ 'code' ] != 0) return $res;
}
// 添加商品表单
$goods_form = $form_data[ 'goods_form' ] ?? [];
if ($goods_form) {
//查询订单项
// $goods_list = array_column($order_object->goods_list, null, 'sku_id');
$order_goods_list = array_column($order_object->getOrderGoodsList(), null, 'sku_id');
foreach ($goods_form as $sku_id => $form_item) {
// $goods_item = $goods_list[ $sku_id ] ?? [];
$order_goods_item = $order_goods_list[$sku_id] ?? [];
$res = $form->addFormData([
'site_id' => $site_id,
'form_id' => $form_item[ 'form_id' ],
'member_id' => $member_id,
'relation_id' => $order_goods_item[ 'order_goods_id' ] ?? 0,
'form_data' => $form_item[ 'form_data' ],
'scene' => 'goods'
]);
if ($res[ 'code' ] != 0) return $res;
}
}
}
return success();
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
*/
namespace addon\form\event;
use addon\form\model\Form;
use app\model\goods\Goods;
/**
* 订单待付款
*/
class OrderPayment
{
/**
* @param $data
* @return array
*/
public function handle($data)
{
/** @var \app\model\order\OrderCreate $order_object */
$order_object = $data['order_object'];
$site_id = $order_object->site_id;
$form_model = new Form();
$info = $form_model->getFormInfo([ [ 'site_id', '=', $site_id], [ 'is_use', '=', 1 ], [ 'form_type', '=', 'order' ] ], 'id,json_data,form_name')[ 'data' ] ?? [];
if (!empty($info)) {
$info[ 'json_data' ] = json_decode($info[ 'json_data' ], true);
//todo 查询用法
$order_object->system_form = $info;
}
$form_ids = array_filter(array_unique(array_column($order_object->goods_list, 'form_id')));
if($form_ids){
$form_list = $form_model->getFormList([ [ 'site_id', '=', $site_id], [ 'is_use', '=', 1 ] , ['id', 'in', $form_ids]], '', 'id, json_data')['data'] ?? [];
$form_array = array_column($form_list, null, 'id');
foreach($order_object->goods_list as &$goods_item){
$item_form = $form_array[$goods_item['form_id'] ?? 0] ?? [];
if($item_form){
$item_form['json_data'] = json_decode($item_form[ 'json_data' ], true);
$goods_item[ 'goods_form' ] = $item_form;
}
}
}
return true;
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
*/
namespace addon\form\event;
/**
* 活动展示
*/
class ShowPromotion
{
/**
* 活动展示
* @return array
*/
public function handle()
{
$data = [
'shop' => [
[
//插件名称
'name' => 'form',
//店铺端展示分类 shop:营销活动 member:互动营销
'show_type' => 'tool',
//展示主题
'title' => '系统表单',
//展示介绍
'description' => '帮助商家快速收集客户信息',
//展示图标
'icon' => 'addon/form/icon.png',
//跳转链接
'url' => 'form://shop/form/lists',
]
]
];
return $data;
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
*/
namespace addon\form\event;
/**
* 应用卸载
*/
class UnInstall
{
/**
* 执行卸载
*/
public function handle()
{
return success();
}
}

BIN
src/addon/form/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,493 @@
<?php
/**
*/
namespace addon\form\model;
use app\model\BaseModel;
use think\facade\Cache;
/**
* 系统表单
*/
class Form extends BaseModel
{
public $form_type = [
'order' => [
'type' => 'order',
'name' => '统一下单',
'preview_img' => 'addon/form/shop/view/public/img/preview/order.png',
'head_img' => 'addon/form/shop/view/public/img/head/order.png'
],
'goods' => [
'type' => 'goods',
'name' => '商品表单',
'preview_img' => 'addon/form/shop/view/public/img/preview/goods.png',
'head_img' => 'addon/form/shop/view/public/img/head/goods.png'
],
'custom' => [
'type' => 'custom',
'name' => '自定义表单',
'preview_img' => 'addon/form/shop/view/public/img/preview/custom.png',
'head_img' => 'addon/form/shop/view/public/img/head/custom.png'
]
];
/**
* 表单组件
*/
const FORM_COMPONENT = [
'ONE_LINE_TEXT' => [
'name' => 'ONE_LINE_TEXT',
'title' => '单行文本',
'type' => 'SYSTEM',
'controller' => 'Text',
'value' => [
'title' => '单行文本框',
'placeholder' => '请输入提示语',
'default' => '',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/on_line_text.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/on_line_text_selected.png'
],
'MANY_LINE_TEXT' => [
'name' => 'MANY_LINE_TEXT',
'title' => '多行文本',
'type' => 'SYSTEM',
'controller' => 'Textarea',
'value' => [
'title' => '多行文本',
'placeholder' => '请输入提示语',
'default' => '',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/many_line_text.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/many_line_text_selected.png'
],
'ID_CARD' => [
'name' => 'ID_CARD',
'title' => '身份证号码',
'type' => 'SYSTEM',
'controller' => 'Text',
'value' => [
'title' => '身份证号码',
'placeholder' => '请输入身份证号码',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/id_card.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/id_card_selected.png'
],
'SELECT' => [
'name' => 'SELECT',
'title' => '下拉框',
'type' => 'SYSTEM',
'controller' => 'Select',
'value' => [
'title' => '下拉框',
'options' => [
'选项一',
'选项二'
],
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/select.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/select_selected.png'
],
'CHECKBOX' => [
'name' => 'CHECKBOX',
'title' => '多选框',
'type' => 'SYSTEM',
'controller' => 'Checkbox',
'value' => [
'title' => '多选框',
'options' => [
'选项一',
'选项二'
],
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/checkbox.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/checkbox_selected.png'
],
'RADIO' => [
'name' => 'RADIO',
'title' => '单选框',
'type' => 'SYSTEM',
'controller' => 'Radio',
'value' => [
'title' => '单选框',
'options' => [
'选项一',
'选项二'
],
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/radio.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/radio_selected.png'
],
'IMG' => [
'name' => 'IMG',
'title' => '图片',
'type' => 'SYSTEM',
'controller' => 'Img',
'value' => [
'title' => '图片',
'max_count' => 3,
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/img.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/img_selected.png'
],
'DATE' => [
'name' => 'DATE',
'title' => '日期',
'type' => 'SYSTEM',
'controller' => 'Date',
'value' => [
'title' => '日期',
'placeholder' => '请输入提示语',
'is_show_default' => true,
'is_current' => true,
'default' => '',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/date.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/date_selected.png'
],
'DATE_LIMIT' => [
'name' => 'DATE_LIMIT',
'title' => '日期范围',
'type' => 'SYSTEM',
'controller' => 'Datelimit',
'value' => [
'title' => '日期范围',
'placeholder_start' => '请输入起始日期提示语',
'placeholder_end' => '请输入结束日期提示语',
'is_show_default_start' => true,
'is_show_default_end' => true,
'is_current_start' => true,
'is_current_end' => true,
'default_start' => '',
'default_end' => '',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/date_limit.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/date_limit_selected.png'
],
'TIME' => [
'name' => 'TIME',
'title' => '时间',
'type' => 'SYSTEM',
'controller' => 'Time',
'value' => [
'title' => '时间',
'placeholder' => '请输入提示语',
'is_show_default' => true,
'is_current' => true,
'default' => '',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/time.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/time_selected.png'
],
'TIME_LIMIT' => [
'name' => 'TIME_LIMIT',
'title' => '时间范围',
'type' => 'SYSTEM',
'controller' => 'Timelimit',
'value' => [
'title' => '时间范围',
'placeholder_start' => '请输入起始时间提示语',
'placeholder_end' => '请输入结束时间提示语',
'is_show_default_start' => true,
'is_show_default_end' => true,
'is_current_start' => true,
'is_current_end' => true,
'default_start' => '',
'default_end' => '',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/time_limit.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/time_limit_selected.png'
],
'CITY' => [
'name' => 'CITY',
'title' => '城市',
'type' => 'SYSTEM',
'controller' => 'City',
'value' => [
'title' => '城市',
'placeholder' => '请输入提示语',
'default_type' => 1,
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/city.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/city_selected.png'
],
'MOBILE' => [
'name' => 'MOBILE',
'title' => '手机号码',
'type' => 'SYSTEM',
'controller' => 'Text',
'value' => [
'title' => '手机号码',
'placeholder' => '请输入手机号码',
'required' => true
],
'sort' => '10000',
'support_diy_view' => '',
'max_count' => 0,
'is_delete' => 0,
'icon' => 'addon/form/shop/view/public/img/icon/mobile.png',
'icon_selected' => 'addon/form/shop/view/public/img/icon/mobile_selected.png'
],
];
/**
* 添加自定义模板
* @param $data
* @return array
*/
public function addForm($data)
{
$res = model('form')->add($data);
if ($res) {
Cache::tag('form')->clear();
return $this->success($res);
} else {
return $this->error($res);
}
}
/**
* 修改自定义模板
* @param array $data
* @param array $condition
* @return array
*/
public function editForm($data, $condition)
{
$res = model('form')->update($data, $condition);
if ($res) {
Cache::tag('form')->clear();
return $this->success($res);
} else {
return $this->error($res);
}
}
/**
* 获取自定义模板信息
* @param array $condition
* @param string $field
* @return array
*/
public function getFormInfo($condition = [], $field = '*', $alias = 'a', $join = [])
{
$info = model('form')->getInfo($condition, $field, $alias, $join);
return $this->success($info);
}
/**
* 删除表单
* @param array $condition
* @return array
*/
public function deleteForm($id, $site_id)
{
model('form')->startTrans();
$res = model('form')->delete([ [ 'id', '=', $id ], [ 'site_id', '=', $site_id ] ]);
if ($res) {
model('form_data')->delete([ [ 'form_id', '=', $id ], [ 'site_id', '=', $site_id ] ]);
model('form')->commit();
Cache::tag('form')->clear();
return $this->success($res);
} else {
model('form')->rollback();
return $this->error($res);
}
}
/**
* 获取表单分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getFormPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*')
{
$list = model('form')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
/**
* 获取表单列表
* @param array $condition
* @param string $order
* @param string $field
* @return array
*/
public function getFormList($condition = [], $order = 'id desc', $field = '*')
{
$data = json_encode([ $condition, $field, $order]);
$cache = Cache::get('form_getFormList_' . $data);
if (!empty($cache)) {
return $this->success($cache);
}
$list = model('form')->getList($condition, $field, $order);
Cache::tag('form')->set('form_getFormList_' . $data, $list);
return $this->success($list);
}
/**
* 查询订单数据并导出
* @param $condition
*/
public function export($param)
{
$form_info = model('form')->getInfo([ [ 'id', '=', $param[ 'id' ] ], [ 'site_id', '=', $param[ 'site_id' ] ] ], 'form_name,id,json_data');
if (empty($form_info)) return $this->error('', '未获取到表单信息');
$form_info[ 'json_data' ] = json_decode($form_info[ 'json_data' ], true);
$form_data_list = model('form_data')->getList([ [ 'fd.form_id', '=', $form_info[ 'id' ] ] ], 'fd.form_data,fd.create_time,m.nickname', 'id desc', 'fd', [ [ 'member m', 'm.member_id = fd.member_id', 'left' ] ]);
if (empty($form_data_list)) return $this->error('', '表单没有可导出的数据');
$phpExcel = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$phpExcel->getProperties()->setTitle('表单数据');
$phpExcel->getProperties()->setSubject('表单数据');
$sheet = $phpExcel->getActiveSheet();
// 创建表头
foreach ($form_info[ 'json_data' ] as $k => $form_item) {
$sheet->getCellByColumnAndRow(( $k + 1 ), 1)->setValue($form_item[ 'value' ][ 'title' ]);
}
$sheet->getCellByColumnAndRow(( count($form_info[ 'json_data' ]) + 1 ), 1)->setValue('会员');
$sheet->getCellByColumnAndRow(( count($form_info[ 'json_data' ]) + 2 ), 1)->setValue('填写时间');
// 填充数据
foreach ($form_data_list as $data_k => $data_item) {
foreach ($form_info[ 'json_data' ] as $k => $form_item) {
$form_data = array_column(json_decode($data_item[ 'form_data' ], true), null, 'id');
if (!empty($form_data[ $form_item[ 'id' ] ])) {
$sheet->getCellByColumnAndRow(( $k + 1 ), ( $data_k + 2 ))->setValue($form_data[ $form_item[ 'id' ] ][ 'val' ] ?? '');
}
}
$sheet->getCellByColumnAndRow(( count($form_info[ 'json_data' ]) + 1 ), ( $data_k + 2 ))->setValue($data_item[ 'nickname' ] ?: '');
$sheet->getCellByColumnAndRow(( count($form_info[ 'json_data' ]) + 2 ), ( $data_k + 2 ))->setValue(time_to_date($data_item[ 'create_time' ]));
}
$objWriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($phpExcel, 'Xlsx');
$file = date('Y年m月d日-' . $form_info[ 'form_name' ] . '数据导出', time()) . '.xlsx';
$objWriter->save($file);
header('Content-type:application/octet-stream');
$filename = basename($file);
header('Content-Disposition:attachment;filename = ' . $filename);
header('Accept-ranges:bytes');
header('Accept-length:' . filesize($file));
readfile($file);
unlink($file);
exit;
}
/**
* 添加表单数据
* @param $param
*/
public function addFormData($param)
{
$info = model('form')->getInfo([ [ 'id', '=', $param[ 'form_id' ] ], [ 'site_id', '=', $param[ 'site_id' ] ] ]);
if (empty($info)) return $this->error('', '该表单不存在');
if (!$info[ 'is_use' ]) return $this->error('', '该表单未启用');
$id = model('form_data')->add([
'site_id' => $param[ 'site_id' ],
'form_id' => $param[ 'form_id' ],
'member_id' => 0,
'relation_id' => $param[ 'relation_id' ],
'create_time' => time(),
'form_data' => json_encode($param[ 'form_data' ]),
'scene' => $param[ 'scene' ]
]);
return $this->success($id);
}
public function urlQrcode($page, $qrcode_param, $app_type, $site_id)
{
$params = [
'site_id' => $site_id,
'data' => $qrcode_param,
'page' => $page,
'promotion_type' => '',
'app_type' => $app_type,
'h5_path' => $page . '?id=' . $qrcode_param[ 'id' ],
'qrcode_path' => 'upload/qrcode/form',
'qrcode_name' => 'form_qrcode_' . $qrcode_param[ 'id' ] . '_' . $site_id
];
$solitaire = event('PromotionQrcode', $params, true);
return $this->success($solitaire);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
*/
namespace addon\form\model;
use app\model\BaseModel;
/**
* 表单数据
*/
class FormData extends BaseModel
{
/**
* 获取表单数据分页列表
* @param $condition
* @param $field
* @param $order
* @param $page
* @param $limit
* @param $alias
* @param $join
* @return array
*/
public function getFormDataPageList($condition, $field, $order, $page, $limit, $alias, $join)
{
$list = model('form_data')->pageList($condition, $field, $order, $page, $limit, $alias, $join);
return $this->success($list);
}
/**
* 查询表单数据
* @param array $where
* @param bool $field
* @param string $alias
* @param null $join
* @return array
*/
public function getFormDataInfo($where = [], $field = true, $alias = 'a', $join = null)
{
$info = model('form_data')->getInfo($where, $field, $alias, $join);
return $this->success($info);
}
/**
* 删除表单数据
* @param array $condition
* @return array
*/
public function deleteFormData($condition = [])
{
$res = model('form_data')->delete($condition);
if ($res) {
return $this->success($res);
} else {
return $this->error($res);
}
}
}

View File

@@ -0,0 +1,332 @@
<?php
/**
*/
namespace addon\form\shop\controller;
use addon\form\model\Form as FormModel;
use addon\form\model\FormData as FormDataModel;
use app\model\order\Order as OrderModel;
use app\shop\controller\BaseShop;
use think\App;
/**
* 分销订单
*/
class Form extends BaseShop
{
public function __construct(App $app = null)
{
$this->replace = [
'FORM_JS' => __ROOT__ . '/addon/form/shop/view/public/js',
'FORM_CSS' => __ROOT__ . '/addon/form/shop/view/public/css',
'FORM_IMG' => __ROOT__ . '/addon/form/shop/view/public/img'
];
parent::__construct($app);
}
/**
* 编辑添加系统表单
* @param $game_data
* @param $award_json
* @return array
*/
public function editForm()
{
$from_model = new FormModel();
if (request()->isJson()) {
$id = input('id', '');
$form_name = input('form_name', '');
$json_data = input('json_data', '');
$data = [
'form_name' => $form_name,
'json_data' => $json_data,
'modify_time' => time()
];
$res = $from_model->editForm($data, [ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ]);
return $res;
}
$id = input('id', '');
$info = $from_model->getFormInfo([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ]);
if (empty($info[ 'data' ])) $this->error('未获取到表单数据');
$this->assign('component', FormModel::FORM_COMPONENT);
$this->assign('info', $info[ 'data' ]);
$this->assign('form_type', ( new FormModel() )->form_type[ $info[ 'data' ][ 'form_type' ] ]);
return $this->fetch('form/edit');
}
/**
* 添加表单
* @return array|mixed
*/
public function addForm()
{
if (request()->isJson()) {
$form_name = input('form_name', '');
$json_data = input('json_data', '');
$form_type = input('form_type', 'order');
$data = [
'form_name' => $form_name,
'json_data' => $json_data,
'form_type' => $form_type,
'site_id' => $this->site_id,
'create_time' => time(),
'is_use' => $form_type != 'order' ? 1 : 0
];
$from_model = new FormModel();
$res = $from_model->addForm($data);
return $res;
}
$form_type = input('form_type', 'order');
$this->assign('component', FormModel::FORM_COMPONENT);
$this->assign('form_type', ( new FormModel() )->form_type[ $form_type ]);
return $this->fetch('form/edit');
}
/**
* 是否开启
* @param $game_data
* @param $award_json
* @return array
*/
public function editIsUse()
{
$from_model = new FormModel();
$is_use = input('is_use', '');
$id = input('id', '');
$form_type = input('form_type', '');
if (empty($is_use) && empty($id)) {
$this->error('id和is_use不可为空');
}
//启用之前先把该类型的全都不启用
if ($form_type == 'order') {
$from_model->editForm([ 'is_use' => 0 ], [ [ 'form_type', '=', 'order' ], [ 'site_id', '=', $this->site_id ] ]);
}
$data = [
'is_use' => $is_use
];
$res = $from_model->editForm($data, [ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ]);
return $res;
}
/**
* 删除数据
* @param $game_data
* @param $award_json
* @return array
*/
public function deleteForm()
{
$id = input('id', '');
if (empty($id)) {
$this->error('id不可为空');
}
$from_model = new FormModel();
$res = $from_model->deleteForm($id, $this->site_id);
return $res;
}
/**
* 表单列表
* @param $game_data
* @param $award_json
* @return array
*/
public function lists()
{
if (request()->isJson()) {
$form_type = input('form_type', '');
$form_name = input('form_name', '');
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$is_use = input('is_use', '');
$condition = [];
$condition[] = [ 'site_id', '=', $this->site_id ];
if (!empty($form_type)) {
$condition[] = [ 'form_type', '=', $form_type ];
}
if (!empty($form_name)) {
$condition[] = [ 'form_name', 'like', '%' . $form_name . '%' ];
}
if (!empty($is_use)) {
$condition[] = [ 'is_use', '=', $is_use ];
}
$from_model = new FormModel();
$res = $from_model->getFormPageList($condition, $page, $page_size);
return $res;
}
$this->assign('form_type', ( new FormModel() )->form_type);
return $this->fetch('form/lists');
}
/**
* 导出表单列表
* @param $game_data
* @param $award_json
* @return array
*/
public function exportForm()
{
$id = input('id', '');
if (empty($id)) {
$this->error('id不可为空');
}
$from_model = new FormModel();
$res = $from_model->export([ 'id' => $id, 'site_id' => $this->site_id ]);
if (isset($res[ 'code' ]) && $res[ 'code' ] != 0) $this->error($res[ 'message' ]);
}
/**
* 获取详情
* @param $game_data
* @param $award_json
* @return array
*/
public function formInfo()
{
$id = input('id', '');
$condition[] = [ 'site_id', '=', $this->site_id ];
if (empty($id)) {
$this->error('id不可为空');
}
$condition[] = [ 'id', '=', $id ];
$from_model = new FormModel();
$res = $from_model->getFormInfo($condition);
return $res;
}
/**
* 查看表单数据
* @param $game_data
* @param $award_json
* @return array
*/
public function formData()
{
$form_id = input('form_id', '');
if (request()->isJson()) {
if (empty($form_id)) {
return error(-1, 'id不可为空');
}
$page = input('page', 1);
$page_size = input('page_size', PAGE_LIST_ROWS);
$nickname = input('nickname', '');
$start_time = input('start_time', '');
$end_time = input('end_time', '');
$condition[] = [ 'fd.form_id', '=', $form_id ];
$condition[] = [ 'fd.site_id', '=', $this->site_id ];
if ($start_time && !$end_time) {
$condition[] = [ 'fd.create_time', '>=', date_to_time($start_time) ];
} elseif (!$start_time && $end_time) {
$condition[] = [ 'fd.create_time', '<=', date_to_time($end_time) ];
} elseif ($start_time && $end_time) {
$condition[] = [ 'fd.create_time', 'between', [ date_to_time($start_time), date_to_time($end_time) ] ];
}
if (!empty($nickname)) $condition[] = [ 'm.nickname', 'like', "%{$nickname}%" ];
$alias = 'fd';
$join = [
/* [
'member m',
'fd.member_id = m.member_id',
'inner'
],*/
];
//,m.headimg,m.nickname,m.status,m.member_level_type
$field = 'fd.*';
$from_model = new FormDataModel();
$res = $from_model->getFormDataPageList($condition, $field, 'fd.id desc', $page, $page_size, $alias, $join);
if (!empty($res[ 'data' ][ 'list' ])) {
$order_model = new OrderModel();
foreach ($res[ 'data' ][ 'list' ] as $k => &$item_v) {
$item_v[ 'form_data' ] = json_decode($item_v[ 'form_data' ], true);
if ($item_v[ 'scene' ] == 'order') {
$item_v[ 'order_info' ] = $order_model->getOrderInfo([ [ 'order_id', '=', $item_v[ 'relation_id' ] ] ], 'order_id,order_no')[ 'data' ];
} elseif ($item_v[ 'scene' ] == 'goods') {
$item_v[ 'order_goods_info' ] = $order_model->getOrderGoodsInfo([ [ 'order_goods_id', '=', $item_v[ 'relation_id' ] ] ], 'order_goods_id,order_id,order_no')[ 'data' ];
}
if($item_v['member_id'] > 0){
$member = model('member')->getInfo(['member_id'=>$item_v['member_id']]);
$res[ 'data' ][ 'list' ][$k]['headimg'] = $member['headimg'];
$res[ 'data' ][ 'list' ][$k]['nickname'] = $member['nickname'];
$res[ 'data' ][ 'list' ][$k]['status'] = $member['status'];
$res[ 'data' ][ 'list' ][$k]['member_level_type'] = $member['member_level_type'];
}
}
}
return $res;
} else {
$this->assign('form_id', $form_id);
$item = model('form')->getInfo(['id'=>$form_id]);
$this->assign('item', $item);
return $this->fetch('form/formdata');
}
}
/**
* 查询表单列表
* @return array
*/
public function getFormList()
{
if (request()->isJson()) {
$form_type = input('form_type', 'goods');
$is_use = input('is_use', 1);
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'form_type', '=', $form_type ],
[ 'is_use', '=', $is_use ]
];
return ( new FormModel() )->getFormList($condition, 'id desc', 'id,form_name');
}
}
/**
* 推广
* @return array
*/
public function promote()
{
if (request()->isJson()) {
$form_id = input('form_id', '');
$app_type = input('app_type', 'all');
$from_model = new FormModel();
$res = $from_model->urlQrcode('/pages_tool/form/formdata', [ 'id' => $form_id,'uniacid'=>$this->site_id ], $app_type, $this->site_id);
return $res;
}
}
/**
* 删除表单数据
* @return array|string|string[]
*/
public function deleteFormData()
{
if (request()->isJson()) {
$id = input('id', '');
if (empty($id)) return error(-1, 'id不可为空');
$from_model = new FormDataModel();
$res = $from_model->deleteFormData([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ]);
return $res;
}
}
}

View File

@@ -0,0 +1,166 @@
<link rel="stylesheet" href="STATIC_EXT/diyview/css/diyview.css" />
<link rel="stylesheet" href="FORM_CSS/form.css" />
<style>
.layui-layout-admin.admin-style-2 .layui-body .body-content{margin: 15px !important;}
#diyView{visibility: visible;}
.preview-wrap .preview-restore-wrap{visibility: visible;}
.edit-attribute{display: block;}
</style>
<div id="diyView">
<!-- 组件列表 -->
<div class="component-list">
<h3>表单</h3>
<div>
<input type="text" name="form_name" class="layui-input" placeholder="请输入表单标题" {notempty name="$info"}value="{$info['form_name']}"{/notempty}>
</div>
<nav>
<h3>组件</h3>
<ul>
{foreach name="component" item="li" key="li_k"}
<li title="{$li.title}" @click="addComponent('{$li.name}')">
<img src="__ROOT__/{$li.icon}" data-icon="__ROOT__/{$li.icon}" data-icon-selected="__ROOT__/{$li.icon_selected}" />
<span>{$li.title}</span>
</li>
{/foreach}
</ul>
</nav>
</div>
<div class="preview-wrap">
<div class="preview-restore-wrap">
<div class="div-wrap">
<div class='diy-view-wrap layui-form'>
<div class="preview-block">
<!-- <div class="order-wrap">
<img src="{:img($form_type.head_img)}?v=1" class="head-img"/>
</div> -->
<div class="draggable-wrap" form-type="{$form_type.type}">
<div class="draggable-element" :class="{'selected' : index == currIndex}" v-for="(item, index) in list" :key="item.id" @click="currIndex = index">
<i class="del" @click="list.splice(index, 1)">x</i>
<form-text v-if="item.controller == 'Text'" :value="item.value" :ref="item.id"></form-text>
<form-textarea v-if="item.controller == 'Textarea'" :value="item.value" :ref="item.id"></form-textarea>
<form-select v-if="item.controller == 'Select'" :value="item.value" :ref="item.id"></form-select>
<form-checkbox v-if="item.controller == 'Checkbox'" :value="item.value" :ref="item.id"></form-checkbox>
<form-radio v-if="item.controller == 'Radio'" :value="item.value" :ref="item.id"></form-radio>
<form-img v-if="item.controller == 'Img'" :value="item.value" :ref="item.id"></form-img>
<form-date v-if="item.controller == 'Date'" :value="item.value" :ref="item.id"></form-date>
<form-date-limit v-if="item.controller == 'Datelimit'" :value="item.value" :ref="item.id"></form-date-limit>
<form-time v-if="item.controller == 'Time'" :value="item.value" :ref="item.id"></form-time>
<form-time-limit v-if="item.controller == 'Timelimit'" :value="item.value" :ref="item.id"></form-time-limit>
<form-city v-if="item.controller == 'City'" :value="item.value" :ref="item.id"></form-city>
</div>
</div>
</div>
<div class="edit-attribute" v-if="editData">
<form-text-edit v-if="editData.controller == 'Text'" :value="editData"></form-text-edit>
<form-textarea-edit v-if="editData.controller == 'Textarea'" :value="editData"></form-textarea-edit>
<form-select-edit v-if="editData.controller == 'Select'" :value="editData"></form-select-edit>
<form-checkbox-edit v-if="editData.controller == 'Checkbox'" :value="editData"></form-checkbox-edit>
<form-radio-edit v-if="editData.controller == 'Radio'" :value="editData"></form-radio-edit>
<form-img-edit v-if="editData.controller == 'Img'" :value="editData"></form-img-edit>
<form-date-edit v-if="editData.controller == 'Date'" :value="editData"></form-date-edit>
<form-date-limit-edit v-if="editData.controller == 'Datelimit'" :value="editData"></form-date-limit-edit>
<form-time-edit v-if="editData.controller == 'Time'" :value="editData"></form-time-edit>
<form-time-limit-edit v-if="editData.controller == 'Timelimit'" :value="editData"></form-time-limit-edit>
<form-city-edit v-if="editData.controller == 'City'" :value="editData"></form-city-edit>
</div>
</div>
</div>
</div>
</div>
<div class="custom-save">
<button class="layui-btn save">保存</button>
</div>
</div>
<script>
var STATICIMG = "STATIC_IMG";
</script>
<script src="STATIC_JS/vue.js"></script>
<script src="STATIC_EXT/diyview/js/components.js"></script>
<script src="STATIC_EXT/diyview/js/async_load_css.js"></script>
<script src="STATIC_EXT/diyview/js/ddsort.js"></script>
<script src="FORM_JS/form.js"></script>
<script>
var formComponents = JSON.parse('{:json_encode($component)}'),
repeat_flag = false;
$(function() {
var height = $(window).height();
var commonHeight = height - 214;
$(".component-list nav").css("height", (commonHeight + 20) + "px");
$(".preview-wrap .preview-restore-wrap .div-wrap").css("height", (commonHeight) + "px");
$(".edit-attribute .attr-wrap").css("height", (commonHeight) + "px");
$(".edit-attribute-placeholder").css("height", (height - 214) + "px");
$(".preview-block").css("min-height", (commonHeight - 120) + "px");
$("body").off("mousemove", ".component-list ul li").on("mousemove", ".component-list ul li", function() {
var icon_selected = $(this).find("img").attr("data-icon-selected");
$(this).find("img").attr("src", icon_selected);
}).on("mouseout", ".component-list ul li", function() {
var icon = $(this).find("img").attr("data-icon");
$(this).find("img").attr("src", icon);
});
$('.save').click(function() {
var form_name = $('[name="form_name"]').val();
if (!/[\S]+/.test(form_name)) {
layer.msg('请输入表单标题', {
icon: 5
});
return;
}
if (!vue._data.list.length) {
layer.msg('您尚未选择任何组件', {
icon: 5
});
return;
}
// 组件内验证
if (!vue.verify()) return;
if (repeat_flag) return;
repeat_flag = true;
$.ajax({
type: "post",
url: {notempty name = "$info"}ns.url("form://shop/form/editform"),{else /} ns.url("form://shop/form/addform"), {/notempty}
data: {
{notempty name = "$info"}id: {$info.id},{/notempty}
form_name: form_name,
form_type: '{$form_type.type}',
json_data: JSON.stringify(vue._data.list)
},
dataType: "JSON",
success: function(res) {
layer.msg(res.message);
if (res.code == 0) {
location.hash = ns.hash("form://shop/form/lists");
} else {
repeat_flag = false;
}
}
});
})
})
{notempty name = "$info"}
setTimeout(function() {
vue._data.list = JSON.parse('{:html_entity_decode($info.json_data)}');
}, 300);
{/notempty}
</script>

View File

@@ -0,0 +1,274 @@
<style>
.table-btn {justify-content: center;}
.layui-layout-admin.admin-style-2 .screen{margin-bottom: 15px;}
.layui-layout-admin.admin-style-2 .layui-form-item .layui-input-inline{background-color: #fff;}
.layui-layout-admin.admin-style-2 .table-tab .layui-tab-title{margin-bottom: 15px;}
.form-img .form-img-wrap {width: 25px;height: 25px;margin: 0 10px 10px 0;border: 1px solid #EAEAEA;display: flex;align-items: center;justify-items: center}
.form-img-wrap img {max-width: 100%;max-height: 100%;height: auto;width: 100%}
.layui-layer-content .layui-form-label {width: 250px}
.layui-layer-content .layui-form-label + .layui-input-block {margin-left: 100px}
.layui-table .form-data-wrap {max-height: 50px;overflow: hidden}
.layui-table .layui-form-item {margin-bottom: 0}
.layui-table .layui-form-label {width: auto;height: 25px;line-height: 25px;}
.layui-table .layui-form-label + .layui-input-block {margin-left: 0; height: 25px;line-height: 25px;min-height: unset;}
.layui-layer-content .form-data-wrap{
height: 700px;
overflow: auto;
}
</style>
<div class="screen layui-collapse" lay-filter="selection_panel">
<div class="layui-colla-item">
<form class="layui-colla-content layui-form layui-show">
<div class="layui-form-item">
<!-- <div class="layui-inline">
<label class="layui-form-label">用户昵称:</label>
<div class="layui-input-inline">
<input type="text" name="nickname" placeholder="请输入用户昵称" autocomplete="off" class="layui-input">
</div>
</div> -->
<div class="layui-inline">
<label class="layui-form-label">创建时间:</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="start_time" placeholder="开始时间" id="start_time" readonly>
<i class=" iconrili iconfont calendar"></i>
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline">
<input type="text" class="layui-input" name="end_time" placeholder="结束时间" id="end_time" readonly>
<i class=" iconrili iconfont calendar"></i>
</div>
</div>
</div>
<div class="form-row">
<button class="layui-btn" lay-filter="search" lay-submit>筛选</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
</div>
</div>
<!-- 列表 -->
<table id="formdata_list" lay-filter="formdata_list"></table>
<input type="hidden" value="" id="param" />
<!-- 状态 -->
<script type="text/html" id="status">
{{# if(d.status == 1){ }}
<span style="color: green;">正常</span>
{{# }else if(d.status == -1){ }}
<span style="color: gray;">冻结</span>
{{# } }}
</script>
<!-- 用户信息 -->
<script type="text/html" id="userdetail">
{{# if(d.member_id>0){ }}
<div class='table-title'>
<div class='title-pic headimg'>
<img layer-src src="{{ns.img(d.headimg)}}" onerror="this.src = '{:img('public/static/img/default_img/head.png')}' ">
</div>
<div class='title-content'>
<p class="layui-elip">{{d.nickname}}</p>
</div>
</div>
{{# } else { }}
<div class='table-title'>
<div class='title-pic headimg'>
<img layer-src src="{:img('public/static/img/default_img/head.png')}">
</div>
<div class='title-content'>
<p class="layui-elip">匿名用户</p>
</div>
</div>
{{# } }}
</script>
<!-- 工具栏操作 -->
<script type="text/html" id="operation">
<div class="table-btn">
<a class="layui-btn" lay-event="see">查看</a>
<a class="layui-btn" lay-event="delete">删除</a>
</div>
</script>
<script type="text/html" id="formData">
<div class="form-data-wrap">
{{# d.form_data.forEach(function(item){ }}
<div class="layui-form-item">
<label class="layui-form-label">{{ item.value.title }}</label>
<div class="layui-input-block">
{{# if(item.controller == 'Img'){ }}
<div class="form-img">
{{# item.img_lists.forEach(function(img){ }}
<div class="form-img-wrap">
<img src="{{ ns.img(img) }}" layer-src>
</div>
{{# }) }}
</div>
{{# } else { }}
{{ item.val }}
{{# } }}
</div>
</div>
{{# }) }}
</div>
</script>
<script>
var repeat_flag = false;
layui.use(['form', 'laydate', 'laytpl'], function() {
var table,
form = layui.form,
laydate = layui.laydate,
laytpl = layui.laytpl;
form.render();
//渲染时间
laydate.render({
elem: '#start_time',
type: 'datetime',
max: 0
});
laydate.render({
elem: '#end_time',
type: 'datetime',
max: 0
});
table = new Table({
elem: '#formdata_list',
url: ns.url("form://shop/form/formdata"),
where: {
form_id: "{$form_id}"
},
cols: [[
{
field: 'userdetail',
title: '会员信息',
width: '25%',
unresize: 'false',
templet: '#userdetail'
},
{
field: '',
title: '表单信息',
width: '25%',
unresize: 'false',
templet: '#formData'
},
{if $item['form_type'] != 'custom'}
{
field: '',
title: '来源订单',
width: '20%',
unresize: 'false',
templet: function(data) {
if(data.scene == 'order'){
return '<a href="'+ ns.href("shop/order/detail", {order_id:data.order_info.order_id}) +'" target="_blank" class="text-color">'+ data.order_info.order_no +'</a>';
}else if(data.scene == 'goods'){
return '<a href="'+ ns.href("shop/order/detail", {order_id:data.order_goods_info.order_id}) +'" target="_blank" class="text-color">'+ data.order_goods_info.order_no +'</a>';
}else{
return '';
}
}
},
{/if}
{
field: 'create_time',
title: '创建时间',
unresize: 'false',
width: '20%',
align: 'center',
templet: function(data) {
return ns.time_to_date(data.create_time);
}
},
{
title: '操作',
unresize: 'false',
align: 'right',
templet: '#operation'
}
]]
});
table.tool(function(obj) {
var data = obj.data;
switch (obj.event) {
case 'see':
laytpl($('#formData').html()).render(data, function(string){
layer.open({
title: '查看信息',
area: ["600px","800px"],
type: 1,
content: string,
btn: ['确认']
})
});
break;
case 'delete': //删除
del(data.id)
break;
}
});
/**
* 搜索功能
*/
form.on('submit(search)', function(data) {
if ($('#start_time').val() != '' && $('#end_time').val() != '' && (new Date($('#end_time').val()).getTime() <= new Date($('#start_time').val()).getTime() )) {
layer.msg('结束时间不能小于开始时间');
return false;
}
table.reload({
page: {
curr: 1
},
where: data.field
});
return false;
});
});
function del(id){
var del_flag = false; //防重复标识
layer.confirm('确定要删除吗?', function (index) {
if (del_flag) return;
del_flag = true;
layer.close(index);
$.ajax({
url: ns.url("form://shop/form/deleteFormData"),
data: {id:id},
dataType: 'JSON',
type: 'POST',
success: function(res) {
layer.msg(res.message);
del_flag = false;
if (res.code == 0) {
listenerHash(); // 刷新页面
layer.closeAll();
}
}
});
});
}
function fun(callback) {
var param = $("#param").val();
callback(param);
}
</script>

View File

@@ -0,0 +1,327 @@
<style>
.layui-table-box {overflow: inherit;}
.layui-table-header {overflow: inherit;}
.layui-table-header .layui-table-cell {overflow: inherit;}
.select-form-type {display: flex;}
.select-form-type .type-item {border: 2px solid #eee;cursor: pointer;width: 300px;text-align: center;margin: 0 15px 15px 0;border-radius: 10px;overflow: hidden}
.select-form-type .type-item .preview {width: 100%;height: auto;}
.select-form-type .type-item .title {line-height: 35px;font-weight: bold}
.select-form-type .selected {border-color: var(--base-color)}
.body-content {padding-top: 15px!important;}
.layui-layout-admin.admin-style-2 .layui-form-item .layui-input-inline{background-color: #fff;}
.layui-layout-admin.admin-style-2 .table-tab .layui-tab-title{margin-bottom: 15px;}
.layui-layout-admin.admin-style-2 .screen{margin-bottom: 15px;}
</style>
<div class="single-filter-box">
<button class="layui-btn" onclick="clickAdd()">添加表单</button>
</div>
<div class="screen layui-collapse" lay-filter="selection_panel">
<div class="layui-colla-item">
<form class="layui-colla-content layui-form layui-show">
<div class="layui-inline">
<label class="layui-form-label">表单名称:</label>
<div class="layui-input-inline">
<input type="text" name="form_name" placeholder="请输入表单名称" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">是否启用:</label>
<div class="layui-input-inline">
<select name="is_use">
<option value="">全部</option>
<option value="1">已启用</option>
<option value="0">未启用</option>
</select>
</div>
</div>
<!-- <div class="layui-inline">
<label class="layui-form-label">表单类型:</label>
<div class="layui-input-inline">
<select name="form_type">
<option value="">请选择表单类型</option>
{foreach name="form_type" item="vo"}
<option value="{$vo['type']}">{$vo['name']}</option>
{/foreach}
</select>
</div>
</div> -->
<div class="form-row">
<button class="layui-btn" lay-filter="search" lay-submit>筛选</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</form>
</div>
</div>
<table id="form_list" lay-filter="form_list"></table>
<script type="text/html" id="operation">
<div class="table-btn">
{{# if(d.is_use==1 && d.form_type == 'custom'){ }}
<a class="layui-btn" lay-event="promote">复制链接</a>
{{# } }}
<a class="layui-btn" lay-event="edit">编辑</a>
<a class="layui-btn" lay-event="data">数据</a>
{{# if(d.is_use==0){ }}
<a class="layui-btn" lay-event="start">启用</a>
{{# } }}
{{# if(d.is_use==1){ }}
<a class="layui-btn" lay-event="stop">禁用</a>
{{# } }}
<a class="layui-btn" lay-event="del">删除</a>
</div>
</script>
<script type="text/html" id="selectFromType">
<div class="select-form-type">
{foreach name="form_type" item="v" key="k" index="index"}
<div class="type-item {if $index eq 1}selected{/if}" form-type="{$k}" {if $index eq 3}style="margin-right: 0;"{/if}>
<img src="{:img('/public/static/img/default_img/menu-skeleton.png')}" alt="" class="preview" style="overflow: hidden;height: 490px;">
<div class="title">{$v.name}</div>
</div>
{/foreach}
</div>
</script>
<!-- 推广 -->
{include file="app/shop/view/promote.html"}
<script>
var table,laytpl,repeat_flag = false, formType = {:json_encode($form_type)};
layui.use(['form', 'laytpl'], function() {
laytpl = layui.laytpl;
form = layui.form;
table = new Table({
elem: '#form_list',
url: ns.url("form://shop/form/lists"),
cols: [
[{
field: 'form_name',
title: '表单名称',
unresize: 'false',
width: '30%',
}, {
field: 'level_name',
title: '表单类型',
unresize: 'false',
width: '15%',
templet: function (data) {
return formType[data.form_type] ? formType[data.form_type].name : '';
}
},{
title: '状态',
unresize: 'false',
width: '15%',
templet: function(data) {
return data.is_use == 1 ? '<span class="text-color">已启用</span>' : '<span>未启用</span>'
}
},
{
title: '创建时间',
unresize: 'false',
width: '20%',
templet: function(data) {
return ns.time_to_date(data.create_time);
}
},{
title: '操作',
toolbar: '#operation',
unresize: 'false',
align:'right'
}]
],
});
/**
* 监听工具栏操作
*/
table.tool(function(obj) {
var data = obj.data;
switch (obj.event) {
case 'del': //删除
del(data.id);
break;
case 'start': //启用
start_status(data.id,1,data.form_type);
break;
case 'stop': //停用
stop_status(data.id,0);
break;
case 'edit': //编辑
location.hash = ns.hash("form://shop/form/editform", {"id": data.id});
break;
case 'data': //更多
location.hash = ns.hash("form://shop/form/formdata", {form_id: data.id});
break;
case 'promote':
promote(data);
break;
}
});
form.on('submit(search)', function(data) {
table.reload({
page: {
curr: 1
},
where: data.field
});
return false;
});
});
// 自定义表单推广
function promote(data) {
if (repeat_flag) return;
repeat_flag = true;
// 先查询 H5 二维码
getFromQrcode(data.id,'h5',function (res) {
res.id = data.id;
repeat_flag = false;
laytpl($("#promote").html()).render(res, function (html) {
layer.open({
type: 1,
area: ['300px', '200px'],
offset: '155px',
title: ['链接分享'],
content: html,
success: function(){
$('input[name="promote_type"][value="h5"]').attr('data-config',JSON.stringify(res.h5));
form.render();
// 推广渠道监听
promoteTypeSwitch();
// 二次查询微信小程序、支付宝小程序二维码
getFromQrcode(data.id,'all',function (res) {
$('input[name="promote_type"]').each(function (index,item) {
if(res[$(item).val()]){
$(item).attr('data-config',JSON.stringify(res[$(item).val()]))
}
})
});
}
});
});
});
}
function getFromQrcode(form_id,app_type,callback) {
$.ajax({
type: "POST",
url: ns.url("form://shop/form/promote"),
data: {
form_id,
app_type
},
dataType: 'JSON',
success: function (res) {
if (callback) callback(res.data);
}
});
}
function clickAdd() {
layer.open({
type: 1,
title: '添加表单',
content: $('#selectFromType').html(),
area: ['660px', '660px'],
btn: ['确定', '取消'],
success: function () {
$('.select-form-type .type-item').click(function () {
$(this).addClass('selected').siblings().removeClass('selected');
})
},
yes: function(index, layero) {
let type = $('.select-form-type .type-item.selected').attr('form-type');
location.hash = ns.hash('form://shop/form/addform?form_type=' + type);
layer.close(index);
}
})
}
/**
* 启用
*/
function start_status(id,is_use,form_type){
var use_flag = false; //防重复标识
layer.confirm('确定要启用吗?', function (index) {
if (use_flag) return;
use_flag = true;
layer.close(index);
$.ajax({
url: ns.url("form://shop/form/editIsUse"),
data: {id:id,is_use:is_use,form_type:form_type},
dataType: 'JSON',
type: 'POST',
success: function(res) {
layer.msg(res.message);
use_flag = false;
if (res.code == 0) {
listenerHash(); // 刷新页面
}
}
});
});
}
/**
* 停用
*/
function stop_status(id,is_use){
var stop_flag = false; //防重复标识
layer.confirm('确定要禁用吗?', function (index) {
if (stop_flag) return;
stop_flag = true;
layer.close(index);
$.ajax({
url: ns.url("form://shop/form/editIsUse"),
data: {id:id,is_use:is_use},
dataType: 'JSON',
type: 'POST',
success: function(res) {
layer.msg(res.message);
stop_flag = false;
if (res.code == 0) {
listenerHash(); // 刷新页面
}
}
});
});
}
function del(id){
var del_flag = false; //防重复标识
layer.confirm('确定要删除吗?', function (index) {
if (del_flag) return;
del_flag = true;
layer.close(index);
$.ajax({
url: ns.url("form://shop/form/deleteForm"),
data: {id:id},
dataType: 'JSON',
type: 'POST',
success: function(res) {
layer.msg(res.message);
del_flag = false;
if (res.code == 0) {
listenerHash(); // 刷新页面
}
}
});
});
}
</script>

View File

@@ -0,0 +1,326 @@
.layui-layout-admin .layui-body .body-content {
padding: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.order-wrap {
}
.order-wrap .head-img {
width: 100%;
height: auto;
}
.draggable-element {
position: relative;
cursor: move;
}
.draggable-element:hover .del {
display: block;
}
.form-gorup {
padding: 15px;
background: #fff;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
}
.form-gorup .label {
font-size: 14px;
color: #666;
width: 80px;
min-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 10px;
cursor: move;
}
.form-gorup .input {
flex: 1;
border: none;
font-size: 14px;
text-align: left;
cursor: move;
}
.form-gorup .textarea {
flex: 1;
border: none;
font-size: 14px;
text-align: left;
cursor: move;
}
.form-gorup .input::placeholder,
.form-gorup .textarea::placeholder {
color: #ddd;
font-size: 14px;
text-align: left;
}
.form-gorup>i {
color: #999;
}
.form-gorup .more {
flex: 1;
font-size: 14px;
text-align: right;
color: #999
}
.edit-attribute .options-wrap .option-item {
position: relative;
margin-bottom: 15px;
width: 100%;
}
.edit-attribute .option-item input {
padding-right: 34px;
}
.edit-attribute .option-item .icontrash {
position: absolute;
right: 0;
top: 0;
width: 34px;
height: 34px;
line-height: 34px;
text-align: center;
cursor: pointer;
}
/* 多行文本 */
.form-gorup .checkbox-list .textarea::placeholder {
text-align: left;
}
.form-gorup .checkbox-list>.textarea {
margin-top: 10px;
width: 100%;
height: 40px;
text-align: left;
}
.add-item-btn-box {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
}
.add-item-btn-box .add-item-btn {
width: 48%;
height: 34px;
line-height: 34px;
text-align: center;
border: 1px dashed #999;
border-radius: 2px;
box-sizing: border-box;
font-size: 12px;
cursor: pointer;
}
.add-items-box {
position: absolute;
top: 40px;
left: 0;
z-index: 9;
width: 100%;
padding: 15px;
box-sizing: border-box;
background-color: #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
}
.add-items-title {
font-size: 12px;
line-height: 20px;
}
.add-items-desc {
font-size: 12px;
line-height: 20px;
color: #909399;
}
.add-items-btn {
text-align: right;
}
/* 多选框 */
.form-gorup-block {
display: block;
}
.form-gorup-block label {
display: inline-block;
width: 100%;
max-width: 100%;
margin-right: 0;
}
.checkbox-list {
width: 100%;
display: flex;
}
.checkbox-item {
display: flex;
align-items: center;
padding-right: 10px;
box-sizing: border-box;
}
.checkbox-item>i {
color: #999;
}
.checkbox-item .checkbox {
width: 14px;
height: 14px;
line-height: 14px;
text-align: center;
border-radius: 2px;
margin-right: 10px;
border: 1px solid #E6E6E6;
}
.checkbox-item .checkbox i {
font-size: 15px;
color: #fff;
}
.checkbox-item .checkbox-title {
line-height: 20px;
}
/* 单选框 */
.checkbox-item .checkbox.radio {
border-radius: 50%;
}
/* 图片 */
.img-box {
display: inline-block;
width: 50px;
height: 50px;
border: 1px solid #E6E6E6;
box-sizing: border-box;
margin-right: 10px;
margin-top: 10px;
line-height: 48px;
text-align: center;
border-radius: 1px;
vertical-align: top;
position: relative;
}
.img-box img {
max-width: 100%;
max-height: 100%;
}
.img-box .close {
background-color: #999;
position: absolute;
top: -7px;
right: -7px;
width: 14px;
height: 14px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.img-box .close i {
color: #fff;
font-size: 14px;
}
.img-box i.iconadd_light {
color: #999;
font-size: 20px;
}
/* 日期 */
.date-input {
margin-top: 10px;
}
.form-gorup .checkbox-list .input::placeholder {
text-align: left;
}
/* 日期范围 */
.date-limit-box {
}
.form-gorup .interval {
margin-right: 10px;
}
.date-limit-box input {
border: 0;
text-align: left !important;
}
.date-limit-box.date input {
width: 75px;
}
.date-limit-box.time input {
width: 30px;
}
.date-limit-form .layui-form-label {
width: 100%;
text-align: left;
}
.date-limit-form .layui-form-label + .layui-input-block {
margin-left: 0;
}
/* 时间 */
.laydate-time-list>li:nth-child(3) {
display: none;
}
.layui-laydate-list.laydate-time-list>li {
width: 50%;
}
.laydate-time-list ol li {
padding-left: 55px !important;
}
.layui-form-item {
margin-bottom: 15px;
}
.edit-attribute .attr-wrap .restore-wrap .attr-title {
margin-bottom: 20px;
}
.layui-checkbox-disbaled, .layui-checkbox-disbaled i {
border-color: #d2d2d2 !important;
}
.layui-checkbox-disbaled[lay-skin=primary] span {
color: #666;
}
[form-type="order"]{
margin-top: 10px;
}
[form-type="order"] .draggable-element {
padding: 0 12px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
<?php
/**
*/
namespace addon\form\shopapi\controller;
use app\shopapi\controller\BaseApi;
use addon\form\model\Form as FormModel;
/**
* 表单管理
* @author Administrator
*
*/
class Form extends BaseApi
{
/**
* 获取表单列表
*/
public function lists()
{
$form_type = $this->params[ 'form_type' ] ?? 'goods';
$res = ( new FormModel() )->getFormList([ [ 'site_id', '=', $this->site_id ], [ 'form_type', '=', $form_type ], [ 'is_use', '=', 1 ] ], 'id desc', 'id, form_name');
return $this->response($res);
}
}