Browse Source

首次提交

master
liutong 1 year ago
parent
commit
af0548ff50
  1. 25
      .gitignore
  2. 1
      niucloud/.env
  3. 1
      niucloud/.example.env
  4. 7
      niucloud/.gitignore
  5. 0
      niucloud/.htaccess
  6. 42
      niucloud/.travis.yml
  7. 32
      niucloud/LICENSE.txt
  8. 56
      niucloud/README.md
  9. 36
      niucloud/addon/hello_world/Addon.php
  10. 40
      niucloud/addon/hello_world/admin/views/diy/components/edit-hello-text.vue
  11. 12
      niucloud/addon/hello_world/admin/views/hello_world/index.vue
  12. 12
      niucloud/addon/hello_world/admin/views/hello_world/site.vue
  13. 28
      niucloud/addon/hello_world/app/adminapi/controller/Index.php
  14. 19
      niucloud/addon/hello_world/app/adminapi/route/route.php
  15. 1
      niucloud/addon/hello_world/app/api/route/route.php
  16. 21
      niucloud/addon/hello_world/app/dict/diy/components.php
  17. 25
      niucloud/addon/hello_world/app/dict/diy/links.php
  18. 90
      niucloud/addon/hello_world/app/dict/diy/pages.php
  19. 14
      niucloud/addon/hello_world/app/dict/diy/template.php
  20. 18
      niucloud/addon/hello_world/app/dict/member/account_change_type.php
  21. 17
      niucloud/addon/hello_world/app/dict/menu/admin.php
  22. 36
      niucloud/addon/hello_world/app/dict/menu/site.php
  23. 19
      niucloud/addon/hello_world/app/dict/notice/notice.php
  24. 7
      niucloud/addon/hello_world/app/dict/notice/sms.php
  25. 14
      niucloud/addon/hello_world/app/dict/notice/weapp.php
  26. 11
      niucloud/addon/hello_world/app/dict/notice/wechat.php
  27. 15
      niucloud/addon/hello_world/app/dict/schedule/schedule.php
  28. 16
      niucloud/addon/hello_world/app/event.php
  29. 27
      niucloud/addon/hello_world/app/job/AddonSchedule.php
  30. 17
      niucloud/addon/hello_world/app/lang/zh-cn/api.php
  31. 27
      niucloud/addon/hello_world/app/lang/zh-cn/dict.php
  32. 18
      niucloud/addon/hello_world/app/lang/zh-cn/validate.php
  33. 47
      niucloud/addon/hello_world/app/listener/AppManageListener.php
  34. 29
      niucloud/addon/hello_world/app/listener/SiteLayout.php
  35. 9
      niucloud/addon/hello_world/info.json
  36. 4
      niucloud/addon/hello_world/package/admin-package.json
  37. 5
      niucloud/addon/hello_world/package/composer.json
  38. 5
      niucloud/addon/hello_world/package/uni-app-package.json
  39. 16
      niucloud/addon/hello_world/package/uni-app-pages.php
  40. 4
      niucloud/addon/hello_world/package/web-package.json
  41. BIN
      niucloud/addon/hello_world/resource/cover.png
  42. BIN
      niucloud/addon/hello_world/resource/icon.png
  43. BIN
      niucloud/addon/hello_world/resource/images/system/layout-hellow.jpg
  44. 6
      niucloud/addon/hello_world/sql/install.sql
  45. 1
      niucloud/addon/hello_world/sql/uninstall.sql
  46. 34
      niucloud/addon/hello_world/uni-app/components/diy/hello-text/index.vue
  47. 14
      niucloud/addon/hello_world/uni-app/components/fixed/hello-index/index.vue
  48. 3
      niucloud/addon/hello_world/uni-app/locale/en.json
  49. 3
      niucloud/addon/hello_world/uni-app/locale/zh-Hans.json
  50. 7
      niucloud/addon/hello_world/uni-app/locale/zh-Hans/pages.index.json
  51. 25
      niucloud/addon/hello_world/uni-app/pages/index.vue
  52. 36
      niucloud/addon/hygl/Addon.php
  53. 52
      niucloud/addon/hygl/admin/api/advertising.ts
  54. 29
      niucloud/addon/hygl/admin/api/common.ts
  55. 60
      niucloud/addon/hygl/admin/api/config.ts
  56. 52
      niucloud/addon/hygl/admin/api/coupons.ts
  57. 7
      niucloud/addon/hygl/admin/api/hello_world.ts
  58. 52
      niucloud/addon/hygl/admin/api/transaction_history.ts
  59. 61
      niucloud/addon/hygl/admin/api/user.ts
  60. 54
      niucloud/addon/hygl/admin/api/user_coupons.ts
  61. 17
      niucloud/addon/hygl/admin/lang/zh-cn/advertising.advertising.json
  62. 33
      niucloud/addon/hygl/admin/lang/zh-cn/config.config.json
  63. 26
      niucloud/addon/hygl/admin/lang/zh-cn/coupons.coupons.json
  64. 1
      niucloud/addon/hygl/admin/lang/zh-cn/hello_world.index.json
  65. 33
      niucloud/addon/hygl/admin/lang/zh-cn/transaction_history.transaction_history.json
  66. 34
      niucloud/addon/hygl/admin/lang/zh-cn/user.user.json
  67. 21
      niucloud/addon/hygl/admin/lang/zh-cn/user_coupons.user_coupons.json
  68. 171
      niucloud/addon/hygl/admin/views/advertising/advertising.vue
  69. 174
      niucloud/addon/hygl/admin/views/advertising/components/advertising-edit.vue
  70. 245
      niucloud/addon/hygl/admin/views/config/components/config-edit.vue
  71. 354
      niucloud/addon/hygl/admin/views/config/config.vue
  72. 238
      niucloud/addon/hygl/admin/views/coupons/components/coupons-edit.vue
  73. 227
      niucloud/addon/hygl/admin/views/coupons/coupons.vue
  74. 17
      niucloud/addon/hygl/admin/views/hello_world/index.vue
  75. 295
      niucloud/addon/hygl/admin/views/transaction_history/components/transaction-history-edit.vue
  76. 286
      niucloud/addon/hygl/admin/views/transaction_history/transaction_history.vue
  77. 311
      niucloud/addon/hygl/admin/views/user/components/user-edit.vue
  78. 283
      niucloud/addon/hygl/admin/views/user/user.vue
  79. 233
      niucloud/addon/hygl/admin/views/user_coupons/components/user-coupons-edit.vue
  80. 249
      niucloud/addon/hygl/admin/views/user_coupons/user_coupons.vue
  81. 106
      niucloud/addon/hygl/app/adminapi/controller/Common.php
  82. 89
      niucloud/addon/hygl/app/adminapi/controller/advertising/Advertising.php
  83. 131
      niucloud/addon/hygl/app/adminapi/controller/config/Config.php
  84. 127
      niucloud/addon/hygl/app/adminapi/controller/coupons/Coupons.php
  85. 29
      niucloud/addon/hygl/app/adminapi/controller/hello_world/Index.php
  86. 120
      niucloud/addon/hygl/app/adminapi/controller/transaction_history/TransactionHistory.php
  87. 147
      niucloud/addon/hygl/app/adminapi/controller/user/User.php
  88. 97
      niucloud/addon/hygl/app/adminapi/controller/user_coupons/UserCoupons.php
  89. 173
      niucloud/addon/hygl/app/adminapi/route/route.php
  90. 271
      niucloud/addon/hygl/app/api/controller/Home.php
  91. 41
      niucloud/addon/hygl/app/api/controller/TestController.php
  92. 306
      niucloud/addon/hygl/app/api/controller/WeChatController.php
  93. 28
      niucloud/addon/hygl/app/api/controller/hello_world/Index.php
  94. 37
      niucloud/addon/hygl/app/api/route/route.php
  95. 4
      niucloud/addon/hygl/app/dict/menu/admin.php
  96. 33
      niucloud/addon/hygl/app/dict/menu/site.php
  97. 12
      niucloud/addon/hygl/app/event.php
  98. 4
      niucloud/addon/hygl/app/lang/en/api.php
  99. 4
      niucloud/addon/hygl/app/lang/en/dict.php
  100. 4
      niucloud/addon/hygl/app/lang/en/validate.php

25
.gitignore

@ -0,0 +1,25 @@
# Build and Release Folders
bin-debug/
bin-release/
[Oo]bj/
[Bb]in/
# Other files and folders
.settings/
# Executables
*.swf
*.air
*.ipa
*.apk
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
# should NOT be excluded as they contain compiler settings and other important
# information for Eclipse / Flash Builder.
/.idea
/upgrade
niucloud/public/.htaccess
uni-app/*
web/*
IM/*

1
niucloud/.env

@ -0,0 +1 @@
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai AUTH_KEY = nzpawfdodlftgvqgbjaeskihscuhxymr [DATABASE] TYPE = mysql HOSTNAME = 82.157.42.191 DATABASE = zhifuguanli_zeya USERNAME = zhifuguanli_zeya PASSWORD = XNfnWG2DGF6GQh27 HOSTPORT = 3306 PREFIX = hy_ CHARSET = utf8 DEBUG = false [REDIS] REDIS_HOSTNAME = 127.0.0.1 PORT = 6379 REDIS_PASSWORD = SELECT = 0 [LANG] default_lang = zh-cn [SYSTEM] ADMIN_TOKEN_NAME = token API_TOKEN_NAME = token ADMIN_SITE_ID_NAME = site-id API_SITE_ID_NAME = site-id ADMIN_TOKEN_EXPIRE_TIME = 604800 API_TOKEN_EXPIRE_TIME = 86400 LANG_NAME = lang CHANNEL_NAME = channel ADMIN_DOMAIN = WAP_DOMAIN = WEB_DOMAIN = [NIUCLOUD] code = secret =

1
niucloud/.example.env

@ -0,0 +1 @@
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai AUTH_KEY = {auth_key} [DATABASE] TYPE = mysql HOSTNAME = {dbhost} DATABASE = {dbname} USERNAME = {dbuser} PASSWORD = {dbpwd} HOSTPORT = {dbport} PREFIX = {dbprefix} CHARSET = utf8 DEBUG = false [REDIS] REDIS_HOSTNAME = 127.0.0.1 PORT = 6379 REDIS_PASSWORD = SELECT = 0 [LANG] default_lang = zh-cn [SYSTEM] ADMIN_TOKEN_NAME = token API_TOKEN_NAME = token ADMIN_SITE_ID_NAME = site-id API_SITE_ID_NAME = site-id ADMIN_TOKEN_EXPIRE_TIME = 604800 API_TOKEN_EXPIRE_TIME = 86400 LANG_NAME = lang CHANNEL_NAME = channel ADMIN_DOMAIN = WAP_DOMAIN = WEB_DOMAIN = [NIUCLOUD] code = secret =

7
niucloud/.gitignore

@ -0,0 +1,7 @@
/.idea
/.vscode
*.log
/runtime
install.lock
/vendor
composer.lock

0
niucloud/.htaccess

42
niucloud/.travis.yml

@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

32
niucloud/LICENSE.txt

@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1. 需要给代码的用户一份Apache Licence ;
2. 如果你修改了代码,需要在被修改的文件中说明;
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可,但不可以表现为对Apache Licence构成更改。
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

56
niucloud/README.md

@ -0,0 +1,56 @@
ThinkPHP 6.0
===============
> 运行环境要求PHP7.2+,兼容PHP8.1
[官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api)
ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
## 主要新特性
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
## 安装
~~~
composer create-project topthink/think tp 6.0.*
~~~
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 文档
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
## 参与开发
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2021 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

36
niucloud/addon/hello_world/Addon.php

@ -0,0 +1,36 @@
<?php
namespace addon\hello_world;
/**
* 插件安装之后单独的插件方法
* Class HelloWorld
* @package addon\hello_world
*/
class Addon
{
/**
* 插件安装执行
*/
public function install()
{
return true;
}
/**
* 插件卸载执行
*/
public function uninstall()
{
return true;
}
/**
* 插件升级执行
*/
public function upgrade()
{
return true;
}
}

40
niucloud/addon/hello_world/admin/views/diy/components/edit-hello-text.vue

@ -0,0 +1,40 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">文本设置</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('blankHeight')">
<el-slider v-model="diyStore.editComponent.height" show-input size="small" class="ml-[10px] horz-blank-slider"/>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
<script lang="ts" setup>
import {t} from '@/lang'
import useDiyStore from '@/stores/modules/diy'
const diyStore = useDiyStore()
diyStore.editComponent.ignore = []; //
defineExpose({})
</script>
<style lang="scss">
.horz-blank-slider {
.el-slider__input {
width: 100px;
}
}
</style>
<style lang="scss" scoped></style>

12
niucloud/addon/hello_world/admin/views/hello_world/index.vue

@ -0,0 +1,12 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
测试页面
</el-card>
</div>
</template>
<script lang="ts" setup>
</script>
<style lang="scss" scoped></style>

12
niucloud/addon/hello_world/admin/views/hello_world/site.vue

@ -0,0 +1,12 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
站点测试页面
</el-card>
</div>
</template>
<script lang="ts" setup>
</script>
<style lang="scss" scoped></style>

28
niucloud/addon/hello_world/app/adminapi/controller/Index.php

@ -0,0 +1,28 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hello_world\app\adminapi\controller;
use core\base\BaseAdminController;
class Index extends BaseAdminController
{
/**
* 接口数据
*/
public function index()
{
return success("HELLO_WORLD_RETURN");
}
}

19
niucloud/addon/hello_world/app/adminapi/route/route.php

@ -0,0 +1,19 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
use think\facade\Route;
/**
* 路由(注意最好group路由名称与插件名称一致,防止路由冲突)
*/
Route::group("hello_world", function () {
Route::get('index', 'addon\hello_world\app\adminapi\controller\Index@index');
});

1
niucloud/addon/hello_world/app/api/route/route.php

@ -0,0 +1 @@

21
niucloud/addon/hello_world/app/dict/diy/components.php

@ -0,0 +1,21 @@
<?php
return [
'BASIC' => [
'title' => get_lang('dict_diy.component_type_basic'),
'list' => [
'HelloText' => [
'title' => 'hello文本',
'icon' => 'iconfont-iconhuiyuanzhongxin',
'path' => 'edit-hello-text',
'support_page' => [],
'uses' => 0,
'sort' => 10007,
'value' => [
'height' => 20
],
],
],
],
];

25
niucloud/addon/hello_world/app/dict/diy/links.php

@ -0,0 +1,25 @@
<?php
return [
'HELLO_WORLD_LINK' => [
'key' => 'hello_world',
'addon_title' => get_lang('dict_diy.hello_world_title'),
'title' => get_lang('dict_diy.hello_world_link'),
'child_list' => [
[
'name' => 'HELLO_WORLD_INDEX',
'title' => get_lang('dict_diy.hello_world_index'),
'url' => '/addon/hello_world/pages/index',
'is_share' => 1,
'action' => ''
],
[
'name' => 'HELLO_WORLD_INFO',
'title' => get_lang('dict_diy.hello_world_info'),
'url' => '/addon/hello_world/pages/info',
'is_share' => 1,
'action' => ''
],
]
],
];

90
niucloud/addon/hello_world/app/dict/diy/pages.php

@ -0,0 +1,90 @@
<?php
return [
'DIY_INDEX' => [
'hello_world_index' => [ // 页面标识
"title" => "hello world 首页", // 页面名称
'cover' => '', // 页面封面图
'preview' => '', // 页面预览图
'desc' => '', // 页面描述
'mode' => 'diy', // 页面模式:diy:自定义,fixed:固定
// 页面数据源
"data" => [
"global" => [
"title" => "hello world首页页面",
"pageBgColor" => "#F8F8F8",
'bgUrl' => '',
'imgWidth' => '',
'imgHeight' => '',
"bottomTabBarSwitch" => true,
"template" => [
'textColor' => "#303133",
"pageBgColor" => "",
"componentBgColor" => "",
"topRounded" => 0,
"bottomRounded" => 0,
"elementBgColor" => "",
"topElementRounded" => 0,
"bottomElementRounded" => 0,
"margin" => [
"top" => 0,
"bottom" => 0,
"both" => 0
]
],
'topStatusBar' => [
'bgColor' => "#ffffff",
'isTransparent' => false,
'isShow' => true,
'style' => 'style-1',
'textColor' => "#333333",
'textAlign' => 'center',
],
'popWindow' => [
'imgUrl' => "",
'imgWidth' => '',
'imgHeight' => '',
'count' => -1,
'show' => 0,
'link' => [
'name' => ""
],
]
],
"value" => [
[
"path" => "edit-image-ads",
"id" => "4640ld4k1pu0",
"componentName" => "ImageAds",
"componentTitle" => "图片广告",
"uses" => 0,
"list" => [
[
"link" => [
"name" => ""
],
"imageUrl" => "static/resource/images/diy/banner.png",
"imgWidth" => 750,
"imgHeight" => 320,
"id" => "2xuytp7622w0"
]
],
"ignore" => [],
"pageBgColor" => "",
"componentBgColor" => "",
"topRounded" => 0,
"bottomRounded" => 0,
"elementBgColor" => "",
"topElementRounded" => 0,
"bottomElementRounded" => 0,
"margin" => [
"top" => 0,
"bottom" => 0,
"both" => 0
]
]
]
]
]
]
];

14
niucloud/addon/hello_world/app/dict/diy/template.php

@ -0,0 +1,14 @@
<?php
return [
'DIY_HELLO_WORLD_INDEX' => [
'title' => get_lang('dict_diy.page_hello_world_index'),
'page' => '/hello_world/pages/index',
'action' => ''
],
'DIY_HELLO_WORLD_INFO' => [
'title' => get_lang('dict_diy.page_hello_world_info'),
'page' => '/hello_world/pages/info',
'action' => ''
],
];

18
niucloud/addon/hello_world/app/dict/member/account_change_type.php

@ -0,0 +1,18 @@
<?php
use app\dict\member\MemberAccountTypeDict;
return [
MemberAccountTypeDict::POINT => [
//调整
'hello_world_test' => [
//名称
'name' => "hello_world账户变化",
//是否增加
'inc' => 1,
//是否减少
'dec' => 1,
],
],
];

17
niucloud/addon/hello_world/app/dict/menu/admin.php

@ -0,0 +1,17 @@
<?php
return [
[
'menu_name' => '插件菜单',
'menu_key' => 'niucloud_hello',
'menu_type' => 1,
'icon' => 'iconfont-iconyingyongshichang',
'api_url' => '',
'router_path' => 'hello_world',
'view_path' => 'hello_world/index',
'methods' => '',
'sort' => 90,
'status' => 1,
'is_show' => 1,
],
];

36
niucloud/addon/hello_world/app/dict/menu/site.php

@ -0,0 +1,36 @@
<?php
return [
[
'menu_name' => '插件站点菜单',
'menu_key' => 'niucloud_site_hello',
'menu_type' => 1,
'icon' => 'iconfont-iconyingyongshichang',
'api_url' => '',
'router_path' => 'hello_world',
'view_path' => 'hello_world/site',
'methods' => '',
'sort' => 100,
'status' => 1,
'is_show' => 1,
],
/* [
'menu_name' => '会员列表',
'menu_key' => 'member_list',
'parent_key' => 'member',
'menu_type' => 1,
'icon' => 'iconfont-iconhuiyuanliebiao',
'api_url' => 'member/member',
'router_path' => 'hello_world_member_list',
'view_path' => 'hello_world/member',
'methods' => 'get',
'sort' => 100,
'status' => 1,
'is_show' => 1,
'children' => [
]
],
"delete" => "member" //针对修改系统菜单处理方式,可以删除系统菜单,设置对应key值,也可删除不需要的菜单处理
*/
];

19
niucloud/addon/hello_world/app/dict/notice/notice.php

@ -0,0 +1,19 @@
<?php
return [
//充值成功通知,站点端发送
'recharge_success' => [
'addon' => 'hello_world',
'key' => 'recharge_success',
'receiver_type' => 1,
'name' => '充值成功通知',
'title' => '会员充值成功后发送',
'async' => true,
'variable' => [
'price' => '充值金额',
'balance' => '充值后账户',
'time' => '充值时间',
'trade_no' => '交易单号'
],
]
];

7
niucloud/addon/hello_world/app/dict/notice/sms.php

@ -0,0 +1,7 @@
<?php
return [
'recharge_success' => [
'content' => '您充值金额¥{price}, 充值后金额¥{balance}',
]
];

14
niucloud/addon/hello_world/app/dict/notice/weapp.php

@ -0,0 +1,14 @@
<?php
return [
'recharge_success' => [
'tid' => '755',
'content' => [
['交易单号', '{trade_no}', 'keyword1'],
['充值金额', '{price}', 'keyword2'],
['账户余额', '{balance}', 'keyword3'],
['充值时间', '{time}', 'keyword4'],
],
'kid_list' => [1, 3, 4, 2],
'scene_desc' => ''
]
];

11
niucloud/addon/hello_world/app/dict/notice/wechat.php

@ -0,0 +1,11 @@
<?php
return [
'recharge_success' => [
'temp_key' => '52552',
'keyword_name_list' => [ '充值时间', '充值金额' ],
'content' => [
[ '充值时间', '{time}', 'time1' ],
[ '充值金额', '{price}', 'amount3' ],
]
]
];

15
niucloud/addon/hello_world/app/dict/schedule/schedule.php

@ -0,0 +1,15 @@
<?php
return [
[
'key' => 'addon_schedule',
'name' => '插件计划任务',
'desc' => '',
'time' => [
'type' => 'min',
'min' => 1
],
'class' => 'addon\hello_world\app\job\AddonSchedule',
'function' => ''
],
];

16
niucloud/addon/hello_world/app/event.php

@ -0,0 +1,16 @@
<?php
return [
//文件执行序列号
'bind' => [
],
'listen' => [
//应用管理
'AppManage' => ['addon\hello_world\app\listener\AppManageListener'],
],
'subscribe' => [
],
];

27
niucloud/addon/hello_world/app/job/AddonSchedule.php

@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hello_world\app\job;
use core\base\BaseJob;
use think\facade\Log;
/**
* 插件计划任务
*/
class AddonSchedule extends BaseJob
{
public function doJob()
{
Log::write('插件计划任务,执行时间:'.date('Y-m-d h:i:s'));
return true;
}
}

17
niucloud/addon/hello_world/app/lang/zh-cn/api.php

@ -0,0 +1,17 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
/**
* 插件api接口语言
*/
return [
//系统常用
'HELLO_WORLD_RETURN' => 'hello world演示数据',
];

27
niucloud/addon/hello_world/app/lang/zh-cn/dict.php

@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
/**
* 插件枚举语言
*/
return [
'dict_diy' => [
'page_hello_world_index' => 'hello 首页',
'page_hello_world_info' => 'hello 信息',
'hello_world_title' => 'hello world',
'hello_world_link' => 'hello world链接',
'hello_world_index' => 'hello world index 插件',
'hello_world_info' => 'hello world info 插件'
],
'dict_site_layout' => [
'hellow_world' => '你好'
]
];

18
niucloud/addon/hello_world/app/lang/zh-cn/validate.php

@ -0,0 +1,18 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
/**
* 插件验证多语言
*/
return [
'file_sort' => 100,
];

47
niucloud/addon/hello_world/app/listener/AppManageListener.php

@ -0,0 +1,47 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hello_world\app\listener;
/**
* 应用管理
* Class AppManage
* @package app\listener\hello_world
*/
class AppManageListener
{
/**
* 应用管理
* @return array
*/
public function handle()
{
return [
"category" => [
//插件如果要单独分类展示,需要专门定义
[
"key" => "hello_world_category",
"name" => "第三方应用",
],
],
[
"addon" => "hello_world",
"title" => "hello world",
"category" => "hello_world_category", //设置插件对应展示分类,默认basic
"desc" => "hello world 应用展示",
"icon" => addon_resource("hello_world", "icon.png"), //图标
"cover" => "", //封面
"url" => "/hello_world"
],
];
}
}

29
niucloud/addon/hello_world/app/listener/SiteLayout.php

@ -0,0 +1,29 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的saas管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud-admin.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hello_world\app\listener;
/**
* 站点端布局
*/
class SiteLayout
{
public function handle()
{
return [
"name" => get_lang("dict_site_layout.hellow_world"),
"key" => "hellow",
"image" => "static/resource/images/system/layout-hellow.jpg",
"sort" => 1
];
}
}

9
niucloud/addon/hello_world/info.json

@ -0,0 +1,9 @@
{
"title": "hello world",
"desc": "Niucloud hello world演示插件",
"key": "hello_world",
"version": "1.0.1",
"author": "niucloud",
"type": "app",
"support_app": ""
}

4
niucloud/addon/hello_world/package/admin-package.json

@ -0,0 +1,4 @@
{
"dependencies": {
}
}

5
niucloud/addon/hello_world/package/composer.json

@ -0,0 +1,5 @@
{
"require": {
}
}

5
niucloud/addon/hello_world/package/uni-app-package.json

@ -0,0 +1,5 @@
{
"dependencies": {
"weixin-js-sdk": "^1.6.0"
}
}

16
niucloud/addon/hello_world/package/uni-app-pages.php

@ -0,0 +1,16 @@
<?php
return [
'pages' => <<<EOT
// PAGE_BEGIN
{
"path": "addon/{{addon_name}}/pages/index",
"style": {
// #ifdef H5
"navigationStyle": "custom",
// #endif
"navigationBarTitleText": "%{{addon_name}}.pages.index%"
}
}
// PAGE_END
EOT
];

4
niucloud/addon/hello_world/package/web-package.json

@ -0,0 +1,4 @@
{
"dependencies": {
}
}

BIN
niucloud/addon/hello_world/resource/cover.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
niucloud/addon/hello_world/resource/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
niucloud/addon/hello_world/resource/images/system/layout-hellow.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

6
niucloud/addon/hello_world/sql/install.sql

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS `{{prefix}}hello_world` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='演示插件表';
INSERT INTO `{{prefix}}hello_world`(`name`) VALUES ('名称');

1
niucloud/addon/hello_world/sql/uninstall.sql

@ -0,0 +1 @@
DROP TABLE IF EXISTS `{{prefix}}hello_world`;

34
niucloud/addon/hello_world/uni-app/components/diy/hello-text/index.vue

@ -0,0 +1,34 @@
<template>
<view :style="warpCss">
hello-world演示插件文本自定义组件
</view>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import useDiyStore from '@/app/stores/diy';
const props = defineProps(['component', 'index']);
const diyStore = useDiyStore();
const diyComponent = computed(() => {
if (diyStore.mode == 'decorate') {
return diyStore.value[props.index];
} else {
return props.component;
}
})
const warpCss = computed(() => {
var style = '';
style += 'background-color:' + diyComponent.value.componentBgColor + ';';
style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
return style;
})
</script>
<style></style>

14
niucloud/addon/hello_world/uni-app/components/fixed/hello-index/index.vue

@ -0,0 +1,14 @@
<template>
<view>
hello-index固定模板示例我也可以装修
<!-- 自定义模板渲染 -->
<diy-group :data="props.data" :pullDownRefreshCount="props.pullDownRefreshCount"></diy-group>
</view>
</template>
<script setup lang="ts">
import { computed, watch } from 'vue';
const props = defineProps(['data', 'pullDownRefreshCount']);
</script>
<style></style>

3
niucloud/addon/hello_world/uni-app/locale/en.json

@ -0,0 +1,3 @@
{
"hello_world.pages.index": "hello_world index"
}

3
niucloud/addon/hello_world/uni-app/locale/zh-Hans.json

@ -0,0 +1,3 @@
{
"hello_world.pages.index": "hello_world首页"
}

7
niucloud/addon/hello_world/uni-app/locale/zh-Hans/pages.index.json

@ -0,0 +1,7 @@
{
"list": "文章列表",
"noData": "~ 暂无数据 ~",
"all": "全部",
"end": "-- 到底了 --",
"searchPlaceholder": "请输入搜索关键词"
}

25
niucloud/addon/hello_world/uni-app/pages/index.vue

@ -0,0 +1,25 @@
<template>
<view class="bg-gray-100 min-h-[100vh]">
<view class="fixed top-0 inset-x-0 z-10">
hello_world
</view>
<tabbar />
</view>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { t } from '@/locale'
import { useShare } from '@/hooks/useShare'
const { setShare, onShareAppMessage, onShareTimeline } = useShare()
setShare()
onShareAppMessage()
onShareTimeline()
</script>
<style lang="scss" scoped>
</style>

36
niucloud/addon/hygl/Addon.php

@ -0,0 +1,36 @@
<?php
namespace addon\hygl;
/**
* 插件安装之后单独的插件方法
*/
class Addon
{
/**
* 插件安装执行
*/
public function install()
{
return true;
}
/**
* 插件卸载执行
*/
public function uninstall()
{
return true;
}
/**
* 插件升级执行
*/
public function upgrade()
{
return true;
}
}

52
niucloud/addon/hygl/admin/api/advertising.ts

@ -0,0 +1,52 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_advertising
/**
* 广
* @param params
* @returns
*/
export function getAdvertisingList(params: Record<string, any>) {
return request.get(`hygl/advertising`, {params})
}
/**
* 广
* @param id 广id
* @returns
*/
export function getAdvertisingInfo(id: number) {
return request.get(`hygl/advertising/${id}`);
}
/**
* 广
* @param params
* @returns
*/
export function addAdvertising(params: Record<string, any>) {
return request.post('hygl/advertising', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
* 广
* @param id
* @param params
* @returns
*/
export function editAdvertising(params: Record<string, any>) {
return request.put(`hygl/advertising/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
* 广
* @param id
* @returns
*/
export function deleteAdvertising(id: number) {
return request.delete(`hygl/advertising/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
// USER_CODE_END -- hygl_advertising

29
niucloud/addon/hygl/admin/api/common.ts

@ -0,0 +1,29 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_common
/**
*
* @param params
* @returns
*/
export function uploadFile(params: FormData) {
let config = {
headers: {
"Content-Type": "multipart/form-data",
}
}
return request.post('hygl/uploadFile', params,config)
}
/**
*
* @param params
*/
export function getWithCouponsList(params: Record<string,any>){
return request.get('hygl/getCouponsList', {params})
}
// USER_CODE_END -- hygl_common

60
niucloud/addon/hygl/admin/api/config.ts

@ -0,0 +1,60 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_config
/**
*
* @param params
* @returns
*/
export function getConfigList(params: Record<string, any>) {
return request.get(`hygl/config`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getConfigInfo(id: number) {
return request.get(`hygl/config/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addConfig(params: Record<string, any>) {
return request.post('hygl/config', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editConfig(params: Record<string, any>) {
return request.put(`hygl/config/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteConfig(id: number) {
return request.delete(`hygl/config/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
/**
* H5站点二维码
* @param id
*/
export function resetH5SiteQRCode(id: number) {
return request.get(`hygl/config/resetH5SiteQRCode/${id}`);
}
// USER_CODE_END -- hygl_config

52
niucloud/addon/hygl/admin/api/coupons.ts

@ -0,0 +1,52 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_coupons
/**
*
* @param params
* @returns
*/
export function getCouponsList(params: Record<string, any>) {
return request.get(`hygl/coupons`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getCouponsInfo(id: number) {
return request.get(`hygl/coupons/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addCoupons(params: Record<string, any>) {
return request.post('hygl/coupons', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editCoupons(params: Record<string, any>) {
return request.put(`hygl/coupons/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteCoupons(id: number) {
return request.delete(`hygl/coupons/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
// USER_CODE_END -- hygl_coupons

7
niucloud/addon/hygl/admin/api/hello_world.ts

@ -0,0 +1,7 @@
import request from '@/utils/request'
/***************************************************** hello world ****************************************************/
export function getHelloWorld() {
return request.get(`hygl/hello_world`)
}

52
niucloud/addon/hygl/admin/api/transaction_history.ts

@ -0,0 +1,52 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_transaction_history
/**
*
* @param params
* @returns
*/
export function getTransactionHistoryList(params: Record<string, any>) {
return request.get(`hygl/transaction_history`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getTransactionHistoryInfo(id: number) {
return request.get(`hygl/transaction_history/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addTransactionHistory(params: Record<string, any>) {
return request.post('hygl/transaction_history', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editTransactionHistory(params: Record<string, any>) {
return request.put(`hygl/transaction_history/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteTransactionHistory(id: number) {
return request.delete(`hygl/transaction_history/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
// USER_CODE_END -- hygl_transaction_history

61
niucloud/addon/hygl/admin/api/user.ts

@ -0,0 +1,61 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_user
/**
*
* @param params
* @returns
*/
export function getUserList(params: Record<string, any>) {
return request.get(`hygl/user`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getUserInfo(id: number) {
return request.get(`hygl/user/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addUser(params: Record<string, any>) {
return request.post('hygl/user', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editUser(params: Record<string, any>) {
return request.put(`hygl/user/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteUser(id: number) {
return request.delete(`hygl/user/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
//获取全部站点
export function getWithSiteList(params: Record<string, any>) {
return request.get('hygl/site', {params})
}
//获取全部用户
export function getWithUserList(params: Record<string, any>) {
return request.get('hygl/user', {params})
}
// USER_CODE_END -- hygl_user

54
niucloud/addon/hygl/admin/api/user_coupons.ts

@ -0,0 +1,54 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- hygl_user_coupons
/**
*
* @param params
* @returns
*/
export function getUserCouponsList(params: Record<string, any>) {
return request.get(`hygl/user_coupons`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getUserCouponsInfo(id: number) {
return request.get(`hygl/user_coupons/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addUserCoupons(params: Record<string, any>) {
return request.post('hygl/user_coupons', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editUserCoupons(params: Record<string, any>) {
return request.put(`hygl/user_coupons/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteUserCoupons(id: number) {
return request.delete(`hygl/user_coupons/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
export function getWithUserList(params: Record<string,any>){
return request.get('hygl/user', {params})
}
// USER_CODE_END -- hygl_user_coupons

17
niucloud/addon/hygl/admin/lang/zh-cn/advertising.advertising.json

@ -0,0 +1,17 @@
{
"id":"序号",
"siteId":"站点",
"siteIdPlaceholder":"请输入站点",
"imgUrl":"广告图",
"imgUrlPlaceholder":"请输入广告图",
"skipUrl":"跳转链接",
"skipUrlPlaceholder":"请输入跳转链接",
"sort":"排序",
"sortPlaceholder":"请输入排序",
"createTime":"创建时间",
"addAdvertising":"添加广告管理",
"updateAdvertising":"编辑广告管理",
"advertisingDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

33
niucloud/addon/hygl/admin/lang/zh-cn/config.config.json

@ -0,0 +1,33 @@
{
"id":"id",
"siteId":"站点id",
"siteIdPlaceholder":"请输入站点id",
"weChatPayAppid":"微信支付-APP的id",
"weChatPayAppidPlaceholder":"请输入微信支付-APP的id",
"weChatPayAppId":"微信支付-公众号APPID",
"weChatPayAppIdPlaceholder":"请输入微信支付-公众号APPID",
"weChatPayMiniappId":"微信支付-小程序APPID",
"weChatPayMiniappIdPlaceholder":"请输入微信支付-小程序APPID",
"weChatPayMchId":"微信支付-商户号",
"weChatPayMchIdPlaceholder":"请输入微信支付-商户号",
"weChatPayKey":"微信支付-商户号秘钥",
"weChatPayKeyPlaceholder":"请输入微信支付-商户号秘钥",
"weChatPayMiniappSecret":"微信支付-小程序secret",
"weChatPayMiniappSecretPlaceholder":"请输入微信支付-小程序secret",
"weChatPayNotifyUrl":"微信支付-异步回调地址",
"weChatPayNotifyUrlPlaceholder":"请输入微信支付-异步回调地址",
"alipayAppId":"支付宝-appid",
"alipayAppIdPlaceholder":"请输入支付宝-appid",
"alipayRsaPrivateKey":"支付宝-开发者私钥",
"alipayRsaPrivateKeyPlaceholder":"请输入支付宝-开发者私钥",
"alipayPublicKey":"支付宝-支付宝公钥",
"alipayPublicKeyPlaceholder":"请输入支付宝-支付宝公钥",
"alipayNotifyUrl":"支付宝-异步回调地址",
"alipayNotifyUrlPlaceholder":"请输入支付宝-异步回调地址",
"createTime":"创建时间",
"addConfig":"添加配置项",
"updateConfig":"编辑配置项",
"configDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

26
niucloud/addon/hygl/admin/lang/zh-cn/coupons.coupons.json

@ -0,0 +1,26 @@
{
"id": "id",
"siteId": "站点id",
"siteIdPlaceholder": "请输入站点id",
"name": "卡券名字",
"namePlaceholder": "请输入卡券名字",
"nominalValue": "卡券面值",
"nominalValuePlaceholder": "请输入卡券面值",
"stock": "卡券库存",
"stockPlaceholder": "请输入卡券库存",
"isShow": "是否展示",
"isShowPlaceholder": "请输入是否展示",
"isLongTermValid": "是否长期有效",
"isLongTermValidPlaceholder": "请输入是否长期有效",
"createTime": "创建时间",
"addCoupons": "添加优惠券",
"updateCoupons": "编辑优惠券",
"couponsDeleteTips": "确定要删除该数据吗?",
"startDate": "请选择开始时间",
"endDate": "请选择结束时间",
"validFrom": "有效期开始时间",
"validUntil": "有效期截止时间",
"validTime": "有效期",
"isObsolete": "是否作废",
"isObsoletePlaceholder": "请输入是否作废"
}

1
niucloud/addon/hygl/admin/lang/zh-cn/hello_world.index.json

@ -0,0 +1 @@
{}

33
niucloud/addon/hygl/admin/lang/zh-cn/transaction_history.transaction_history.json

@ -0,0 +1,33 @@
{
"id":"序号",
"siteId":"站点id",
"siteIdPlaceholder":"请输入站点id",
"userId":"用户",
"userIdPlaceholder":"请输入用户",
"remark":"用户备注",
"remarkPlaceholder":"请输入用户备注",
"orderNum":"我方订单号",
"orderNumPlaceholder":"请输入我方订单号",
"payNum":"支付平台订单号",
"payNumPlaceholder":"请输入支付平台订单号",
"payType":"支付方式",
"payTypePlaceholder":"请输入支付方式",
"price":"订单应付金额(元)",
"pricePlaceholder":"请输入订单应付金额(元)",
"cashFee":"用户实际支付金额(元)",
"cashFeePlaceholder":"请输入用户实际支付金额(元)",
"payStatus":"是否完成支付",
"payStatusPlaceholder":"请输入是否完成支付",
"payTime":"用户付款时间",
"payTimePlaceholder":"请输入用户付款时间",
"payDataJson":"支付回调json字符串|默认null,支付成功后异步回调的值",
"payDataJsonPlaceholder":"请输入支付回调json字符串|默认null,支付成功后异步回调的值",
"createTime":"创建时间",
"createTimePlaceholder":"请输入创建时间",
"addTransactionHistory":"添加会员交易记录",
"updateTransactionHistory":"编辑会员交易记录",
"transactionHistoryDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间",
"couponsInfo":"优惠券使用"
}

34
niucloud/addon/hygl/admin/lang/zh-cn/user.user.json

@ -0,0 +1,34 @@
{
"id":"id",
"idPlaceholder":"请输入",
"siteId":"站点id",
"siteIdPlaceholder":"请输入站点id",
"tel":"联系电话",
"telPlaceholder":"请输入联系电话",
"name":"姓名",
"namePlaceholder":"请输入姓名",
"pic":"用户头像|相对路径",
"picPlaceholder":"请输入用户头像",
"password":"密码",
"passwordPlaceholder":"请输入密码",
"pid":"用户上级",
"pidPlaceholder":"请输入用户上级",
"level":"会员层级",
"levelPlaceholder":"请输入会员层级",
"wxOpenid":"微信小程序openid",
"wxOpenidPlaceholder":"请输入微信小程序openid",
"wxUnionid":"微信unionid",
"wxUnionidPlaceholder":"请输入微信unionid",
"sex":"性别",
"sexPlaceholder":"请输入性别",
"birthday":"生日",
"birthdayPlaceholder":"请输入生日",
"isShow":"是否可用",
"isShowPlaceholder":"请输入是否可用",
"createTime":"创建时间",
"addUser":"添加会员管理",
"updateUser":"编辑会员管理",
"userDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

21
niucloud/addon/hygl/admin/lang/zh-cn/user_coupons.user_coupons.json

@ -0,0 +1,21 @@
{
"id":"id",
"userId":"用户id",
"userIdPlaceholder":"全部",
"siteId":"站点id",
"siteIdPlaceholder":"请输入站点id",
"couponsId":"卡券名字",
"couponsIdPlaceholder":"请输入卡券名字",
"nominalValue":"卡券面值",
"nominalValuePlaceholder":"请输入卡券面值",
"isShow":"是否可用",
"isShowPlaceholder":"请输入是否可用",
"createTime":"创建时间",
"createTimePlaceholder":"请输入创建时间",
"addUserCoupons":"添加用户优惠券",
"updateUserCoupons":"编辑用户优惠券",
"userCouponsDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间",
"validTime":"有效期"
}

171
niucloud/addon/hygl/admin/views/advertising/advertising.vue

@ -0,0 +1,171 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{ pageName }}</span>
<el-button type="primary" @click="addEvent">
{{ t('addAdvertising') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="advertisingTable.searchParam" ref="searchFormRef">
<el-form-item>
<el-button type="primary" @click="loadAdvertisingList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="advertisingTable.data" size="large" v-loading="advertisingTable.loading">
<template #empty>
<span>{{ !advertisingTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('imgUrl')" width="100" align="left">
<template #default="{ row }">
<el-avatar v-if="row.img_url" :src="img(row.img_url)"/>
<el-avatar v-else icon="UserFilled"/>
</template>
</el-table-column>
<el-table-column prop="skip_url" :label="t('skipUrl')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="sort" :label="t('sort')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="advertisingTable.page" v-model:page-size="advertisingTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="advertisingTable.total"
@size-change="loadAdvertisingList()" @current-change="loadAdvertisingList"/>
</div>
</div>
<edit ref="editAdvertisingDialog" @complete="loadAdvertisingList"/>
</el-card>
</div>
</template>
<script lang="ts" setup>
import {reactive, ref, watch} from 'vue'
import {t} from '@/lang'
import {useDictionary} from '@/app/api/dict'
import {getAdvertisingList, deleteAdvertising,} from '@/addon/hygl/api/advertising'
import {img} from '@/utils/common'
import {ElMessageBox, FormInstance} from 'element-plus'
import Edit from '@/addon/hygl/views/advertising/components/advertising-edit.vue'
import {useRoute} from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let advertisingTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取广告管理列表
*/
const loadAdvertisingList = (page: number = 1) => {
advertisingTable.loading = true
advertisingTable.page = page
getAdvertisingList({
page: advertisingTable.page,
limit: advertisingTable.limit,
...advertisingTable.searchParam
}).then(res => {
advertisingTable.loading = false
advertisingTable.data = res.data.data
advertisingTable.total = res.data.total
}).catch(() => {
advertisingTable.loading = false
})
}
loadAdvertisingList()
const editAdvertisingDialog: Record<string, any> | null = ref(null)
/**
* 添加广告管理
*/
const addEvent = () => {
editAdvertisingDialog.value.setFormData()
editAdvertisingDialog.value.showDialog = true
}
/**
* 编辑广告管理
* @param data
*/
const editEvent = (data: any) => {
editAdvertisingDialog.value.setFormData(data)
editAdvertisingDialog.value.showDialog = true
}
/**
* 删除广告管理
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('advertisingDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteAdvertising(id).then(() => {
loadAdvertisingList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadAdvertisingList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

174
niucloud/addon/hygl/admin/views/advertising/components/advertising-edit.vue

@ -0,0 +1,174 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateAdvertising') : t('addAdvertising')" width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-form-item :label="t('imgUrl')">
<upload-image v-model="formData.img_url"/>
</el-form-item>
<el-form-item :label="t('skipUrl')">
<el-input v-model="formData.skip_url" clearable :placeholder="t('skipUrlPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('sort')" prop="sort">
<el-input-number v-model="formData.sort" clearable :placeholder="t('sortPlaceholder')" class="input-width"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {ref, reactive, computed, watch} from 'vue'
import {useDictionary} from '@/app/api/dict'
import {t} from '@/lang'
import type {FormInstance} from 'element-plus'
import {addAdvertising, editAdvertising, getAdvertisingInfo,} from '@/addon/hygl/api/advertising'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
img_url: '',
skip_url: '',
sort: '1',
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
img_url: [
{required: true, message: t('imgUrlPlaceholder'), trigger: 'blur'},
]
,
skip_url: [
{required: true, message: t('skipUrlPlaceholder'), trigger: 'blur'},
]
,
sort: [
{required: true, message: t('sortPlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (value && !/^\d{1,9999}$/.test(value)) {
callback(new Error(t('generateBetween')))
} else {
callback()
}
}
},
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editAdvertising : addAdvertising
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getAdvertisingInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

245
niucloud/addon/hygl/admin/views/config/components/config-edit.vue

@ -0,0 +1,245 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateConfig') : t('addConfig')" width="50%" class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('weChatPayAppid')" >
<el-input v-model="formData.we_chat_pay_appid" clearable :placeholder="t('weChatPayAppidPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('weChatPayAppId')" >
<el-input v-model="formData.we_chat_pay_app_id" clearable :placeholder="t('weChatPayAppIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('weChatPayMiniappId')" >
<el-input v-model="formData.we_chat_pay_miniapp_id" clearable :placeholder="t('weChatPayMiniappIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('weChatPayMchId')" >
<el-input v-model="formData.we_chat_pay_mch_id" clearable :placeholder="t('weChatPayMchIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('weChatPayKey')" >
<el-input v-model="formData.we_chat_pay_key" clearable :placeholder="t('weChatPayKeyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('weChatPayMiniappSecret')" >
<el-input v-model="formData.we_chat_pay_miniapp_secret" clearable :placeholder="t('weChatPayMiniappSecretPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('weChatPayNotifyUrl')" prop="we_chat_pay_notify_url">
<el-input v-model="formData.we_chat_pay_notify_url" clearable :placeholder="t('weChatPayNotifyUrlPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('alipayAppId')" >
<el-input v-model="formData.alipay_appId" clearable :placeholder="t('alipayAppIdPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('alipayRsaPrivateKey')" >
<el-input v-model="formData.alipay_rsa_private_key" clearable :placeholder="t('alipayRsaPrivateKeyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('alipayPublicKey')" >
<el-input v-model="formData.alipay_public_key" clearable :placeholder="t('alipayPublicKeyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('alipayNotifyUrl')" prop="alipay_notify_url">
<el-input v-model="formData.alipay_notify_url" clearable :placeholder="t('alipayNotifyUrlPlaceholder')" class="input-width" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addConfig, editConfig, getConfigInfo, } from '@/addon/hygl/api/config'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
we_chat_pay_appid: '',
we_chat_pay_app_id: '',
we_chat_pay_miniapp_id: '',
we_chat_pay_mch_id: '',
we_chat_pay_key: '',
we_chat_pay_miniapp_secret: '',
we_chat_pay_notify_url: '',
alipay_appId: '',
alipay_rsa_private_key: '',
alipay_public_key: '',
alipay_notify_url: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
we_chat_pay_appid: [
{ required: true, message: t('weChatPayAppidPlaceholder'), trigger: 'blur' },
]
,
we_chat_pay_app_id: [
{ required: true, message: t('weChatPayAppIdPlaceholder'), trigger: 'blur' },
]
,
we_chat_pay_miniapp_id: [
{ required: true, message: t('weChatPayMiniappIdPlaceholder'), trigger: 'blur' },
]
,
we_chat_pay_mch_id: [
{ required: true, message: t('weChatPayMchIdPlaceholder'), trigger: 'blur' },
]
,
we_chat_pay_key: [
{ required: true, message: t('weChatPayKeyPlaceholder'), trigger: 'blur' },
]
,
we_chat_pay_miniapp_secret: [
{ required: true, message: t('weChatPayMiniappSecretPlaceholder'), trigger: 'blur' },
]
,
we_chat_pay_notify_url: [
{ required: true, message: t('weChatPayNotifyUrlPlaceholder'), trigger: 'blur' },
]
,
alipay_appId: [
{ required: true, message: t('alipayAppIdPlaceholder'), trigger: 'blur' },
]
,
alipay_rsa_private_key: [
{ required: true, message: t('alipayRsaPrivateKeyPlaceholder'), trigger: 'blur' },
]
,
alipay_public_key: [
{ required: true, message: t('alipayPublicKeyPlaceholder'), trigger: 'blur' },
]
,
alipay_notify_url: [
{ required: true, message: t('alipayNotifyUrlPlaceholder'), trigger: 'blur' },
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editConfig : addConfig
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if(row){
const data = await (await getConfigInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label{
height: auto !important;
}
</style>

354
niucloud/addon/hygl/admin/views/config/config.vue

@ -0,0 +1,354 @@
<template>
<div class="main-container">
<div class="detail-head">
<!-- <div class="left" @click="back()">-->
<!-- <span class="iconfont iconxiangzuojiantou !text-xs"></span>-->
<!-- <span class="ml-[1px]">{{ t('returnToPreviousPage') }}</span>-->
<!-- </div>-->
<!-- <span class="adorn">|</span>-->
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<el-form :model="formData" label-width="270px" ref="formRef" :rules="formRules" class="page-form">
<!--
<el-form-item :label="t('weChatPayAppid')">
<el-input v-model="formData.we_chat_pay_appid" clearable :placeholder="t('weChatPayAppidPlaceholder')"
class="input-width"/>
</el-form-item>
-->
<el-form-item :label="t('weChatPayAppId')" prop="we_chat_pay_app_id">
<el-input v-model="formData.we_chat_pay_app_id" clearable :placeholder="t('weChatPayAppIdPlaceholder')"
class="input-width"/>
</el-form-item>
<!--
<el-form-item :label="t('weChatPayMiniappId')">
<el-input v-model="formData.we_chat_pay_miniapp_id" clearable
:placeholder="t('weChatPayMiniappIdPlaceholder')" class="input-width"/>
</el-form-item>
-->
<el-form-item :label="t('weChatPayMchId')" prop="we_chat_pay_mch_id">
<el-input v-model="formData.we_chat_pay_mch_id" clearable :placeholder="t('weChatPayMchIdPlaceholder')"
class="input-width"/>
</el-form-item>
<el-form-item :label="t('weChatPayKey')" prop="we_chat_pay_key">
<el-input v-model="formData.we_chat_pay_key" clearable :placeholder="t('weChatPayKeyPlaceholder')"
class="input-width"/>
</el-form-item>
<!--
<el-form-item :label="t('weChatPayMiniappSecret')">
<el-input v-model="formData.we_chat_pay_miniapp_secret" clearable
:placeholder="t('weChatPayMiniappSecretPlaceholder')" class="input-width"/>
</el-form-item>
-->
<el-form-item :label="t('weChatPayNotifyUrl')" prop="we_chat_pay_notify_url">
<el-input disabled="true" v-model="formData.we_chat_pay_notify_url" clearable
:placeholder="t('weChatPayNotifyUrlPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('上传微信商户私钥(apiclient_key.pem)')" prop="we_chat_pay_mch_secret_cert">
<el-input v-model="formData.we_chat_pay_mch_secret_cert" clearable
:placeholder="t('请上传商户私钥')" class="input-width"/>
<div>
<input type="file"
@change="handleFileUpload($event,'we_chat_pay_mch_secret_cert','config_we_chat_pay_mch_secret_cert')">
</div>
</el-form-item>
<el-form-item :label="t('上传微信商户公钥(apiclient_cert.pem)')" prop="we_chat_pay_mch_public_cert_path">
<el-input v-model="formData.we_chat_pay_mch_public_cert_path" clearable
:placeholder="t('请上传商户公钥')" class="input-width"/>
<input type="file"
@change="handleFileUpload($event,'we_chat_pay_mch_public_cert_path','config_we_chat_pay_mch_public_cert_path')">
</el-form-item>
<!--
<el-form-item :label="t('alipayAppId')">
<el-input v-model="formData.alipay_appId" clearable :placeholder="t('alipayAppIdPlaceholder')"
class="input-width"/>
</el-form-item>
<el-form-item :label="t('alipayRsaPrivateKey')">
<el-input v-model="formData.alipay_rsa_private_key" clearable
:placeholder="t('alipayRsaPrivateKeyPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('alipayPublicKey')">
<el-input v-model="formData.alipay_public_key" clearable :placeholder="t('alipayPublicKeyPlaceholder')"
class="input-width"/>
</el-form-item>
<el-form-item :label="t('alipayNotifyUrl')" prop="alipay_notify_url">
<el-input v-model="formData.alipay_notify_url" clearable :placeholder="t('alipayNotifyUrlPlaceholder')"
class="input-width"/>
</el-form-item>
-->
<el-form-item :label="t('H5站点地址')" prop="h5_site_url">
<el-input disabled="true" v-model="formData.h5_site_url" clearable
:placeholder="t('H5站点地址')"
class="input-width"/>
</el-form-item>
<el-form-item :label="t('H5站点二维码')" prop="h5_qrcode_url">
<el-input disabled="true" v-model="formData.h5_qrcode_url" clearable :placeholder="t('H5站点二维码')"
class="input-width"/>
<el-button style="margin-left: 15px;" type="primary" @click="resetQrCode()">{{ t('重新生成二维码') }}</el-button>
</el-form-item>
<el-form-item v-if="formData.ol_h5_qrcode_url" :label="t('原始H5站点二维码')" prop="h5_qrcode_url">
<div>
<p style="color: red;">重新生成二维码后->点击"保存"将替换此二维码</p>
<img :src="formData.ol_h5_qrcode_url" alt="">
<a :href="formData.ol_h5_qrcode_url" target="downloadFile" download="h5_qrcode.png">
<el-button type="primary">打开二维码</el-button>
</a>
</div>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" @click="onSave(formRef)">{{ t('save') }}</el-button>
<!-- <el-button @click="back()">{{ t('cancel') }}</el-button>-->
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {ref, reactive, computed, watch} from 'vue'
import {t} from '@/lang'
import {useDictionary} from '@/app/api/dict'
import type {FormInstance} from 'element-plus'
import {getConfigInfo, addConfig, editConfig, getConfigList, resetH5SiteQRCode,} from '@/addon/hygl/api/config';
import {useRoute} from 'vue-router'
import {ElMessage} from 'element-plus'
import {uploadFile} from "@/addon/hygl/api/common";
const route = useRoute()
const id: number = parseInt(route.query.id);
const loading = ref(false)
const pageName = route.meta.title
/**
* 表单数据
*/
const initialFormData = {
id: 0,
we_chat_pay_appid: '',
we_chat_pay_app_id: '',
we_chat_pay_miniapp_id: '',
we_chat_pay_mch_id: '',
we_chat_pay_key: '',
we_chat_pay_miniapp_secret: '',
we_chat_pay_notify_url: '',
alipay_appId: '',
alipay_rsa_private_key: '',
alipay_public_key: '',
alipay_notify_url: '',
we_chat_pay_mch_secret_cert: '',
we_chat_pay_mch_public_cert_path: '',
h5_site_url:'',
h5_qrcode_url:'',
ol_h5_qrcode_url:'',
}
const formData: Record<string, any> = reactive({...initialFormData})
const setFormData = async (id: number = 0) => {
Object.assign(formData, initialFormData)
const data = await (await getConfigInfo(id)).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
setFormData();
const formRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
//
const formRules = computed(() => {
return {
we_chat_pay_appid: [
{required: true, message: t('weChatPayAppidPlaceholder'), trigger: 'blur'},
],
we_chat_pay_app_id: [
{required: true, message: t('weChatPayAppIdPlaceholder'), trigger: 'blur'},
]
,
we_chat_pay_miniapp_id: [
{required: true, message: t('weChatPayMiniappIdPlaceholder'), trigger: 'blur'},
]
,
we_chat_pay_mch_id: [
{required: true, message: t('weChatPayMchIdPlaceholder'), trigger: 'blur'},
]
,
we_chat_pay_key: [
{required: true, message: t('weChatPayKeyPlaceholder'), trigger: 'blur'},
]
,
we_chat_pay_miniapp_secret: [
{required: true, message: t('weChatPayMiniappSecretPlaceholder'), trigger: 'blur'},
]
,
we_chat_pay_notify_url: [
{required: true, message: t('weChatPayNotifyUrlPlaceholder'), trigger: 'blur'},
]
,
we_chat_pay_mch_secret_cert: [
{required: true, message: t('商户私钥必传'), trigger: 'blur'},
],
we_chat_pay_mch_public_cert_path: [
{required: true, message: t('商户公钥必传'), trigger: 'blur'},
],
alipay_appId: [
{required: true, message: t('alipayAppIdPlaceholder'), trigger: 'blur'},
],
alipay_rsa_private_key: [
{required: true, message: t('alipayRsaPrivateKeyPlaceholder'), trigger: 'blur'},
]
,
alipay_public_key: [
{required: true, message: t('alipayPublicKeyPlaceholder'), trigger: 'blur'},
]
,
alipay_notify_url: [
{required: true, message: t('alipayNotifyUrlPlaceholder'), trigger: 'blur'},
]
,
}
})
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
const save = editConfig
save(data).then(res => {
loading.value = false
setFormData()//
// history.back()
}).catch(err => {
loading.value = false
})
}
})
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
const back = () => {
history.back()
}
//
const resetQrCode = async () => {
let data = formData
if (!data.id) {
ElMessage({
message: '请先填写必要信息并点击保存后再试',
type: 'warning',
})
return
}
let aa = resetH5SiteQRCode(data.id).then(res => {
if (res.code){
formData.h5_qrcode_url = res.data.url
}
// history.back()
}).catch(err => {
console.log(err)
})
}
//()
const handleFileUpload = (event: Event, name: string, path: string) => {
const fileInput = event.target as HTMLInputElement;
if (!fileInput.files || fileInput.files.length === 0) {
return;
}
const file = fileInput.files[0];
let form_data = new FormData();
form_data.append('file', file); // 使 file
form_data.append('path', path); // 使 path
uploadFile(form_data).then(res => {
console.log(222, res)
if (res.code) {
formData[name] = res.data.file_path
}
// loading.value = false
// history.back()
}).catch(err => {
// loading.value = false
})
};
</script>
<style lang="scss" scoped></style>

238
niucloud/addon/hygl/admin/views/coupons/components/coupons-edit.vue

@ -0,0 +1,238 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateCoupons') : t('addCoupons')" width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-form-item :label="t('name')" prop="name">
<el-input v-model="formData.name" clearable :placeholder="t('namePlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('nominalValue')" prop="nominal_value">
<el-input-number v-model="formData.nominal_value" clearable :placeholder="t('nominalValuePlaceholder')"
class="input-width"/>
</el-form-item>
<el-form-item :label="t('stock')" prop="stock">
<el-input-number v-model="formData.stock" clearable :placeholder="t('stockPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('isShow')" prop="is_show">
<el-radio-group v-model="formData.is_show" :placeholder="t('isShowPlaceholder')">
<el-radio
v-for="(item, index) in is_showList"
:key="index"
:label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('isObsolete')" prop="is_obsolete">
<el-radio-group v-model="formData.is_obsolete" :placeholder="t('isObsoletePlaceholder')">
<el-radio label="1"></el-radio>
<el-radio label="0"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('isLongTermValid')" prop="is_long_term_valid">
<el-radio-group v-model="formData.is_long_term_valid" :placeholder="t('isLongTermValidPlaceholder')">
<el-radio label="1"></el-radio>
<el-radio label="0"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-show="formData.is_long_term_valid !=='1'" :label="t('validTime')" prop="valid_time">
<el-date-picker v-model="formData.valid_time" type="daterange"
value-format="YYYY-MM-DD"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {ref, reactive, computed, watch} from 'vue'
import {useDictionary} from '@/app/api/dict'
import {t} from '@/lang'
import type {FormInstance} from 'element-plus'
import {addCoupons, editCoupons, getCouponsInfo,} from '@/addon/hygl/api/coupons'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
name: '',
nominal_value: '',
stock: '100',
is_show: '1',
is_long_term_valid: '1',
is_obsolete: '0',
valid_time: [],
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
name: [
{required: true, message: t('namePlaceholder'), trigger: 'blur'},
]
,
nominal_value: [
{ required: true, message: t('nominalValuePlaceholder'), trigger: 'blur' },
{
validator: (rule: any, value: string, callback: any) => {
const floatValue = parseFloat(value);
if (isNaN(floatValue) || floatValue <= 0 || floatValue > 99999 || !/^\d+(\.\d{1,2})?$/.test(value)) {
callback(new Error(t('请输入0.1-99999')))
} else {
callback()
}
}
},
]
,
stock: [
{required: true, message: t('stockPlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (value && !/^\d{0,99999}$/.test(value)) {
callback(new Error(t('generateBetween')))
} else {
callback()
}
}
},
]
,
is_show: [
{required: true, message: t('isShowPlaceholder'), trigger: 'blur'},
]
,
is_long_term_valid: [
{required: true, message: t('isLongTermValidPlaceholder'), trigger: 'blur'},
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editCoupons : addCoupons
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
let is_showList = ref([])
const is_showDictList = async () => {
is_showList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
is_showDictList();
watch(() => is_showList.value, () => {
formData.is_show = is_showList.value[0].value
})
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getCouponsInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

227
niucloud/addon/hygl/admin/views/coupons/coupons.vue

@ -0,0 +1,227 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{ pageName }}</span>
<el-button type="primary" @click="addEvent">
{{ t('addCoupons') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="couponsTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('name')" prop="name">
<el-input v-model="couponsTable.searchParam.name" :placeholder="t('namePlaceholder')"/>
</el-form-item>
<el-form-item :label="t('nominalValue')" prop="nominal_value">
<range-input v-model="couponsTable.searchParam.nominal_value"/>
</el-form-item>
<el-form-item :label="t('isShow')" prop="is_show">
<el-select class="w-[280px]" v-model="couponsTable.searchParam.is_show" clearable
:placeholder="t('isShowPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in is_showList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadCouponsList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="couponsTable.data" size="large" v-loading="couponsTable.loading">
<template #empty>
<span>{{ !couponsTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="name" :label="t('name')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="nominal_value" :label="t('nominalValue')" min-width="120"
:show-overflow-tooltip="true"/>
<el-table-column prop="stock" :label="t('stock')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('isShow')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in is_showList">
<div v-if="item.value == row.is_show">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('isObsolete')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in is_showList">
<div v-if="item.value == row.is_obsolete">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('isLongTermValid')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in is_showList">
<div v-if="item.value == row.is_long_term_valid">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('validTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.valid_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="couponsTable.page" v-model:page-size="couponsTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="couponsTable.total"
@size-change="loadCouponsList()" @current-change="loadCouponsList"/>
</div>
</div>
<edit ref="editCouponsDialog" @complete="loadCouponsList"/>
</el-card>
</div>
</template>
<script lang="ts" setup>
import {reactive, ref, watch} from 'vue'
import {t} from '@/lang'
import {useDictionary} from '@/app/api/dict'
import {getCouponsList, deleteCoupons,} from '@/addon/hygl/api/coupons'
import {img} from '@/utils/common'
import {ElMessageBox, FormInstance} from 'element-plus'
import Edit from '@/addon/hygl/views/coupons/components/coupons-edit.vue'
import {useRoute} from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let couponsTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
"name": "",
"nominal_value": [],
"is_show": ""
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const is_showList = ref([] as any[])
const is_showDictList = async () => {
is_showList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
is_showDictList();
/**
* 获取优惠券列表
*/
const loadCouponsList = (page: number = 1) => {
couponsTable.loading = true
couponsTable.page = page
getCouponsList({
page: couponsTable.page,
limit: couponsTable.limit,
...couponsTable.searchParam
}).then(res => {
couponsTable.loading = false
couponsTable.data = res.data.data
couponsTable.total = res.data.total
}).catch(() => {
couponsTable.loading = false
})
}
loadCouponsList()
const editCouponsDialog: Record<string, any> | null = ref(null)
/**
* 添加优惠券
*/
const addEvent = () => {
editCouponsDialog.value.setFormData()
editCouponsDialog.value.showDialog = true
}
/**
* 编辑优惠券
* @param data
*/
const editEvent = (data: any) => {
editCouponsDialog.value.setFormData(data)
editCouponsDialog.value.showDialog = true
}
/**
* 删除优惠券
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('couponsDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteCoupons(id).then(() => {
loadCouponsList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadCouponsList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

17
niucloud/addon/hygl/admin/views/hello_world/index.vue

@ -0,0 +1,17 @@
<template>
<span class="text-[20px]">{{hello_world_text}}</span>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { getHelloWorld } from '@/addon/hygl/api/hello_world'
const hello_world_text = ref('');
const getHelloWorldInfo = async () => {
hello_world_text.value = await (await getHelloWorld()).data
}
getHelloWorldInfo()
</script>
<style lang="scss" scoped>
</style>

295
niucloud/addon/hygl/admin/views/transaction_history/components/transaction-history-edit.vue

@ -0,0 +1,295 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateTransactionHistory') : t('addTransactionHistory')"
width="50%" class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-form-item :label="t('userId')" prop="user_id">
<el-input v-model="formData.user_id" clearable :placeholder="t('userIdPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('remark')">
<el-input v-model="formData.remark" clearable :placeholder="t('remarkPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('orderNum')" prop="order_num">
<el-input v-model="formData.order_num" clearable :placeholder="t('orderNumPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('payNum')">
<el-input v-model="formData.pay_num" clearable :placeholder="t('payNumPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('payType')" prop="pay_type">
<el-select class="input-width" v-model="formData.pay_type" clearable :placeholder="t('payTypePlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in pay_typeList"
:key="index"
:label="item['name']"
:value="item['value']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('price')" prop="price">
<el-input-number v-model="formData.price" clearable :placeholder="t('pricePlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('cashFee')">
<el-input-number v-model="formData.cash_fee" clearable :placeholder="t('cashFeePlaceholder')"
class="input-width"/>
</el-form-item>
<el-form-item :label="t('payStatus')" prop="pay_status">
<el-radio-group v-model="formData.pay_status" :placeholder="t('payStatusPlaceholder')">
<el-radio
v-for="(item, index) in pay_statusList"
:key="index"
:label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('payTime')" class="input-width">
<el-date-picker
class="flex-1 !flex"
v-model="formData.pay_time"
clearable
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="t('payTimePlaceholder')">
</el-date-picker>
</el-form-item>
<el-form-item :label="t('payDataJson')">
<el-input v-model="formData.pay_data_json" type="textarea" rows="4" clearable
:placeholder="t('payDataJsonPlaceholder')" class="input-width"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {ref, reactive, computed, watch} from 'vue'
import {useDictionary} from '@/app/api/dict'
import {t} from '@/lang'
import type {FormInstance} from 'element-plus'
import {
addTransactionHistory,
editTransactionHistory,
getTransactionHistoryInfo,
} from '@/addon/hygl/api/transaction_history'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
user_id: '',
remark: '',
order_num: '',
pay_num: '',
pay_type: '',
price: '',
cash_fee: '',
pay_status: '0',
pay_time: '',
pay_data_json: '',
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
user_id: [
{required: true, message: t('userIdPlaceholder'), trigger: 'blur'},
]
,
remark: [
{required: true, message: t('remarkPlaceholder'), trigger: 'blur'},
]
,
order_num: [
{required: true, message: t('orderNumPlaceholder'), trigger: 'blur'},
]
,
pay_num: [
{required: true, message: t('payNumPlaceholder'), trigger: 'blur'},
]
,
pay_type: [
{required: true, message: t('payTypePlaceholder'), trigger: 'blur'},
]
,
price: [
{required: true, message: t('pricePlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (value && !/^\d{0,99999}$/.test(value)) {
callback(new Error(t('generateBetween')))
} else {
callback()
}
}
},
]
,
cash_fee: [
{required: true, message: t('cashFeePlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (value && !/^\d{0,99999}$/.test(value)) {
callback(new Error(t('generateBetween')))
} else {
callback()
}
}
},
]
,
pay_status: [
{required: true, message: t('payStatusPlaceholder'), trigger: 'blur'},
]
,
pay_time: [
{required: true, message: t('payTimePlaceholder'), trigger: 'blur'},
]
,
pay_data_json: [
{required: true, message: t('payDataJsonPlaceholder'), trigger: 'blur'},
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editTransactionHistory : addTransactionHistory
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
let pay_typeList = ref([])
const pay_typeDictList = async () => {
pay_typeList.value = await (await useDictionary('pay_type')).data.dictionary
}
pay_typeDictList();
watch(() => pay_typeList.value, () => {
formData.pay_type = pay_typeList.value[0].value
})
let pay_statusList = ref([])
const pay_statusDictList = async () => {
pay_statusList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
pay_statusDictList();
watch(() => pay_statusList.value, () => {
formData.pay_status = pay_statusList.value[0].value
})
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getTransactionHistoryInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

286
niucloud/addon/hygl/admin/views/transaction_history/transaction_history.vue

@ -0,0 +1,286 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<!-- <span class="text-lg">{{ pageName }}</span>-->
<!-- <el-button type="primary" @click="addEvent">-->
<!-- {{ t('addTransactionHistory') }}-->
<!-- </el-button>-->
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="transactionHistoryTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('userId')" prop="user_id">
<el-input v-model="transactionHistoryTable.searchParam.user_id" :placeholder="t('userIdPlaceholder')"/>
</el-form-item>
<el-form-item :label="t('orderNum')" prop="order_num">
<el-input v-model="transactionHistoryTable.searchParam.order_num" :placeholder="t('orderNumPlaceholder')"/>
</el-form-item>
<el-form-item :label="t('payNum')" prop="pay_num">
<el-input v-model="transactionHistoryTable.searchParam.pay_num" :placeholder="t('payNumPlaceholder')"/>
</el-form-item>
<el-form-item :label="t('payType')" prop="pay_type">
<el-select class="w-[280px]" v-model="transactionHistoryTable.searchParam.pay_type" clearable
:placeholder="t('payTypePlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in pay_typeList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('price')" prop="price">
<range-input v-model="transactionHistoryTable.searchParam.price"/>
</el-form-item>
<el-form-item :label="t('cashFee')" prop="cash_fee">
<range-input v-model="transactionHistoryTable.searchParam.cash_fee"/>
</el-form-item>
<el-form-item :label="t('payStatus')" prop="pay_status">
<el-select class="w-[280px]" v-model="transactionHistoryTable.searchParam.pay_status" clearable
:placeholder="t('payStatusPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in pay_statusList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('payTime')" prop="pay_time">
<el-date-picker v-model="transactionHistoryTable.searchParam.pay_time" type="daterange"
value-format="YYYY-MM-DD"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')"/>
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="transactionHistoryTable.searchParam.create_time" type="daterange"
value-format="YYYY-MM-DD"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadTransactionHistoryList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="transactionHistoryTable.data" size="large" v-loading="transactionHistoryTable.loading">
<template #empty>
<span>{{ !transactionHistoryTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="user_id" :label="t('userId')" min-width="120" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.user && row.user.name ? row.user.name + `#` + row.user.id : '顶级' }}
</template>
</el-table-column>
<!-- <el-table-column prop="remark" :label="t('remark')" min-width="120" :show-overflow-tooltip="true"/>-->
<el-table-column prop="order_num" :label="t('orderNum')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="pay_num" :label="t('payNum')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('payType')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in pay_typeList">
<div v-if="item.value == row.pay_type">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="price" :label="t('price')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('couponsInfo')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.userCoupons && row.userCoupons.coupons ? row.userCoupons.coupons.name : '' }}
</template>
</el-table-column>
<el-table-column prop="cash_fee" :label="t('cashFee')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('payStatus')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in pay_statusList">
<div v-if="item.value == row.pay_status">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('payTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.pay_time || '' }}
</template>
</el-table-column>
<!--
<el-table-column prop="pay_data_json" :label="t('payDataJson')" min-width="120"
:show-overflow-tooltip="true"/>
-->
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<!-- <el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>-->
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="transactionHistoryTable.page"
v-model:page-size="transactionHistoryTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="transactionHistoryTable.total"
@size-change="loadTransactionHistoryList()" @current-change="loadTransactionHistoryList"/>
</div>
</div>
<edit ref="editTransactionHistoryDialog" @complete="loadTransactionHistoryList"/>
</el-card>
</div>
</template>
<script lang="ts" setup>
import {reactive, ref, watch} from 'vue'
import {t} from '@/lang'
import {useDictionary} from '@/app/api/dict'
import {getTransactionHistoryList, deleteTransactionHistory,} from '@/addon/hygl/api/transaction_history'
import {img} from '@/utils/common'
import {ElMessageBox, FormInstance} from 'element-plus'
import Edit from '@/addon/hygl/views/transaction_history/components/transaction-history-edit.vue'
import {useRoute} from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let transactionHistoryTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
"user_id": "",
"order_num": "",
"pay_num": "",
"pay_type": "",
"price": [],
"cash_fee": [],
"pay_status": "",
"pay_time": [],
"create_time": []
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const pay_typeList = ref([] as any[])
const pay_typeDictList = async () => {
pay_typeList.value = await (await useDictionary('pay_type')).data.dictionary
}
pay_typeDictList();
const pay_statusList = ref([] as any[])
const pay_statusDictList = async () => {
pay_statusList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
pay_statusDictList();
/**
* 获取会员交易记录列表
*/
const loadTransactionHistoryList = (page: number = 1) => {
transactionHistoryTable.loading = true
transactionHistoryTable.page = page
getTransactionHistoryList({
page: transactionHistoryTable.page,
limit: transactionHistoryTable.limit,
...transactionHistoryTable.searchParam
}).then(res => {
transactionHistoryTable.loading = false
transactionHistoryTable.data = res.data.data
transactionHistoryTable.total = res.data.total
}).catch(() => {
transactionHistoryTable.loading = false
})
}
loadTransactionHistoryList()
const editTransactionHistoryDialog: Record<string, any> | null = ref(null)
/**
* 添加会员交易记录
*/
const addEvent = () => {
editTransactionHistoryDialog.value.setFormData()
editTransactionHistoryDialog.value.showDialog = true
}
/**
* 编辑会员交易记录
* @param data
*/
const editEvent = (data: any) => {
editTransactionHistoryDialog.value.setFormData(data)
editTransactionHistoryDialog.value.showDialog = true
}
/**
* 删除会员交易记录
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('transactionHistoryDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteTransactionHistory(id).then(() => {
loadTransactionHistoryList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadTransactionHistoryList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

311
niucloud/addon/hygl/admin/views/user/components/user-edit.vue

@ -0,0 +1,311 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateUser') : t('addUser')" width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-form-item :label="t('tel')" prop="tel">
<el-input v-model="formData.tel" clearable :placeholder="t('telPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('name')" prop="name">
<el-input v-model="formData.name" clearable :placeholder="t('namePlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('pic')">
<upload-image v-model="formData.pic"/>
</el-form-item>
<el-form-item :label="t('password')">
<el-input v-model="formData.password" clearable :placeholder="t('passwordPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('pid')" prop="pid">
<el-select class="input-width" v-model="formData.pid" clearable :placeholder="t('pidPlaceholder')">
<el-option label="顶级" :value="0"></el-option>
<el-option
v-for="(item, index) in pidList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<!-- <el-form-item :label="t('level')" prop="level">-->
<!-- <el-input v-model="formData.level" clearable :placeholder="t('levelPlaceholder')" class="input-width"/>-->
<!-- </el-form-item>-->
<el-form-item :label="t('wxOpenid')" v-show="!formData.id">
<el-input v-model="formData.wx_openid" clearable :placeholder="t('wxOpenidPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('wxUnionid')" v-show="!formData.id">
<el-input v-model="formData.wx_unionid" clearable :placeholder="t('wxUnionidPlaceholder')" class="input-width"/>
</el-form-item>
<el-form-item :label="t('sex')" prop="sex">
<el-radio-group v-model="formData.sex" :placeholder="t('sexPlaceholder')">
<el-radio
v-for="(item, index) in sexList"
:key="index"
:label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('birthday')" class="input-width">
<el-date-picker
class="flex-1 !flex"
v-model="formData.birthday"
clearable
type="date"
value-format="YYYY-MM-DD"
:placeholder="t('birthdayPlaceholder')">
</el-date-picker>
</el-form-item>
<el-form-item :label="t('isShow')" prop="is_show">
<el-radio-group v-model="formData.is_show" :placeholder="t('isShowPlaceholder')">
<el-radio
v-for="(item, index) in is_showList"
:key="index"
:label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {ref, reactive, computed, watch} from 'vue'
import {useDictionary} from '@/app/api/dict'
import {t} from '@/lang'
import type {FormInstance} from 'element-plus'
import {addUser, editUser, getUserInfo, getWithUserList,} from '@/addon/hygl/api/user'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
tel: '',
name: '',
pic: '',
password: '',
pid: 0,
// level: '',
wx_openid: '',
wx_unionid: '',
sex: '1',
birthday: '',
is_show: '1',
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
tel: [
{required: true, message: t('telPlaceholder'), trigger: 'blur'},
]
,
name: [
{required: true, message: t('namePlaceholder'), trigger: 'blur'},
]
,
pic: [
{required: true, message: t('picPlaceholder'), trigger: 'blur'},
]
,
password: [
{required: true, message: t('passwordPlaceholder'), trigger: 'blur'},
]
,
pid: [
{required: true, message: t('pidPlaceholder'), trigger: 'blur'},
]
,
level: [
{required: true, message: t('levelPlaceholder'), trigger: 'blur'},
]
,
wx_openid: [
{required: true, message: t('wxOpenidPlaceholder'), trigger: 'blur'},
]
,
wx_unionid: [
{required: true, message: t('wxUnionidPlaceholder'), trigger: 'blur'},
]
,
sex: [
{required: true, message: t('sexPlaceholder'), trigger: 'blur'},
]
,
birthday: [
{required: true, message: t('birthdayPlaceholder'), trigger: 'blur'},
]
,
is_show: [
{required: true, message: t('isShowPlaceholder'), trigger: 'blur'},
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editUser : addUser
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
let site_idList = ref([])
const site_idDictList = async () => {
site_idList.value = await (await useDictionary('placeholder_')).data.dictionary
}
site_idDictList();
watch(() => site_idList.value, () => {
formData.site_id = site_idList.value[0].value
})
//
const pidList = ref([] as any[])
const setPidList = async () => {
pidList.value = await (await getWithUserList({})).data.data
}
setPidList()
let sexList = ref([])
const sexDictList = async () => {
sexList.value = await (await useDictionary('sex_radio')).data.dictionary
}
sexDictList();
watch(() => sexList.value, () => {
formData.sex = sexList.value[0].value
})
let is_showList = ref([])
const is_showDictList = async () => {
is_showList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
is_showDictList();
watch(() => is_showList.value, () => {
formData.is_show = is_showList.value[0].value
})
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getUserInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined){
formData[key] = data[key]
// ()
}
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

283
niucloud/addon/hygl/admin/views/user/user.vue

@ -0,0 +1,283 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{ pageName }}</span>
<el-button type="primary" @click="addEvent">
{{ t('addUser') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="userTable.searchParam" ref="searchFormRef">
<!-- <el-form-item :label="t('siteId')" prop="site_id">-->
<!-- <el-select class="w-[280px]" v-model="userTable.searchParam.site_id" clearable-->
<!-- :placeholder="t('siteIdPlaceholder')">-->
<!-- <el-option label="全部" value=""></el-option>-->
<!-- <el-option-->
<!-- v-for="(item, index) in site_idList"-->
<!-- :key="index"-->
<!-- :label="item.name"-->
<!-- :value="item.value"-->
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item :label="t('tel')" prop="tel">
<el-input v-model="userTable.searchParam.tel" :placeholder="t('telPlaceholder')"/>
</el-form-item>
<el-form-item :label="t('name')" prop="name">
<el-input v-model="userTable.searchParam.name" :placeholder="t('namePlaceholder')"/>
</el-form-item>
<!-- <el-form-item :label="t('password')" prop="password">-->
<!-- <el-input v-model="userTable.searchParam.password" :placeholder="t('passwordPlaceholder')"/>-->
<!-- </el-form-item>-->
<el-form-item :label="t('sex')" prop="sex">
<el-select class="w-[280px]" v-model="userTable.searchParam.sex" clearable
:placeholder="t('sexPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in sexList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('birthday')" prop="birthday">
<el-date-picker v-model="userTable.searchParam.birthday" type="daterange"
value-format="YYYY-MM-DD"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')"/>
</el-form-item>
<el-form-item :label="t('isShow')" prop="is_show">
<el-select class="w-[280px]" v-model="userTable.searchParam.is_show" clearable
:placeholder="t('isShowPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in is_showList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadUserList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="userTable.data" size="large" v-loading="userTable.loading">
<template #empty>
<span>{{ !userTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="60" :show-overflow-tooltip="true"/>
<el-table-column prop="tel" :label="t('tel')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="name" :label="t('name')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('pic')" width="100" align="left">
<template #default="{ row }">
<el-avatar v-if="row.pic" :src="img(row.pic)"/>
<el-avatar v-else icon="UserFilled"/>
</template>
</el-table-column>
<!-- <el-table-column prop="password" :label="t('password')" min-width="120" :show-overflow-tooltip="true"/>-->
<el-table-column :label="t('pid')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.user && row.user.name ? row.user.name + `#` + row.user.id : '顶级' }}
</template>
</el-table-column>
<el-table-column prop="level" :label="t('level')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="wx_openid" :label="t('wxOpenid')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="wx_unionid" :label="t('wxUnionid')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('sex')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in sexList">
<div v-if="item.value == row.sex">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="birthday" :label="t('birthday')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('isShow')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in is_showList">
<div v-if="item.value == row.is_show">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="userTable.page" v-model:page-size="userTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="userTable.total"
@size-change="loadUserList()" @current-change="loadUserList"/>
</div>
</div>
<edit ref="editUserDialog" @complete="loadUserList"/>
</el-card>
</div>
</template>
<script lang="ts" setup>
import {reactive, ref, watch} from 'vue'
import {t} from '@/lang'
import {useDictionary} from '@/app/api/dict'
import {getUserList, deleteUser,} from '@/addon/hygl/api/user'
import {img} from '@/utils/common'
import {ElMessageBox, FormInstance} from 'element-plus'
import Edit from '@/addon/hygl/views/user/components/user-edit.vue'
import {useRoute} from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let userTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
"site_id": "",
"tel": "",
"name": "",
"password": "",
"sex": "",
"birthday": [],
"is_show": ""
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const site_idList = ref([] as any[])
const site_idDictList = async () => {
site_idList.value = await (await useDictionary('placeholder_')).data.dictionary
}
site_idDictList();
const sexList = ref([] as any[])
const sexDictList = async () => {
sexList.value = await (await useDictionary('sex_radio')).data.dictionary
}
sexDictList();
const is_showList = ref([] as any[])
const is_showDictList = async () => {
is_showList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
is_showDictList();
/**
* 获取会员管理列表
*/
const loadUserList = (page: number = 1) => {
userTable.loading = true
userTable.page = page
getUserList({
page: userTable.page,
limit: userTable.limit,
...userTable.searchParam
}).then(res => {
userTable.loading = false
userTable.data = res.data.data
userTable.total = res.data.total
}).catch(() => {
userTable.loading = false
})
}
loadUserList()
const editUserDialog: Record<string, any> | null = ref(null)
/**
* 添加会员管理
*/
const addEvent = () => {
editUserDialog.value.setFormData()
editUserDialog.value.showDialog = true
}
/**
* 编辑会员管理
* @param data
*/
const editEvent = (data: any) => {
editUserDialog.value.setFormData(data)
editUserDialog.value.showDialog = true
}
/**
* 删除会员管理
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('userDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteUser(id).then(() => {
loadUserList()
}).catch(() => {
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadUserList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

233
niucloud/addon/hygl/admin/views/user_coupons/components/user-coupons-edit.vue

@ -0,0 +1,233 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateUserCoupons') : t('addUserCoupons')" width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form"
v-loading="loading">
<el-form-item :label="t('userId')" prop="user_id">
<el-select class="input-width" v-model="formData.user_id" clearable :placeholder="t('userIdPlaceholder')" filterable>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in userIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('couponsId')" prop="coupons_id">
<el-select class="input-width" v-model="formData.coupons_id" clearable :placeholder="t('couponsIdPlaceholder')" filterable>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in nameList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<!--
<el-form-item :label="t('nominalValue')" prop="nominal_value">
<el-input-number v-model="formData.nominal_value" clearable :placeholder="t('nominalValuePlaceholder')"
class="input-width"/>
</el-form-item>
-->
<el-form-item :label="t('isShow')" prop="is_show">
<el-radio-group v-model="formData.is_show" :placeholder="t('isShowPlaceholder')">
<el-radio
v-for="(item, index) in is_showList"
:key="index"
:label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import {ref, reactive, computed, watch} from 'vue'
import {useDictionary} from '@/app/api/dict'
import {t} from '@/lang'
import type {FormInstance} from 'element-plus'
import {addUserCoupons, editUserCoupons, getUserCouponsInfo, getWithUserList,} from '@/addon/hygl/api/user_coupons'
import {getWithCouponsList} from "@/addon/hygl/api/common";
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
user_id: '',
coupons_id: '',
is_show: '1',
}
const formData: Record<string, any> = reactive({...initialFormData})
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
user_id: [
{required: true, message: t('userIdPlaceholder'), trigger: 'blur'},
]
,
coupons_id: [
{required: true, message: t('couponsIdPlaceholder'), trigger: 'blur'},
]
,
nominal_value: [
{required: true, message: t('nominalValuePlaceholder'), trigger: 'blur'},
{
validator: (rule: any, value: string, callback: any) => {
if (value && !/^\d{0,99999}$/.test(value)) {
callback(new Error(t('generateBetween')))
} else {
callback()
}
}
},
]
,
is_show: [
{required: true, message: t('isShowPlaceholder'), trigger: 'blur'},
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editUserCoupons : addUserCoupons
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
//
const nameList = ref([] as any[])
const setNameList = async () => {
nameList.value = await (await getWithCouponsList({'name':''})).data
}
setNameList()
let is_showList = ref([])
const is_showDictList = async () => {
is_showList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
is_showDictList();
watch(() => is_showList.value, () => {
formData.is_show = is_showList.value[0].value
})
const userIdList = ref([] as any[])
const setUserIdList = async () => {
userIdList.value = await (await getWithUserList({})).data.data
}
setUserIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getUserCouponsInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

249
niucloud/addon/hygl/admin/views/user_coupons/user_coupons.vue

@ -0,0 +1,249 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{ pageName }}</span>
<el-button type="primary" @click="addEvent">
{{ t('addUserCoupons') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="userCouponsTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('userId')" prop="user_id">
<el-select class="w-[280px]" v-model="userCouponsTable.searchParam.user_id" clearable
:placeholder="t('userIdPlaceholder')">
<el-option
v-for="(item, index) in userIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<!-- <el-form-item :label="t('siteId')" prop="site_id">-->
<!-- <el-input v-model="userCouponsTable.searchParam.site_id" :placeholder="t('siteIdPlaceholder')"/>-->
<!-- </el-form-item>-->
<el-form-item :label="t('couponsId')" prop="name">
<el-input v-model="userCouponsTable.searchParam.coupons_id" :placeholder="t('couponsIdPlaceholder')"/>
</el-form-item>
<el-form-item :label="t('nominalValue')" prop="nominal_value">
<range-input v-model="userCouponsTable.searchParam.nominal_value"/>
</el-form-item>
<el-form-item :label="t('isShow')" prop="is_show">
<el-select class="w-[280px]" v-model="userCouponsTable.searchParam.is_show" clearable
:placeholder="t('isShowPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in is_showList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="userCouponsTable.searchParam.create_time" type="datetimerange"
format="YYYY-MM-DD hh:mm:ss"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadUserCouponsList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="userCouponsTable.data" size="large" v-loading="userCouponsTable.loading">
<template #empty>
<span>{{ !userCouponsTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="user_id" :label="t('userId')" min-width="120" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.user && row.user.name ? row.user.name : '' }}
</template>
</el-table-column>
<el-table-column prop="coupons_id" :label="t('couponsId')" min-width="120" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.coupons && row.coupons.name ? row.coupons.name : '' }}
</template>
</el-table-column>
<el-table-column prop="nominal_value" :label="t('nominalValue')" min-width="120"
:show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.coupons && row.coupons.nominal_value ? row.coupons.nominal_value : '0' }}
</template>
</el-table-column>
<el-table-column prop="valid_time" :label="t('validTime')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('isShow')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in is_showList">
<div v-if="item.value == row.is_show">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<!-- <el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>-->
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="userCouponsTable.page" v-model:page-size="userCouponsTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="userCouponsTable.total"
@size-change="loadUserCouponsList()" @current-change="loadUserCouponsList"/>
</div>
</div>
<edit ref="editUserCouponsDialog" @complete="loadUserCouponsList"/>
</el-card>
</div>
</template>
<script lang="ts" setup>
import {reactive, ref, watch} from 'vue'
import {t} from '@/lang'
import {useDictionary} from '@/app/api/dict'
import {getUserCouponsList, deleteUserCoupons, getWithUserList,} from '@/addon/hygl/api/user_coupons'
import {img} from '@/utils/common'
import {ElMessageBox, FormInstance} from 'element-plus'
import Edit from '@/addon/hygl/views/user_coupons/components/user-coupons-edit.vue'
import {useRoute} from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let userCouponsTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
"user_id": "",
"site_id": "",
"coupons_id": "",
"nominal_value": [],
"is_show": "",
"create_time": []
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const is_showList = ref([] as any[])
const is_showDictList = async () => {
is_showList.value = await (await useDictionary('is_show_radio')).data.dictionary
}
is_showDictList();
/**
* 获取用户优惠券列表
*/
const loadUserCouponsList = (page: number = 1) => {
userCouponsTable.loading = true
userCouponsTable.page = page
getUserCouponsList({
page: userCouponsTable.page,
limit: userCouponsTable.limit,
...userCouponsTable.searchParam
}).then(res => {
userCouponsTable.loading = false
userCouponsTable.data = res.data.data
userCouponsTable.total = res.data.total
}).catch(() => {
userCouponsTable.loading = false
})
}
loadUserCouponsList()
const editUserCouponsDialog: Record<string, any> | null = ref(null)
/**
* 添加用户优惠券
*/
const addEvent = () => {
editUserCouponsDialog.value.setFormData()
editUserCouponsDialog.value.showDialog = true
}
/**
* 编辑用户优惠券
* @param data
*/
const editEvent = (data: any) => {
editUserCouponsDialog.value.setFormData(data)
editUserCouponsDialog.value.showDialog = true
}
/**
* 删除用户优惠券
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('userCouponsDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteUserCoupons(id).then(() => {
loadUserCouponsList()
}).catch(() => {
})
})
}
const userIdList = ref([])
const setUserIdList = async () => {
userIdList.value = await (await getWithUserList({})).data
}
setUserIdList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadUserCouponsList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

106
niucloud/addon/hygl/app/adminapi/controller/Common.php

@ -0,0 +1,106 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller;
use addon\hygl\app\model\coupons\Coupons;
use addon\hygl\app\service\admin\CommonService;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\config\ConfigService;
use core\base\BaseAdminService;
/**
* 公共项控制器
* Class Config
* @package addon\hygl\app\adminapi\controller\config
*/
class Common extends BaseAdminController
{
/**
* 上传文件到本地
*/
public function uploadFile()
{
$file = $_FILES['file']; // 获取上传的文件
$name = $file['name'];//上传文件的原名称
$path = $this->request->param('path', '');//表名_字段名的格式 如:user_pic=user表pic字段
if (!$file || !$path) {
return fail('缺少参数');
}
// 判断是否上传文件
if (empty($file)) {
return '未选择要上传的文件';
}
$site_id = (new CommonService())->getSiteId();//获取站点id
// 文件上传目录
$date = date('Y_m_d');
$save_path = "addon/hygl/upload/{$path}/{$site_id}/{$date}/";//文件保存的路径,如:addon/hygl/upload/upload_files/ 就表示在根目录的public/addon/hygl/upload/upload_files/下
// 文件名(不包含扩展名)
$filename = time() . rand(1111, 9999);
// 扩展名
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
// 创建保存目录
if (!is_dir($save_path)) {
mkdir($save_path, 0755, true);
}
// 文件保存相对路径
$save_file = $save_path . $filename . '.' . $ext;
// 将上传的文件移动到指定位置
if (!move_uploaded_file($file['tmp_name'], $save_file)) {
return '文件上传失败';
}
// 返回文件保存的信息给客户端
$res = [
'name' => $name,//上传文件的原名称
'file_name' => $filename . '.' . $ext,//新文件名称
'file_path' => $save_file,//相对路径
'url' => get_file_url($save_file),//绝对路径
];
return success('操作成功', $res);
}
//远程获取优惠券下拉菜单
public function getCouponsList(){
$site_id = (new CommonService())->getSiteId();
$couponsModel = new Coupons();
$res = $couponsModel->where([["site_id","=",$site_id]])
->where('is_show',1)
->where('is_obsolete',0)
->where('stock','>',0)
->select()->toArray();
if ($res){
foreach($res as &$v){
if ($v['is_long_term_valid'] == 1){
$v['name'] = "{$v['name']}(长期有效)";
}else{
$data_1 = date('Y-m-d',$v['valid_from']);
$data_2 = date('Y-m-d',$v['valid_until']);
$v['name'] = "{$v['name']}(有效期{$data_1}-{$data_2})";
}
}
}
return success($res);
}
}

89
niucloud/addon/hygl/app/adminapi/controller/advertising/Advertising.php

@ -0,0 +1,89 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\advertising;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\advertising\AdvertisingService;
/**
* 广告管理控制器
* Class Advertising
* @package addon\hygl\app\adminapi\controller\advertising
*/
class Advertising extends BaseAdminController
{
/**
* 获取广告管理列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
]);
return success((new AdvertisingService())->getPage($data));
}
/**
* 广告管理详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new AdvertisingService())->getInfo($id));
}
/**
* 添加广告管理
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["img_url",""],
["skip_url",""],
["sort",0],
]);
$this->validate($data, 'addon\hygl\app\validate\advertising\Advertising.add');
$id = (new AdvertisingService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 广告管理编辑
* @param $id 广告管理id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["img_url",""],
["skip_url",""],
["sort",0],
]);
$this->validate($data, 'addon\hygl\app\validate\advertising\Advertising.edit');
(new AdvertisingService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 广告管理删除
* @param $id 广告管理id
* @return \think\Response
*/
public function del(int $id){
(new AdvertisingService())->del($id);
return success('DELETE_SUCCESS');
}
}

131
niucloud/addon/hygl/app/adminapi/controller/config/Config.php

@ -0,0 +1,131 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\config;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\config\ConfigService;
/**
* 配置项控制器
* Class Config
* @package addon\hygl\app\adminapi\controller\config
*/
class Config extends BaseAdminController
{
/**
* 获取配置项列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
]);
return success((new ConfigService())->getPage($data));
}
/**
* 配置项详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new ConfigService())->getInfo($id));
}
/**
* 重新生成H5站点二维码
* @param int $id
* @return \think\Response
*/
public function resetH5SiteQRCode(int $id){
$qrcode = (new ConfigService())->resetH5SiteQRCode($id);
$res = [
'url'=>$qrcode['url'],
'ol_url'=>$qrcode['ol_url']
];
return success($res);
}
/**
* 添加配置项
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["we_chat_pay_appid",""],
["we_chat_pay_app_id",""],
["we_chat_pay_miniapp_id",""],
["we_chat_pay_mch_id",""],
["we_chat_pay_key",""],
["we_chat_pay_miniapp_secret",""],
["we_chat_pay_notify_url",""],
["alipay_appId",""],
["alipay_rsa_private_key",""],
["alipay_public_key",""],
["alipay_notify_url",""],
["we_chat_pay_mch_secret_cert",""],
["we_chat_pay_mch_public_cert_path",""],
]);
$this->validate($data, 'addon\hygl\app\validate\config\Config.add');
$id = (new ConfigService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 配置项编辑
* @param $id 配置项id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["we_chat_pay_appid",""],
["we_chat_pay_app_id",""],
["we_chat_pay_miniapp_id",""],
["we_chat_pay_mch_id",""],
["we_chat_pay_key",""],
["we_chat_pay_miniapp_secret",""],
["we_chat_pay_notify_url",""],
// ["alipay_appId",""],
// ["alipay_rsa_private_key",""],
// ["alipay_public_key",""],
// ["alipay_notify_url",""],
["h5_qrcode_url",""],
["we_chat_pay_mch_secret_cert",""],
["we_chat_pay_mch_public_cert_path",""],
]);
if (!$data['we_chat_pay_mch_secret_cert'] || !$data['we_chat_pay_mch_public_cert_path']){
return fail('微信商户私钥或商户公钥不能为空');
}
$this->validate($data, 'addon\hygl\app\validate\config\Config.edit');
(new ConfigService())->edit($data);
return success('EDIT_SUCCESS');
}
/**
* 配置项删除
* @param $id 配置项id
* @return \think\Response
*/
public function del(int $id){
(new ConfigService())->del($id);
return success('DELETE_SUCCESS');
}
}

127
niucloud/addon/hygl/app/adminapi/controller/coupons/Coupons.php

@ -0,0 +1,127 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\coupons;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\coupons\CouponsService;
/**
* 优惠券控制器
* Class Coupons
* @package addon\hygl\app\adminapi\controller\coupons
*/
class Coupons extends BaseAdminController
{
/**
* 获取优惠券列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["name",""],
["nominal_value",["",""]],
["is_show",""]
]);
return success((new CouponsService())->getPage($data));
}
/**
* 优惠券详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new CouponsService())->getInfo($id));
}
/**
* 添加优惠券
* @return \think\Response
*/
public function add()
{
$data = $this->request->params([
["name", ""],
["nominal_value", 0.00],
["stock", 0],
["is_show", ""],
["is_obsolete", ""],
["is_long_term_valid", ""],
["valid_time", []],
]);
$this->validate($data, 'addon\hygl\app\validate\coupons\Coupons.add');
$data['valid_from'] = 0;
$data['valid_until'] = 0;
if (!$data['is_long_term_valid']){
//不是长期有效
if (empty($data['valid_time'][0]) || empty($data['valid_time'][1])){
return fail('有效期不能为空');
}else{
$data['valid_from'] = strtotime($data['valid_time'][0]);
$data['valid_until'] = strtotime($data['valid_time'][1]);
}
}
$id = (new CouponsService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 优惠券编辑
* @param $id 优惠券id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["name", ""],
["nominal_value", 0.00],
["stock", 0],
["is_show", ""],
["is_obsolete", ""],//是否作废1=是
["is_long_term_valid", ""],
["valid_time", []],
]);
$this->validate($data, 'addon\hygl\app\validate\coupons\Coupons.edit');
$data['valid_from'] = 0;
$data['valid_until'] = 0;
if (!$data['is_long_term_valid']){
//不是长期有效
if (empty($data['valid_time'][0]) || empty($data['valid_time'][1])){
return fail('有效期不能为空');
}else{
$data['valid_from'] = strtotime($data['valid_time'][0]);
$data['valid_until'] = strtotime($data['valid_time'][1]);
}
}
unset($data['valid_time']);
(new CouponsService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 优惠券删除
* @param $id 优惠券id
* @return \think\Response
*/
public function del(int $id){
(new CouponsService())->del($id);
return success('DELETE_SUCCESS');
}
}

29
niucloud/addon/hygl/app/adminapi/controller/hello_world/Index.php

@ -0,0 +1,29 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\hello_world;
use core\base\BaseAdminController;
use think\Response;
class Index extends BaseAdminController
{
/**
* Hello World
* @return Response
*/
public function index()
{
return success('SUCCESS', 'Hello World');
}
}

120
niucloud/addon/hygl/app/adminapi/controller/transaction_history/TransactionHistory.php

@ -0,0 +1,120 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\transaction_history;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\transaction_history\TransactionHistoryService;
/**
* 会员交易记录控制器
* Class TransactionHistory
* @package addon\hygl\app\adminapi\controller\transaction_history
*/
class TransactionHistory extends BaseAdminController
{
/**
* 获取会员交易记录列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["user_id",""],
["order_num",""],
["pay_num",""],
["pay_type",""],
["price",["",""]],
["cash_fee",["",""]],
["pay_status",""],
["pay_time",["",""]],
["create_time",["",""]]
]);
return success((new TransactionHistoryService())->getPage($data));
}
/**
* 会员交易记录详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new TransactionHistoryService())->getInfo($id));
}
/**
* 添加会员交易记录
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["user_id",0],
["remark",""],
["order_num",""],
["pay_num",""],
["pay_type",""],
["price",0.00],
["cash_fee",0.00],
["pay_status",0],
["pay_time",0],
["pay_data_json",""],
]);
if ($data['pay_time']){
$data['pay_time'] = strtotime($data['pay_time']);
}
$this->validate($data, 'addon\hygl\app\validate\transaction_history\TransactionHistory.add');
$id = (new TransactionHistoryService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 会员交易记录编辑
* @param $id 会员交易记录id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["user_id",0],
["remark",""],
["order_num",""],
["pay_num",""],
["pay_type",""],
["price",0.00],
["cash_fee",0.00],
["pay_status",0],
["pay_time",0],
["pay_data_json",""],
]);
if ($data['pay_time']){
$data['pay_time'] = strtotime($data['pay_time']);
}
$this->validate($data, 'addon\hygl\app\validate\transaction_history\TransactionHistory.edit');
(new TransactionHistoryService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 会员交易记录删除
* @param $id 会员交易记录id
* @return \think\Response
*/
public function del(int $id){
(new TransactionHistoryService())->del($id);
return success('DELETE_SUCCESS');
}
}

147
niucloud/addon/hygl/app/adminapi/controller/user/User.php

@ -0,0 +1,147 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\user;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\user\UserService;
/**
* 会员管理控制器
* Class User
* @package addon\hygl\app\adminapi\controller\user
*/
class User extends BaseAdminController
{
/**
* 获取会员管理列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["tel",""],
["name",""],
["password",""],
["sex",""],
["birthday",["",""]],
["is_show",""]
]);
return success((new UserService())->getPage($data));
}
/**
* 会员管理详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new UserService())->getInfo($id));
}
/**
* 添加会员管理
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["tel",""],
["name",""],
["pic",""],
["password",""],
["pid",0],
["level",0],
["wx_openid",""],
["wx_unionid",""],
["sex",""],
["birthday","2024-02-20 11:15:10"],
["is_show",""],
]);
//验证手机号唯一
$isTelExist = (new UserService())->isTelExist($data['tel']);
if ($isTelExist) {
return fail('手机号已存在');
}
$data['password'] = create_password($data['password']);
//根据pid计算对应的用户层级
$data['level'] = (new UserService())->createLevel($data['pid']);
$this->validate($data, 'addon\hygl\app\validate\user\User.add');
$id = (new UserService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 会员管理编辑
* @param $id 会员管理id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["tel",""],
["name",""],
["pic",""],
["password",""],
["pid",0],
["level",0],
["wx_openid",""],
["wx_unionid",""],
["sex",""],
["birthday","2024-02-20 11:15:10"],
["is_show",""],
]);
//验证手机号唯一
$isTelExist = (new UserService())->isTelExist($data['tel'],$id);
if ($isTelExist) {
return fail('手机号已存在');
}
if ($data['password']) {
$data['password'] = create_password($data['password']);
} else {
unset($data['password']);
}
//根据pid计算对应的用户层级
$data['level'] = (new UserService())->createLevel($data['pid']);
$this->validate($data, 'addon\hygl\app\validate\user\User.edit');
(new UserService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 会员管理删除
* @param $id 会员管理id
* @return \think\Response
*/
public function del(int $id){
(new UserService())->del($id);
return success('DELETE_SUCCESS');
}
//获取全部用户
public function getUserAll(){
return success(( new UserService())->getUserAll());
}
//获取全部站点
public function getSiteAll(){
return success(( new UserService())->getSiteAll());
}
}

97
niucloud/addon/hygl/app/adminapi/controller/user_coupons/UserCoupons.php

@ -0,0 +1,97 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\adminapi\controller\user_coupons;
use addon\hygl\app\service\admin\coupons\CouponsService;
use core\base\BaseAdminController;
use addon\hygl\app\service\admin\user_coupons\UserCouponsService;
/**
* 用户优惠券控制器
* Class UserCoupons
* @package addon\hygl\app\adminapi\controller\user_coupons
*/
class UserCoupons extends BaseAdminController
{
/**
* 获取用户优惠券列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["user_id",""],
["coupons_id",""],
["nominal_value",["",""]],
["is_show",""],
["create_time",["",""]]
]);
return success((new UserCouponsService())->getPage($data));
}
/**
* 用户优惠券详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new UserCouponsService())->getInfo($id));
}
/**
* 添加用户优惠券
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["user_id",0],
["coupons_id",""],
["is_show",""],
]);
$this->validate($data, 'addon\hygl\app\validate\user_coupons\UserCoupons.add');
$id = (new UserCouponsService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 用户优惠券编辑
* @param $id 用户优惠券id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["user_id",0],
["coupons_id",""],
["is_show",""],
]);
$this->validate($data, 'addon\hygl\app\validate\user_coupons\UserCoupons.edit');
(new UserCouponsService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 用户优惠券删除
* @param $id 用户优惠券id
* @return \think\Response
*/
public function del(int $id){
(new UserCouponsService())->del($id);
return success('DELETE_SUCCESS');
}
public function getUserAll(){
return success(( new UserCouponsService())->getUserAll());
}
}

173
niucloud/addon/hygl/app/adminapi/route/route.php

@ -0,0 +1,173 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
use think\facade\Route;
use app\adminapi\middleware\AdminCheckRole;
use app\adminapi\middleware\AdminCheckToken;
use app\adminapi\middleware\AdminLog;
/**
* 会员管理系统
*/
Route::group('hygl', function () {
/***************************************************** hello world ****************************************************/
Route::get('hello_world', 'addon\hygl\app\adminapi\controller\hello_world\Index@index');
//上传文件到本地
Route::post('uploadFile', 'addon\hygl\app\adminapi\controller\Common@uploadFile');
//获取远程检索用户优惠券列表
Route::get('getCouponsList', 'addon\hygl\app\adminapi\controller\Common@getCouponsList');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_BEGIN -- hygl_user
Route::group('hygl', function () {
//会员管理列表
Route::get('user', 'addon\hygl\app\adminapi\controller\user\User@lists');
//会员管理详情
Route::get('user/:id', 'addon\hygl\app\adminapi\controller\user\User@info');
//添加会员管理
Route::post('user', 'addon\hygl\app\adminapi\controller\user\User@add');
//编辑会员管理
Route::put('user/:id', 'addon\hygl\app\adminapi\controller\user\User@edit');
//删除会员管理
Route::delete('user/:id', 'addon\hygl\app\adminapi\controller\user\User@del');
//获取全部会员
Route::get('user','addon\hygl\app\adminapi\controller\user\User@getUserAll');
//获取全部站点
Route::get('site','addon\hygl\app\adminapi\controller\user\User@getSiteAll');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- hygl_user
// USER_CODE_BEGIN -- hygl_coupons
Route::group('hygl', function () {
//优惠券列表
Route::get('coupons', 'addon\hygl\app\adminapi\controller\coupons\Coupons@lists');
//优惠券详情
Route::get('coupons/:id', 'addon\hygl\app\adminapi\controller\coupons\Coupons@info');
//添加优惠券
Route::post('coupons', 'addon\hygl\app\adminapi\controller\coupons\Coupons@add');
//编辑优惠券
Route::put('coupons/:id', 'addon\hygl\app\adminapi\controller\coupons\Coupons@edit');
//删除优惠券
Route::delete('coupons/:id', 'addon\hygl\app\adminapi\controller\coupons\Coupons@del');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- hygl_coupons
// USER_CODE_BEGIN -- hygl_config
Route::group('hygl', function () {
//配置项列表
Route::get('config', 'addon\hygl\app\adminapi\controller\config\Config@lists');
//配置项详情
Route::get('config/:id', 'addon\hygl\app\adminapi\controller\config\Config@info');
//配置项-重新生成H5站点二维码
Route::get('config/resetH5SiteQRCode/:id', 'addon\hygl\app\adminapi\controller\config\Config@resetH5SiteQRCode');
//添加配置项
Route::post('config', 'addon\hygl\app\adminapi\controller\config\Config@add');
//编辑配置项
Route::put('config/:id', 'addon\hygl\app\adminapi\controller\config\Config@edit');
//删除配置项
Route::delete('config/:id', 'addon\hygl\app\adminapi\controller\config\Config@del');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- hygl_config
// USER_CODE_BEGIN -- hygl_transaction_history
Route::group('hygl', function () {
//会员交易记录列表
Route::get('transaction_history', 'addon\hygl\app\adminapi\controller\transaction_history\TransactionHistory@lists');
//会员交易记录详情
Route::get('transaction_history/:id', 'addon\hygl\app\adminapi\controller\transaction_history\TransactionHistory@info');
//添加会员交易记录
Route::post('transaction_history', 'addon\hygl\app\adminapi\controller\transaction_history\TransactionHistory@add');
//编辑会员交易记录
Route::put('transaction_history/:id', 'addon\hygl\app\adminapi\controller\transaction_history\TransactionHistory@edit');
//删除会员交易记录
Route::delete('transaction_history/:id', 'addon\hygl\app\adminapi\controller\transaction_history\TransactionHistory@del');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- hygl_transaction_history
// USER_CODE_BEGIN -- hygl_user_coupons
Route::group('hygl', function () {
//用户优惠券列表
Route::get('user_coupons', 'addon\hygl\app\adminapi\controller\user_coupons\UserCoupons@lists');
//用户优惠券详情
Route::get('user_coupons/:id', 'addon\hygl\app\adminapi\controller\user_coupons\UserCoupons@info');
//添加用户优惠券
Route::post('user_coupons', 'addon\hygl\app\adminapi\controller\user_coupons\UserCoupons@add');
//编辑用户优惠券
Route::put('user_coupons/:id', 'addon\hygl\app\adminapi\controller\user_coupons\UserCoupons@edit');
//删除用户优惠券
Route::delete('user_coupons/:id', 'addon\hygl\app\adminapi\controller\user_coupons\UserCoupons@del');
Route::get('user','addon\hygl\app\adminapi\controller\user_coupons\UserCoupons@getUserAll');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- hygl_user_coupons
// USER_CODE_BEGIN -- hygl_advertising
Route::group('hygl', function () {
//广告管理列表
Route::get('advertising', 'addon\hygl\app\adminapi\controller\advertising\Advertising@lists');
//广告管理详情
Route::get('advertising/:id', 'addon\hygl\app\adminapi\controller\advertising\Advertising@info');
//添加广告管理
Route::post('advertising', 'addon\hygl\app\adminapi\controller\advertising\Advertising@add');
//编辑广告管理
Route::put('advertising/:id', 'addon\hygl\app\adminapi\controller\advertising\Advertising@edit');
//删除广告管理
Route::delete('advertising/:id', 'addon\hygl\app\adminapi\controller\advertising\Advertising@del');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- hygl_advertising

271
niucloud/addon/hygl/app/api/controller/Home.php

@ -0,0 +1,271 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\api\controller;
use addon\hygl\app\model\advertising\Advertising;
use addon\hygl\app\model\config\Config;
use addon\hygl\app\model\coupons\Coupons;
use addon\hygl\app\model\transaction_history\TransactionHistory;
use addon\hygl\app\model\user\User;
use addon\hygl\app\model\user_coupons\UserCoupons;
use app\model\site\Site;
use core\base\BaseApiController;
use think\facade\Db;
use think\Response;
class Home extends BaseApiController
{
/**
* Hello World
* @return Response
*/
public function index()
{
return success('SUCCESS', 'Hello World');
}
//获取站点信息
public function getSiteInfo()
{
$site_id = $this->request->param('site_id', '');
$site_name = Site::where('site_id', $site_id)->value('site_name');//获取站点信息
//获取微信公众号id
$we_chat_pay_app_id = Config::where('site_id', $site_id)->value('we_chat_pay_app_id');
$res = [
'site_id' => $site_id,
'site_name' => $site_name,
'we_chat_pay_app_id' => $we_chat_pay_app_id,
];
return success($res);
}
//获取用户信息
public function getUser()
{
$site_id = $this->request->param('site_id', '');
$role = $this->request->param('role', '');//身份//wx=微信 zfb=支付宝
$openid = $this->request->param('openid', '');
if (!$site_id || !in_array($role, ['wx', 'zfb']) || !$openid) {
return fail('确少参数');
}
$user = User::where('site_id', $site_id);
if ($role == 'wx') {
$user = $user->where('wx_openid', $openid);
} else {
$user = $user->where('zfb_openid', $openid);
}
$user = $user->find();
//创建用户
if (!$user) {
if ($role == 'wx') {
$wx_openid = $openid;
$name = "微信用户{$openid}";
} else {
$zfb_openid = $openid;
$name = "微信用户{$openid}";
}
$data = [
'name' => $name,
'site_id' => $site_id,
'wx_openid' => $wx_openid ?? null,
'zfb_openid' => $zfb_openid ?? null,
'is_show' => 1,
'pid' => 0,
'level' => 1,
];
$user_data = User::create($data);
$res = [
'user_id' => $user_data['id']
];
} else {
$res = [
'user_id' => $user['id']
];
}
return success($res);
}
//获取用户拥有的优惠券
public function getUserCoupons()
{
$user_id = $this->request->param('user_id', '');
$site_id = $this->request->param('site_id', '');
$original_price = $this->request->param('original_price', '');//订单总金额
if (!$user_id || !$site_id) {
return fail('确少参数');
}
$time = time();
$data = UserCoupons::where('site_id', $site_id)
->where('user_id', $user_id)
->where('is_show', 1)//是否可用1=是,0=否
->with([
'coupons' => function ($q) use ($original_price) {
$q->where('is_obsolete', 0);
}
])
->select()->toArray();
$userCoupons = [];
foreach($data as $v){
if (!empty($v['coupons'])){
if ($v['coupons']['is_long_term_valid'] == 1){
//长期有效
$userCoupons[] = [
'id'=>$v['id'],
'name'=>"{$v['coupons']['name']}(长期有效)",
'nominal_value'=>$v['coupons']['nominal_value'] ?? 0,
'coupons'=>$v['coupons'] ?? [],
];
}elseif($v['coupons']['valid_from'] <= $time && $v['coupons']['valid_until'] >= $time){
//在有效期之内
$data_1 = date('Y-m-d',$v['coupons']['valid_from']);
$data_2 = date('Y-m-d',$v['coupons']['valid_until']);
$userCoupons[] = [
'id'=>$v['id'],
'name'=>"{$v['coupons']['name']}({$data_1}~{$data_2})",
'nominal_value'=>$v['coupons']['nominal_value'] ?? 0,
'coupons'=>$v['coupons'] ?? [],
];
}
}
}
if ($userCoupons){
// 定义自定义排序函数
// 使用匿名函数作为回调函数进行排序
usort($userCoupons, function($a, $b) {
return $b['coupons']['nominal_value'] - $a['coupons']['nominal_value'];
});
}
return success($userCoupons);
}
//获取可领取的优惠券
public function getReceiveCouponsList()
{
$site_id = $this->request->param('site_id', '');
$data = Coupons::where('site_id', $site_id)
->where('stock', '>', 0)
->where('is_show', 1)
->select();
$res = $data->toArray();
return success($res);
}
//创建订单
public function addOrder()
{
$site_id = $this->request->param('site_id', '');
$user_id = $this->request->param('user_id', '');
$pay_type = $this->request->param('pay_type', '');
$original_price = $this->request->param('original_price', '');//订单总价格
$user_coupons_id = $this->request->param('user_coupons_id', '');//用户优惠券中间表id
$original_price = bcmul($original_price,1,2);
if (!$site_id || !$user_id || !in_array($pay_type, [1, 2, 3, 4, 5, 6, 7, 8]) || !$original_price) {
return fail('缺少参数');
}
$order_num = time() . rand(1111, 9999);
$price = $original_price;
//计算优惠劵
if ($user_coupons_id) {
$user_coupons = UserCoupons::where('id', $user_coupons_id)
->where('is_show',1)
->with(['coupons'])
->find();
if (empty($user_coupons['coupons']) || $user_coupons['coupons']['is_obsolete'] != 0){
return fail('优惠券信息不存在');
}
if ($user_coupons['coupons']['is_long_term_valid'] != 1){
//不是长期有效
$time = time();
if ($user_coupons['coupons']['valid_from'] > $time || $user_coupons['coupons']['valid_until'] < $time){
return fail('优惠券已过期');
}
}
//判断优惠券面值是否大于支付面值
if ($user_coupons['coupons']['nominal_value'] >= $original_price){
return fail("优惠券面值需要小于{$original_price}");
}
$price = $original_price - $user_coupons['coupons']['nominal_value'];
if ($price <= 0) {
return fail("满减后或支付金额不能为0元");
}
}
$create_data = [
'site_id' => $site_id,//
'user_id' => $user_id,//
'order_num' => $order_num,//
'pay_type' => $pay_type,//
'original_price' => $original_price,//订单原价(元)|优惠前的金额
'price' => $price,//订单应付金额(元)|(优惠后的金额)精确到`分`
'user_coupons_id' => $user_coupons['id'],//用户优惠券中间表id
];
Db::startTrans();
try {
$res = TransactionHistory::create($create_data);
Db::commit();
} catch (\Exception $exception) {
Db::rollback();
return fail('系统繁忙');
}
if ($res) {
return success($res->toArray());
} else {
return fail('系统繁忙');
}
}
//获取广告列表
public function getAdvertising()
{
$site_id = $this->request->param('site_id', '');//站点id
if (!$site_id) {
return fail('缺少参数');
}
$field = 'id,img_url,skip_url,sort,site_id';
$res = Advertising::order('sort', 'desc')
->field($field)
->where('site_id', $site_id)
->select()
->toArray();
if ($res) {
foreach ($res as &$v) {
if ($v['img_url']) {
$v['img_url'] = get_file_url($v['img_url']);
}
}
}
return success($res);
}
}

41
niucloud/addon/hygl/app/api/controller/TestController.php

@ -0,0 +1,41 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\api\controller;
use app\model\site\Site;
use core\base\BaseApiController;
use think\Response;
class TestController extends BaseApiController
{
/**
* Hello World
* @return Response
*/
public function index()
{
return success('SUCCESS', 'Hello World');
}
//获取站点信息
public function getSiteInfo(){
$site_id = $this->request->param('site_id','');
$site_name = Site::where('site_id',$site_id)->value('site_name');
$res = [
'site_id'=>$site_id,
'site_name'=>$site_name
];
return success($res);
}
}

306
niucloud/addon/hygl/app/api/controller/WeChatController.php

@ -0,0 +1,306 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\api\controller;
use addon\hygl\app\model\config\Config;
use addon\hygl\app\model\transaction_history\TransactionHistory;
use addon\hygl\app\model\user\User;
use addon\hygl\app\model\user_coupons\UserCoupons;
use app\model\site\Site;
use core\base\BaseApiController;
use think\facade\Log;
use Yansongda\Pay\Pay;
/**
* 微信相关控制器
* Class WeChatController
* @package addon\hygl\app\api\controller
*/
class WeChatController extends BaseApiController
{
/**
* 获取openid
*/
public function getOpenid(){
$code = $this->request->param('code','');//
$site_id = $this->request->param('site_id','');
$wx_config = Config::where('site_id',$site_id)->field('we_chat_pay_app_id,we_chat_pay_gzh_secret')->find();
$appid = $wx_config['we_chat_pay_app_id'];
$secret = $wx_config['we_chat_pay_gzh_secret'];
$tokeninfo = $this->http_curl("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code");//获取access_token
$tokeninfo = json_decode($tokeninfo, true);
if (empty($tokeninfo['openid'])){
return fail('链接失效,请重新扫码');
}
$res = [
'openid'=>$tokeninfo['openid'],//微信openid
];
return success($res);
}
//curl请求
public function http_curl($url){
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//执行命令
$data = curl_exec($curl);
//关闭URL请求
curl_close($curl);
//显示获得的数据
return $data;
}
protected $config = [
'wechat' => [
'default' => [
// 必填-商户号
'mch_id' => '1647413230',
// 必填-v3商户秘钥
'mch_secret_key' => 'jTwAPZXpylR7TCoinWn2srOQUb6ioZlL',
// 必填-商户私钥 字符串或路径
'mch_secret_cert' => 'addon/hygl/wx_mch_cert/100000/apiclient_key.pem',
// 必填-商户公钥证书路径
'mch_public_cert_path' => 'addon/hygl/wx_mch_cert/100000/apiclient_cert.pem',
// 必填
'notify_url' => 'http://hycrm.zeyan.wang/api/hygl/wechatPayNotify',
// 选填-公众号 的 app_id
'mp_app_id' => 'wxd2d733a7163bff05',
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
'mode' => Pay::MODE_NORMAL,
]
],
'logger' => [ // optional
'enable' => false,
'file' => './logs/wechat.log',
'level' => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
'type' => 'single', // optional, 可选 daily.
'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
],
'http' => [ // optional
'timeout' => 5.0,
'connect_timeout' => 5.0,
// 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
],
];
public function wxMpPay_DEMO(){
$order = [
'out_trade_no' => time().'',
'description' => 'subject-测试',
'amount' => [
'total' => 1,
],
'payer' => [
'openid' => 'oYuE665Oexv3miom7BbuRQgevkHo',
],
];
$pay = Pay::wechat($this->config)->mp($order);
dd($pay);
}
//创建微信公众号支付(JSAPI)
public function wxMpPay(){
$order_id = $this->request->param('order_id','');
$user_id = $this->request->param('user_id','');
$site_id = $this->request->param('site_id','');
if (!$order_id || !$user_id || !$site_id) {
return fail('缺少参数');
}
$order = TransactionHistory::where('id',$order_id)
->where('user_id',$user_id)
->where('pay_status',0)
->find();
if (!$order){
return fail('订单不正确,请重新扫码');
}
$config = $this->initWxPayConfig($site_id);
if(!$config['code']){
return fail($config['msg']);
}
$openid = User::where('id',$user_id)->value('wx_openid');
if (!$openid){
return fail('请重新扫码');
}
$site_name = Site::where('site_id',$site_id)->value('site_name');
$order_pay = [
'out_trade_no' => $order['order_num'],//我方订单号
'description' => $site_name,
'amount' => [
'total' => $order['price'] * 100,//金额(分)
],
'payer' => [
'openid' => $openid,//支付用户的openid
],
];
//拉起微信公众号(JSAPI)支付
$pay = Pay::wechat($config['data'])->mp($order_pay);
return success($pay->toArray());
}
//支付成功异步回调
public function wechatPayNotify($site_id)
{
$filePath = 'login/test.txt';
// $date = date('Y-m-d H:i:s') . '_$site_id=' .$site_id;
// $data = "回调成功了-{$date}"; // 要写入的数据
// $a = file_put_contents($filePath, $data);
$site_id = $this->request->param('site_id','');
$config = $this->initWxPayConfig($site_id);//初始化微信支付配置项
$pay = Pay::wechat($config['data']);
try {
// 是的,你没有看错,就是这么简单!返回值为微信回调的订单数据
$data = $pay->callback();
// $a = "{$data->summary} - {$data['resource']['ciphertext']['trade_state_desc']}";
// file_put_contents($filePath,json_encode($data, JSON_UNESCAPED_UNICODE));
Log::write($data->all(),'notice');//记录日志
//判断是否支付成功
if ($data['event_type'] == "TRANSACTION.SUCCESS" && $data['resource']['ciphertext']['trade_state'] == "SUCCESS") {
//支付成功
//防止支付回调成功后重复给用户打款
$order = TransactionHistory::where('order_num', $data['resource']['ciphertext']['out_trade_no'])
->find();//查询我方订单号是否打款
if ($order['pay_status'] == 1) {
//已经支付过了,通知微信停止异步回调
return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';//付款成功
}
//修改订单状态
$cash_fee = $data['resource']['ciphertext']['amount']['payer_total'] ?? 0;
if ($cash_fee > 0){
$cash_fee = bcdiv($cash_fee, 100, 2);
}
$update = TransactionHistory::where('id', $order['id'])
->where('pay_status', 0)
->update([
'pay_num' => $data['resource']['ciphertext']['transaction_id'],//支付平台订单号
'cash_fee' => $cash_fee,//用户实际支付金额(元) 分 / 100=元
'pay_status' => 1,//订单支付状态|默认0:未支付,1:已支付
'pay_time' => time(),//
'pay_data_json' => json_encode($data, JSON_UNESCAPED_UNICODE),//支付回调json字符串
]);
if ($order['user_coupons_id']){
//核销优惠券
UserCoupons::where('id',$order['user_coupons_id'])
->where('is_show',1)
->update([
'is_show'=>0,
]);
}
if (!$update){
Log::write("订单{$data['resource']['ciphertext']['out_trade_no']}支付回调失败", 'error');//记录日志
}
}
} catch (\Exception $exception) {
Log::write($exception->getMessage(), 'error');//记录日志
$data = "错误-{$exception->getMessage()},行={$exception->getFile()},{$exception->getLine()}";
file_put_contents($filePath, $data);
}
$str = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
return $str;
}
//
/**
* 初始化微信支付配置项
* @param $site_id 站点id
* @return array[]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function initWxPayConfig($site_id){
//微信支付配置项目
$wx_config = Config::where('site_id',$site_id)
->find();
if (!$wx_config){
$res = [
'code'=>false,//true=成功,false=失败
'msg'=>'支付配置项不正确',
'data'=>[],
];
}else{
$config = [
'wechat' => [
'default' => [
// 必填-商户号
'mch_id' => $wx_config['we_chat_pay_mch_id'],
// 必填-v3商户秘钥
'mch_secret_key' => $wx_config['we_chat_pay_key'],
// 必填-商户私钥 字符串或路径
'mch_secret_cert' => $wx_config['we_chat_pay_mch_secret_cert'],
// 必填-商户公钥证书路径
'mch_public_cert_path' => $wx_config['we_chat_pay_mch_public_cert_path'],
// 必填
'notify_url' => $wx_config['we_chat_pay_notify_url'],
// 选填-公众号 的 app_id
'mp_app_id' => $wx_config['we_chat_pay_app_id'],
// 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
'mode' => Pay::MODE_NORMAL,
]
],
'logger' => [ // optional
'enable' => false,
'file' => './logs/wechat.log',
'level' => 'debug', // 建议生产环境等级调整为 info,开发环境为 debug
'type' => 'single', // optional, 可选 daily.
'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天
],
'http' => [ // optional
'timeout' => 5.0,
'connect_timeout' => 5.0,
// 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
],
];
$res = [
'code'=>true,//true=成功,false=失败
'msg'=>'',
'data'=>$config,
];
}
return $res;
}
}

28
niucloud/addon/hygl/app/api/controller/hello_world/Index.php

@ -0,0 +1,28 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\hygl\app\api\controller\hello_world;
use core\base\BaseApiController;
use think\Response;
class Index extends BaseApiController
{
/**
* Hello World
* @return Response
*/
public function index()
{
dd(123123123);
return success('SUCCESS', 'Hello World');
}
}

37
niucloud/addon/hygl/app/api/route/route.php

@ -0,0 +1,37 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
use app\api\middleware\ApiCheckToken;
use app\api\middleware\ApiLog;
use app\api\middleware\ApiChannel;
use think\facade\Route;
/**
* 会员管理系统
*/
Route::group('hygl', function() {
/***************************************************** hello world ****************************************************/
//http://hycrm.zeyan.wang/api/hygl/test
Route::get('test1', 'addon\hygl\app\api\controller\hello_world\Index@index');
Route::get('hello_world', 'addon\hygl\app\api\controller\hello_world\Index@index');
})->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class, false) //false表示不验证登录
->middleware(ApiLog::class);
Route::group('hygl', function() {
})->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class, true) //表示验证登录
->middleware(ApiLog::class);

4
niucloud/addon/hygl/app/dict/menu/admin.php

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

33
niucloud/addon/hygl/app/dict/menu/site.php

@ -0,0 +1,33 @@
<?php
return [
[
'menu_name' => '会员管理系统',
'menu_key' => 'hygl',
'menu_type' => 0,
'icon' => '',
'api_url' => '',
'router_path' => 'hygl',
'view_path' => '',
'methods' => '',
'sort' => 100,
'status' => 1,
'is_show' => 1,
'children' => [
[
'menu_name' => '会员管理系统',
'menu_key' => 'hygl_hello_world',
'menu_type' => 1,
'icon' => '',
'api_url' => 'hygl/hello_world',
'router_path' => 'hello_world',
'view_path' => 'hello_world/index',
'methods' => 'get',
'sort' => 100,
'status' => 1,
'is_show' => 1,
'children' => []
],
]
]
];

12
niucloud/addon/hygl/app/event.php

@ -0,0 +1,12 @@
<?php
return [
'bind' => [
],
'listen' => [
],
'subscribe' => [
],
];

4
niucloud/addon/hygl/app/lang/en/api.php

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

4
niucloud/addon/hygl/app/lang/en/dict.php

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

4
niucloud/addon/hygl/app/lang/en/validate.php

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

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

Loading…
Cancel
Save