This commit is contained in:
wangchen147 2023-12-15 16:26:02 +08:00
parent 89759ebe39
commit f5e15f31ac
1131 changed files with 21084 additions and 1331 deletions

View File

@ -74,6 +74,7 @@ declare module '@vue/runtime-core' {
HeatMap: typeof import('./src/components/heat-map/index.vue')['default']
Icon: typeof import('./src/components/icon/index.vue')['default']
PopoverInput: typeof import('./src/components/popover-input/index.vue')['default']
RangeInput: typeof import('./src/components/range-input/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SelectArea: typeof import('./src/components/select-area/index.vue')['default']

View File

@ -25,6 +25,7 @@
"sortablejs": "^1.15.0",
"vue": "^3.2.45",
"vue-i18n": "^9.2.2",
"vue-jsonp": "^2.0.0",
"vue-router": "^4.1.6",
"vue-web-terminal": "^3.1.7",
"vue3-video-play": "^1.3.1-beta.6"
@ -6244,6 +6245,11 @@
"vue": "^3.2.2"
}
},
"node_modules/vue-jsonp": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/vue-jsonp/-/vue-jsonp-2.0.0.tgz",
"integrity": "sha512-Mzd9GNeuKP5hHFDWZNMWOsCuMILSkA6jo2l4A02wheFz3qqBzH7aSEFTey1BRCZCLizlaf1EqJ5YUtF392KspA=="
},
"node_modules/vue-router": {
"version": "4.1.6",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz",
@ -11365,6 +11371,11 @@
"clipboard": "^2.0.4"
}
},
"vue-jsonp": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/vue-jsonp/-/vue-jsonp-2.0.0.tgz",
"integrity": "sha512-Mzd9GNeuKP5hHFDWZNMWOsCuMILSkA6jo2l4A02wheFz3qqBzH7aSEFTey1BRCZCLizlaf1EqJ5YUtF392KspA=="
},
"vue-router": {
"version": "4.1.6",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz",

View File

@ -28,7 +28,8 @@
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.6",
"vue-web-terminal": "^3.1.7",
"vue3-video-play": "^1.3.1-beta.6"
"vue3-video-play": "^1.3.1-beta.6",
"vue-jsonp": "^2.0.0"
},
"devDependencies": {
"@tailwindcss/line-clamp": "^0.4.2",

71
admin/src/app/api/pay.ts Normal file
View File

@ -0,0 +1,71 @@
import request from '@/utils/request'
/***************************************************** 账单列表 **************************************************/
/**
*
* @param params
* @returns
*/
export function getAccountList(params: Record<string, any>) {
return request.get(`pay/account`, {params})
}
/**
*
* @param id
*/
export function getAccountInfo(id: number) {
return request.get(`pay/account/${id}`)
}
/**
*
* @returns
*/
export function getAccountStat() {
return request.get(`pay/account/stat`)
}
/**
*
* @returns
*/
export function getAccountType() {
return request.get(`pay/account/type`)
}
/***************************************************** 退款信息 **************************************************/
/**
* 退
* @param params
* @returns
*/
export function getPayRefundPages(params: Record<string, any>) {
return request.get(`pay/refund`, {params})
}
/**
* 退
* @param id
*/
export function getPayRefundInfo(refund_no: string) {
return request.get(`pay/refund/${refund_no}`)
}
/**
* 退
* @param id
*/
export function getRefundType() {
return request.get(`pay/refund/type`)
}
/**
* 退
* @param id
*/
export function getRefundTransfer(params: Record<string, any>) {
return request.post(`pay/refund/transfer`, params, {showSuccessMessage: true})
}

View File

@ -83,8 +83,8 @@ export function getMenus(type: string) {
*
* @param menu_key
*/
export function getMenuInfo(menu_key: string) {
return request.get(`sys/menu/info/${menu_key}`);
export function getMenuInfo(app_type: string, menu_key: string) {
return request.get(`sys/menu/${app_type}/info/${menu_key}`);
}
/**
@ -101,15 +101,15 @@ export function addMenu(params: Record<string, any>) {
* @param params
*/
export function editMenu(params: Record<string, any>) {
return request.put(`sys/menu/${params.menu_key}`, params, { showSuccessMessage: true })
return request.put(`sys/menu/${params.app_type}/${params.menu_key}`, params, { showSuccessMessage: true })
}
/**
*
* @param menu_key
*/
export function deleteMenu(menu_key: string) {
return request.delete(`sys/menu/${menu_key}`, { showSuccessMessage: true })
export function deleteMenu(app_type: string, menu_key: string) {
return request.delete(`sys/menu/${app_type}/${menu_key}`, { showSuccessMessage: true })
}
/**
@ -333,6 +333,13 @@ export function getContraryAddress(params: any) {
return request.get(`sys/area/contrary`, { params })
}
/**
*
* @param code
*/
export function getAreaByCode(code: number | string) {
return request.get(`sys/area/code/${code}`)
}
/***************************************************** 存储设置 ****************************************************/
/**

View File

@ -0,0 +1,10 @@
{
"refundNo": "退款编号",
"refundMoney": "退款金额",
"payType": "支付类型",
"status": "退款状态",
"createTime": "申请时间",
"refundNoPlaceholder": "请输入退款编号",
"startDate": "开始时间",
"endDate": "结束时间"
}

View File

@ -0,0 +1,16 @@
{
"refundNo": "退款编号",
"refundMoney": "退款金额",
"payType": "支付类型",
"status": "退款状态",
"createTime": "申请时间",
"refundNoPlaceholder": "请输入退款编号",
"startDate": "开始时间",
"endDate": "结束时间",
"outTradeNo": "交易流水号",
"refundTypeName": "退款方式",
"statusName": "退款状态",
"transfer": "转账",
"transferType": "转账方式",
"voucher": "凭证"
}

View File

@ -34,7 +34,7 @@
"siteInlet": "站点入口",
"enterSite": "访问站点",
"siteList": "站点列表",
"openClose": "开启/停止",
"openClose": "开启/停止",
"closeTxt":"停止",
"openTxt":"开启",
"siteUrlDevelopMessage": "站点域名功能正在开发中",

View File

@ -9,7 +9,7 @@
<el-tab-pane :label="t('wechatTemplate')" name="/channel/wechat/message" />
</el-tabs>
<div class="flex" v-loading="loading">
<div class="preview-wrap w-[300px] h-[550px] mr-[16px] bg-overlay rounded-md flex flex-col justify-between">
<div class="preview-wrap w-[300px] h-[550px] mr-[16px] bg-overlay rounded-md flex flex-col justify-between border border-color">
<div class="head w-full h-[70px]"></div>
<div class="menu-list h-[70px] flex border-t border-color">

View File

@ -0,0 +1,123 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-[20px]">{{pageName}}</span>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="payRefundTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('refundNo')" prop="refund_no">
<el-input v-model="payRefundTable.searchParam.refund_no" :placeholder="t('refundNoPlaceholder')" />
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="payRefundTable.searchParam.create_time" type="datetimerange"
value-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="loadPayRefundList()">{{ 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="payRefundTable.data" size="large" v-loading="payRefundTable.loading">
<template #empty>
<span>{{ !payRefundTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="refund_no" :label="t('refundNo')" min-width="200" />
<el-table-column prop="money" :label="t('refundMoney')" min-width="120" />
<el-table-column prop="type_name" :label="t('payType')" min-width="120" />
<el-table-column prop="status_name" :label="t('status')" min-width="120" />
<el-table-column prop="create_time" :label="t('createTime')" min-width="160" />
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="payRefundTable.page" v-model:page-size="payRefundTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="payRefundTable.total"
@size-change="loadPayRefundList()" @current-change="loadPayRefundList" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { getPayRefundPages } from '@/app/api/pay'
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const payRefundTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
refund_no: '',
create_time: []
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
/**
* 获取商品标签列表
*/
const loadPayRefundList = (page: number = 1) => {
payRefundTable.loading = true
payRefundTable.page = page
getPayRefundPages({
page: payRefundTable.page,
limit: payRefundTable.limit,
...payRefundTable.searchParam
}).then(res => {
payRefundTable.loading = false
payRefundTable.data = res.data.data
payRefundTable.total = res.data.total
}).catch(() => {
payRefundTable.loading = false
})
}
loadPayRefundList()
const infoEvent = (data) => {
router.push('/finance/refund/detail?refund_no=' + data.refund_no)
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadPayRefundList()
}
</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>

View File

@ -0,0 +1,161 @@
<template>
<div class="main-container">
<div class="detail-head">
<div class="left" @click="router.push({ path: '/member/refund' })">
<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 relative" shadow="never" v-if="formData">
<div class="flex px-[20px] py-[20px] justify-between">
<span>{{ t('refundMoney') }}<span>{{ formData.money }}</span></span>
<span>{{ t('refundNo') }}<span>{{ formData.refund_no }}</span></span>
</div>
<el-table :data="refundList" size="large">
<el-table-column prop="out_trade_no" :label="t('outTradeNo')" min-width="200" />
<el-table-column prop="create_time" :label="t('createTime')" min-width="160" />
<el-table-column prop="refund_type_name" :label="t('refundTypeName')" min-width="120" />
<el-table-column :label="t('refundMoney')" min-width="120">
<template #default="{ row }">
<span>{{ row.money }}</span>
</template>
</el-table-column>
<el-table-column prop="status_name" :label="t('statusName')" min-width="120" />
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="transferEvent(row)" v-if="row.status == 'wait'">{{ t('transfer') }}</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="transferDialog" :title="title" width="500px" class="diy-dialog-wrap"
:destroy-on-close="true">
<el-form :model="transfeFormData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('transferType')">
<el-radio-group v-model="transfeFormData.refund_type">
<el-radio :label="item.value" v-for="(item, index) in refundTypeData" :key="index">{{ item.name }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('refundMoney')" >
<span>{{ transfeFormData.refund_money }}</span>
</el-form-item>
<el-form-item :label="t('voucher')" v-if="transfeFormData.refund_type == 'offline'">
<upload-image v-model="transfeFormData.voucher" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="transferDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { getPayRefundInfo, getRefundType, getRefundTransfer } from '@/app/api/pay'
import { useRoute, useRouter } from 'vue-router'
import { img, getAppType } from '@/utils/common'
import { ElMessageBox, FormInstance } from 'element-plus'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const refundNo: string = route.query.refund_no
const loading = ref(true)
const appType = getAppType()
const refundList = ref([])
const formData: Record<string, any> | null = ref(null)
const setFormData = async (refundNo: string = '') => {
loading.value = true
formData.value = null
await getPayRefundInfo(refundNo)
.then(({ data }) => {
formData.value = data
refundList.value.push(data)
})
.catch(() => {
})
loading.value = false
}
if (refundNo) setFormData(refundNo)
else loading.value = false
const refundTypeData = ref([])
getRefundType().then((data) => {
Object.keys(data.data).forEach((key: string) => {
refundTypeData.value.push({ value: key, name: data.data[key] })
})
})
const transferDialog = ref(false)
const transferEvent = (data) => {
transferDialog.value = true
transfeFormData.refund_no = data.refund_no
transfeFormData.refund_money = data.money
}
const initialFormData = {
refund_no: '',
refund_type: 'back',
voucher: '',
refund_money: 0.00
}
const transfeFormData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
label_name: [
{ required: true, message: t('labelNamePlaceholder'), trigger: 'blur' }
]
}
})
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
const data = transfeFormData
getRefundTransfer(data).then(res => {
loading.value = false
transferDialog.value = false
refundList.value = []
setFormData(refundNo)
}).catch(err => {
transferDialog.value = false
loading.value = false
})
}
})
}
// const transferEvent = () => {
// const routeUrl = router.resolve({
// path: '/member/refund',
// query: { refund_id: formData.value.refund_id }
// })
// window.open(routeUrl.href, '_blank')
// }
</script>
<style lang="scss" scoped></style>

View File

@ -78,6 +78,16 @@
</template>
</el-table-column>
<el-table-column :label="t('manager')" width="150" align="left">
<template #default="{ row }">
<div class="flex items-center">
<div class="flex flex flex-col">
<span>{{ row.admin.username || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="app_name" :label="t('app')" width="150" :show-overflow-tooltip="true" />
<el-table-column prop="group_name" :label="t('groupId')" width="150" :show-overflow-tooltip="true" />
<el-table-column prop="create_time" :label="t('createTime')" width="250" :show-overflow-tooltip="true" />
@ -101,8 +111,9 @@
<el-table-column :label="t('operation')" min-width="250" align="right" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="toSiteLink">
<a href="javascript:;" title="启动站点" class="iconfont iconicon_huojian"></a>
<el-button type="primary" link @click="toSiteLink(row)">
<!-- <a href="javascript:;" title="启动站点" class="iconfont iconicon_huojian"></a>-->
访问站点
</el-button>
<el-button type="primary" link @click="openClose(row.status, row.site_id)"
v-if="row.status == 1 || row.status == 3">{{ row.status == 1 ? t('closeTxt') : t('openTxt')
@ -140,8 +151,6 @@ import { CollectionTag } from '@element-plus/icons-vue'
const route = useRoute()
const pageName = route.meta.title
const siteLink = location.origin + '/site/login'
const groupList = ref({
all: []
})
@ -275,8 +284,9 @@ const editEvent = (data: any) => {
* 站点登录
* @param data
*/
const toSiteLink = () => {
window.open(siteLink)
const toSiteLink = (data: any) => {
// window.localStorage.setItem('site.siteId', data.site_id)
window.open(`${location.origin}/site/`)
}
const openClose = (i, site_id) => {

View File

@ -0,0 +1,35 @@
<template>
<div class="el-date-editor el-input__wrapper el-range-editor el-tooltip__trigger el-tooltip__trigger" :class="{'is-active': isActive}">
<input class="el-range-input" v-model="props.modelValue[0]" @blur="isActive = false" @focus="isActive = true" :placeholder="props.startPlaceholder">
<span class="el-range-separator">-</span>
<input class="el-range-input" v-model="props.modelValue[1]" @blur="isActive = false" @focus="isActive = true" :placeholder="props.endPlaceholder">
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const isActive = ref(false)
const props = defineProps({
startPlaceholder: {
type: String,
default: ''
},
endPlaceholder: {
type: String,
default: ''
},
modelValue: {
type: Array,
default: () => {
return ['', '']
}
}
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -189,3 +189,38 @@ export function deepClone(obj: object) {
}
return o
}
/**
*
* @param {Number} len
* @param {Boolean} firstU
* @param {Nubmer} radix
*/
export function guid(len = 10, firstU = true, radix = null) {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
const uuid = []
radix = radix || chars.length
if (len) {
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
} else {
let r
// rfc4122标准要求返回的uuid中,某些位为固定的字符
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
uuid[14] = '4'
for (let i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
}
}
}
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
if (firstU) {
uuid.shift()
return `u${uuid.join('')}`
}
return uuid.join('')
}

View File

@ -33,7 +33,7 @@ export const createCircle = (map: any, geometriesData: any) => {
{
styleId: 'circle',
center: new LatLng(geometriesData.center.lat, geometriesData.center.lng),
radius: geometriesData.radius,
radius: parseInt(geometriesData.radius),
id: geometriesData.key
}
]
@ -55,8 +55,8 @@ export const createCircle = (map: any, geometriesData: any) => {
})
editor.on('adjust_complete', (data: any) => {
geometriesData.center = data.center
geometriesData.radius = data.radius
geometriesData.center = { lat: data.center.lat, lng: data.center.lng }
geometriesData.radius = parseInt(data.radius)
})
geometry[geometriesData.key] = { graphical: multiCircle, editor }
@ -121,7 +121,9 @@ export const createPolygon = (map: any, geometriesData: any) => {
})
editor.on('adjust_complete', (data: any) => {
geometriesData.paths = data.paths
geometriesData.paths = data.paths.map(item => {
return { lat: item.lat, lng: item.lng}
})
})
geometry[geometriesData.key] = { graphical: multiPolygon, editor }

View File

@ -100,8 +100,7 @@ class AddonDevelop extends BaseAdminController
* @return void
*/
public function checkKey($key){
return success(data:(new AppService())->checkKey($key));
return success(data:(new AddonDevelopService())->checkKey($key));
}
/**

View File

@ -0,0 +1,65 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\adminapi\controller\pay;
use app\dict\pay\RefundDict;
use app\service\admin\pay\RefundService;
use core\base\BaseAdminController;
class PayRefund extends BaseAdminController
{
/**
* 退款列表
* @return \think\Response
*/
public function pages()
{
$data = $this->request->params([
['refund_no', ''],
['create_time', []],
['status', '']
]);
return success(data: (new RefundService())->getPage($data));
}
/**
* 退款详情
* @param $refund_no
* @return \think\Response
*/
public function detail($refund_no)
{
return success(data: (new RefundService())->getDetail($refund_no));
}
/**
* 获取退款方式
*/
public function getRefundType()
{
return success(data:(new RefundDict())->getType());
}
/**
* 转账
* @return \think\Response
*/
public function transfer()
{
$data = $this->request->params([
['refund_no', ''],
['refund_type', []],
['voucher', '']
]);
return success(data:(new RefundService())->refund($data));
}
}

View File

@ -83,7 +83,7 @@ class Site extends BaseAdminController
*/
public function menu()
{
return success((new AuthSiteService())->getMenuList(1, 'all'));
return success((new AuthSiteService())->getMenuList(1, 'all', 'all', 0));
}
/**

View File

@ -58,4 +58,12 @@ class Area extends BaseAdminController
]);
return success((new AreaService())->getAddressInfo($data['location']));
}
/**
*
* @return void
*/
public function areaByAreaCode(string $code) {
return success((new AreaService())->getAreaByAreaCode($code));
}
}

View File

@ -37,9 +37,9 @@ class Menu extends BaseAdminController
* @param $menu_key
* @return Response
*/
public function info($menu_key)
public function info($app_type, $menu_key)
{
return success((new MenuService())->get($menu_key));
return success((new MenuService())->get($app_type, $menu_key));
}
/**
@ -73,7 +73,7 @@ class Menu extends BaseAdminController
/**
* 菜单或接口更新
*/
public function edit($menu_key)
public function edit($app_type, $menu_key)
{
$data = $this->request->params([
['menu_name', ''],
@ -92,7 +92,7 @@ class Menu extends BaseAdminController
['is_show', 0],
]);
$this->validate($data, 'app\validate\sys\Menu.edit');
(new MenuService())->edit($menu_key, $data);
(new MenuService())->edit($app_type, $menu_key, $data);
return success('EDIT_SUCCESS');
}
@ -120,9 +120,9 @@ class Menu extends BaseAdminController
* @param $menu_key
* @return Response
*/
public function del($menu_key)
public function del($app_type, $menu_key)
{
(new MenuService())->del($menu_key);
(new MenuService())->del($app_type, $menu_key);
return success('DELETE_SUCCESS');
}

View File

@ -39,6 +39,15 @@ Route::group('pay', function () {
Route::put('refuse/:out_trade_no', 'pay.Pay/refuse');
// 支付单据详情
Route::get('detail/:id', 'pay.Pay/detail');
/***************************************************** 退款 *************************************************/
//退款列表
Route::get('refund', 'pay.PayRefund/pages');
//退款详情
Route::get('refund/:refund_no', 'pay.PayRefund/detail');
//退款方式
Route::get('refund/type', 'pay.PayRefund/getRefundType');
//退款转账
Route::post('refund/transfer', 'pay.PayRefund/transfer');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,

View File

@ -40,17 +40,17 @@ Route::group('sys', function () {
//菜单新增
Route::post('menu', 'sys.Menu/add');
//菜单更新
Route::put('menu/:menu_key', 'sys.Menu/edit');
Route::put('menu/:app_type/:menu_key', 'sys.Menu/edit');
//菜单列表
Route::get('menu/:app_type', 'sys.Menu/lists');
//删除单个菜单
Route::delete('menu/:menu_key', 'sys.Menu/del');
Route::delete('menu/:app_type/:menu_key', 'sys.Menu/del');
//菜单类型
Route::get('menutype', 'sys.Menu/getMenuType');
//授权用户菜单
Route::get('authmenu', 'sys.Auth/authMenuList');
// 获取菜单信息
Route::get('menu/info/:menu_key', 'sys.Menu/info');
Route::get('menu/:app_type/info/:menu_key', 'sys.Menu/info');
// 初始化菜单
Route::post('menu/refresh', 'sys.Menu/refreshMenu');
@ -155,6 +155,8 @@ Route::group('sys', function () {
//获取地址位置信息
Route::get('area/get_info', 'sys.Area/addressInfo');
Route::get('area/contrary', 'sys.Area/contraryAddress');
// 获取省市县数据根据地址id
Route::get('area/code/:code', 'sys.Area/areaByAreaCode');
/***************************************************** 渠道管理 ****************************************************/
Route::get('channel', 'sys.Channel/getChannelType');

View File

@ -0,0 +1,103 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\member;
use core\base\BaseApiController;
use app\service\api\member\AddressService;
/**
* 会员收货地址控制器
* Class Address
* @package app\api\controller\address
*/
class Address extends BaseApiController
{
/**
* 获取会员收货地址列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["type",""]
]);
return success((new AddressService())->getList($data));
}
/**
* 会员收货地址详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new AddressService())->getInfo($id));
}
/**
* 添加会员收货地址
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["name",""],
["mobile",""],
["province_id",0],
["city_id",0],
["district_id",0],
["address",""],
["address_name", ""],
["full_address",""],
["lng",""],
["lat",""],
["is_default",0],
["type",'']
]);
$this->validate($data, 'app\validate\member\Address.add');
$id = (new AddressService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 会员收货地址编辑
* @param $id 会员收货地址id
* @return \think\Response
*/
public function edit($id){
$data = $this->request->params([
["name",""],
["mobile",""],
["province_id",0],
["city_id",0],
["district_id",0],
["address",""],
["address_name", ""],
["full_address",""],
["lng",""],
["lat",""],
["is_default",0],
["type",'']
]);
$this->validate($data, 'app\validate\member\Address.edit');
(new AddressService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 会员收货地址删除
* @param $id 会员收货地址id
* @return \think\Response
*/
public function del(int $id){
(new AddressService())->del($id);
return success('DELETE_SUCCESS');
}
}

View File

@ -0,0 +1,47 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\api\controller\sys;
use app\service\api\sys\AreaService;
use core\base\BaseApiController;
use think\Response;
class Area extends BaseApiController
{
/**
* 拖过pid获取子项列表
* @param int $pid
* @return Response
*/
public function listByPid(int $pid)
{
return success((new AreaService())->getListByPid($pid));
}
/**
* 获取层级列表
* @param int $level
* @return Response
*/
public function tree(int $level)
{
return success((new AreaService())->getAreaTree($level));
}
/**
*
* @return void
*/
public function areaByAreaCode(string $code) {
return success((new AreaService())->getAreaByAreaCode($code));
}
}

View File

@ -73,6 +73,19 @@ Route::group('member', function () {
Route::put('cashout_account/:account_id', 'member.CashOutAccount/edit');
// 删除提现账号
Route::delete('cashout_account/:account_id', 'member.CashOutAccount/del');
/***************************************************** 会员地址 **************************************************/
//会员收货地址列表
Route::get('address', 'member.Address/lists');
//会员收货地址详情
Route::get('address/:id', 'member.Address/info');
//添加会员收货地址
Route::post('address', 'member.Address/add');
//编辑会员收货地址
Route::put('address/:id', 'member.Address/edit');
//删除会员收货地址
Route::delete('address/:id', 'member.Address/del');
})->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class, true)
->middleware(ApiLog::class);

View File

@ -83,6 +83,14 @@ Route::group(function() {
Route::get('site', 'sys.Config/site');
//场景域名
Route::get('scene_domain', 'sys.Config/getSceneDomain');
/***************************************************** 地区管理 ****************************************************/
//通过pid获取列表
Route::get('area/list_by_pid/:pid', 'sys.Area/listByPid');
//通过层级获取列表
Route::get('area/tree/:level', 'sys.Area/tree');
// 获取省市县数据根据地址id
Route::get('area/code/:code', 'sys.Area/areaByAreaCode');
})->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class)
->middleware(ApiLog::class);

View File

@ -414,6 +414,32 @@ return
'status' => 1,
'is_show' => 1,
],
[
'menu_name' => '会员退款',
'menu_key' => 'member_refund_list',
'menu_type' => 1,
'icon' => 'iconfont-iconhuiyuantixian',
'api_url' => 'pay/pay_refund',
'router_path' => 'refund',
'view_path' => 'finance/pay_refund',
'methods' => 'get',
'sort' => 9,
'status' => 1,
'is_show' => 1,
],
[
'menu_name' => '退款详情',
'menu_key' => 'member_refund_detail',
'menu_type' => 1,
'icon' => 'iconfont-iconhuiyuantixian',
'api_url' => 'pay/refund',
'router_path' => 'refund/detail',
'view_path' => 'finance/refund_detail',
'methods' => 'get',
'sort' => 9,
'status' => 1,
'is_show' => 0,
],
]
],
[

View File

@ -38,7 +38,7 @@ class PayDict
//支付状态
public const STATUS_WAIT = '0';//待支付
public const STATUS_ING = '1';//支付中
public const STATUS_ED = '2';//已支付
public const STATUS_FINISH = '2';//已支付
public const STATUS_AUDIT = '3';//待审核
public const STATUS_CALCLE = '-1';//已取消
@ -102,7 +102,7 @@ class PayDict
return [
self::STATUS_WAIT => get_lang('dict_pay.status_wait'),
self::STATUS_ING => get_lang('dict_pay.status_ing'),
self::STATUS_ED => get_lang('dict_pay.status_ed'),
self::STATUS_FINISH => get_lang('dict_pay.status_finish'),
self::STATUS_CALCLE => get_lang('dict_pay.status_cancle'),
self::STATUS_AUDIT => get_lang('dict_pay.status_audit')
];

View File

@ -25,6 +25,8 @@ class RefundDict
const OFFLINE = 'offline';//线下打款
const BALANCE = 'balance';//线下支付
CONST BACK = 'back';//原路退款
/**
* 获取状态
* @return array
@ -49,7 +51,8 @@ class RefundDict
self::WECHATPAY => get_lang('dict_pay_refund.wechatpay'),
self::ALIPAY => get_lang('dict_pay_refund.alipay'),
self::OFFLINE => get_lang('dict_pay_refund.offline'),
self::BALANCE => get_lang('dict_pay_refund.balance')
self::BALANCE => get_lang('dict_pay_refund.balance'),
self::BACK => get_lang('dict_pay_refund.back'),
];
}
}

View File

@ -232,25 +232,31 @@ CREATE TABLE `member_account_log` (
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员账单表' ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `member_address`;
CREATE TABLE `member_address` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL DEFAULT 0 COMMENT '会员id',
`site_id` int(11) NOT NULL DEFAULT 0 COMMENT '站点id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户姓名',
`mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机',
`telephone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '联系电话',
`province_id` int(11) NOT NULL DEFAULT 0 COMMENT '省id',
`city_id` int(11) NOT NULL DEFAULT 0 COMMENT '市id',
`district_id` int(11) NOT NULL DEFAULT 0 COMMENT '区县id',
`community_id` int(11) NOT NULL DEFAULT 0 COMMENT '社区id',
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '地址信息',
`full_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '详细地址信息',
`longitude` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '经度',
`latitude` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '纬度',
`is_default` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否是默认地址',
`type` int(11) NOT NULL DEFAULT 1 COMMENT '地址类型 1 普通地址 2 定位地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员收货地址' ROW_FORMAT = Dynamic;
CREATE TABLE `member_address` (
id int UNSIGNED NOT NULL AUTO_INCREMENT,
member_id int NOT NULL DEFAULT 0 COMMENT '会员id',
site_id int NOT NULL DEFAULT 0 COMMENT '站点id',
name varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名',
mobile varchar(255) NOT NULL DEFAULT '' COMMENT '手机',
province_id int NOT NULL DEFAULT 0 COMMENT '省id',
city_id int NOT NULL DEFAULT 0 COMMENT '市id',
district_id int NOT NULL DEFAULT 0 COMMENT '区县id',
address varchar(255) NOT NULL DEFAULT '' COMMENT '地址信息',
address_name varchar(255) NOT NULL DEFAULT '',
full_address varchar(255) NOT NULL DEFAULT '' COMMENT '详细地址信息',
lng varchar(255) NOT NULL DEFAULT '' COMMENT '经度',
lat varchar(255) NOT NULL DEFAULT '' COMMENT '纬度',
is_default tinyint NOT NULL DEFAULT 0 COMMENT '是否是默认地址',
type varchar(30) NOT NULL DEFAULT '' COMMENT '地址类型 address 普通地址 location_address 定位地址',
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '会员收货地址';
ALTER TABLE `member_address`
ADD INDEX IDX_member_address (member_id);
DROP TABLE IF EXISTS `member_cash_out`;
CREATE TABLE `member_cash_out` (
@ -376,8 +382,13 @@ CREATE TABLE `pay_refund` (
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
`refund_time` int(11) NOT NULL DEFAULT 0 COMMENT '支付时间',
`close_time` int(11) NOT NULL DEFAULT 0 COMMENT '关闭时间',
`fail_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '失败原因',
`fail_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '失败原因',
`voucher` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '支付凭证',
`trade_type` varchar(255) NOT NULL DEFAULT '' COMMENT '业务类型',
`trade_id` varchar(50) NOT NULL DEFAULT '' COMMENT '业务关联id',
`refund_type` varchar(255) NOT NULL DEFAULT '' COMMENT '退款方式',
`main_type` varchar(255) NOT NULL DEFAULT '' COMMENT '操作人类型',
`main_id` int NOT NULL DEFAULT 0 COMMENT '操作人',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支付记录表' ROW_FORMAT = Dynamic;
@ -877,6 +888,7 @@ INSERT INTO `site` VALUES (1, 'niucloud-admin', '0', '', 'admin', '', '', '1', '
UPDATE `site` SET site_id = 0 WHERE site_id = 1;
INSERT INTO `sys_user` VALUES ('1', '', '', '', '', '', '0', '0', '0', '1', '0', '0', '0');
INSERT INTO `sys_user_role` VALUES ('1', '1', '0', '', '0', '1', '1');

View File

@ -275,6 +275,10 @@ return [
'offline' => '线下退款',
'balance' => '退款到余额',
'back' => '原路退款',
'status_success' => '退款成功',
'status_dealing' => '退款中',
'status_wait' => '待退款',
'status_fail' => '退款失败',
],
'dict_order_refund' => [
'refunding' => '退款中',

View File

@ -1,139 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的saas管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud-admin.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\model\article;
use app\dict\sys\FileDict;
use core\base\BaseModel;
use think\db\Query;
use think\model\relation\HasOne;
/**
* 文章模型
* Class Article
* @package app\model\article
*/
class Article extends BaseModel
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'article';
/**
* @return HasOne
*/
public function articleCategory()
{
return $this->hasOne(ArticleCategory::class, 'category_id', 'category_id')->joinType('left')->withField('category_id, name')->bind(['category_name' => 'name']);
}
/**
* 文章分类搜索器
* @param $query
* @param $value
* @param $data
*/
public function searchCategoryIdAttr($query, $value, $data)
{
if ($value) {
$query->where('category_id', $value);
}
}
/**
* 文章标题搜索器
* @param $query
* @param $value
* @param $data
*/
public function searchTitleAttr($query, $value, $data)
{
if ($value) {
$query->where('title', 'like', '%' . $value . '%');
}
}
/**
* 文章标题搜索器
* @param $query
* @param $value
* @param $data
*/
public function searchIsShowAttr($query, $value, $data)
{
if ($value != '') {
$query->where('is_show', $value);
}
}
public function searchIdsAttr(Query $query, $value, $data)
{
if (!empty($value)) {
$query->whereIn('id', $data['ids']);
}
}
/**
* 文章标题搜索器
* @param $query
* @param $value
* @param $data
*/
public function searchSortAttr($query, $value, $data)
{
if ($value) {
$query->where('sort', $value);
}
}
public function getArticleUrlAttr($value, $data)
{
$wap_domain = !empty(env("system.wap_domain")) ? preg_replace('#/$#', '', env("system.wap_domain")) : request()->domain();
$web_domain = !empty(env("system.web_domain")) ? preg_replace('#/$#', '', env("system.web_domain")) : request()->domain();
return [
'wap_url' => $wap_domain . "/wap/" . $data['site_id'] . "/pages/article/detail?id={$data['id']}",
'web_url' => $web_domain . "/web/" . $data['site_id'] . "/article/detail?id={$data['id']}"
];
}
public function getImageThumbBigAttr($value, $data)
{
if ($data['image'] != '') {
return get_thumb_images($data['site_id'], $data['image'], FileDict::BIG);
}
}
public function getImageThumbMidAttr($value, $data)
{
if ($data['image'] != '') {
return get_thumb_images($data['site_id'], $data['image'], FileDict::MID);
}
}
public function getImageThumbSmallAttr($value, $data)
{
if ($data['image'] != '') {
return get_thumb_images($data['site_id'], $data['image'], FileDict::SMALL);
}
}
}

View File

@ -1,55 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的saas管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud-admin.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\model\article;
use core\base\BaseModel;
/**
* 文章栏目模型
* Class ArticleCategory
* @package app\model\article
*/
class ArticleCategory extends BaseModel
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'category_id';
/**
* 模型名称
* @var string
*/
protected $name = 'article_category';
/**
* 文章分类名称搜索器
* @param $query
* @param $value
* @param $data
*/
public function searchNameAttr($query, $value, $data)
{
if ($value) {
$query->where([['name', 'like', "%$value%"]]);
}
}
public function getArticleNumAttr($value, $data)
{
return (new Article())->where([['category_id', '=', $data['category_id']]])->count();
}
}

View File

@ -33,4 +33,15 @@ class MemberAddress extends BaseModel
*/
protected $name = 'member_address';
/**
* 搜索器:会员收货地址地址类型 1 普通地址 2 定位地址
* @param $value
* @param $data
*/
public function searchTypeAttr($query, $value, $data)
{
if ($value) {
$query->where("type", $value);
}
}
}

View File

@ -11,6 +11,7 @@
namespace app\model\pay;
use app\dict\pay\PayDict;
use app\dict\pay\RefundDict;
use core\base\BaseModel;
@ -40,7 +41,7 @@ class Refund extends BaseModel
];
/**
* 状态字段转化
* 支付状态字段转化
* @param $value
* @param $data
* @return mixed
@ -60,7 +61,77 @@ class Refund extends BaseModel
public function getTypeNameAttr($value, $data)
{
if (empty($data['type'])) return '';
return RefundDict::getType()[$data['type']] ?? '';
return PayDict::getPayType()[$data['type']]['name'] ?? '';
}
/**
* 退款方式
* @param $value
* @param $data
* @return mixed|string
*
*/
public function getRefundTypeNameAttr($value, $data)
{
if (empty($data['refund_type'])) return '';
return RefundDict::getType()[$data['refund_type']] ?? '';
}
/**
* 创建时间搜索器
* @param $query
* @param $value
* @param $data
*/
public function searchCreateTimeAttr($query, $value, $data)
{
$start_time = empty($value[0]) ? 0 : strtotime($value[0]);
$end_time = empty($value[1]) ? 0 : strtotime($value[1]);
if ($start_time > 0 && $end_time > 0) {
$query->whereBetweenTime('create_time', $start_time, $end_time);
} else if ($start_time > 0 && $end_time == 0) {
$query->where([['create_time', '>=', $start_time]]);
} else if ($start_time == 0 && $end_time > 0) {
$query->where([['create_time', '<=', $end_time]]);
}
}
/**
* 状态
* @param $query
* @param $value
* @param $data
*/
public function searchStatusAttr($query, $value, $data)
{
if ($value != '') {
$query->where('status', '=', $value);
}
}
/**
* 状态
* @param $query
* @param $value
* @param $data
*/
public function searchOutTradeNoAttr($query, $value, $data)
{
if ($value != '') {
$query->where('out_trade_no', '=', $value);
}
}
/**
* 状态
* @param $query
* @param $value
* @param $data
*/
public function searchRefundNoAttr($query, $value, $data)
{
if ($value != '') {
$query->where('refund_no', '=', $value);
}
}
}

View File

@ -16,6 +16,8 @@ use app\service\core\addon\CoreAddonDevelopBuildService;
use app\service\core\addon\CoreAddonDevelopDownloadService;
use app\service\core\addon\CoreAddonDevelopService;
use app\service\core\addon\CoreAddonService;
use app\service\core\niucloud\CoreAppService;
use app\service\core\niucloud\CoreModuleService;
use core\base\BaseAdminService;
@ -98,4 +100,15 @@ class AddonDevelopService extends BaseAdminService
public function download(string $key){
return (new CoreAddonDevelopDownloadService($key))->download();
}
/**
* 校验key是否被占用
* @param $key
* @return array|\core\util\niucloud\http\Response|false|object|\Psr\Http\Message\ResponseInterface
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function checkKey($key)
{
return ( new CoreModuleService() )->checkKey($key);
}
}

View File

@ -235,4 +235,14 @@ class AddonService extends BaseAdminService
public function getAddonKeysBySiteId(int $site_id){
return (new CoreSiteService())->getAddonKeysBySiteId($site_id);
}
/**
* 获取插件信息
* @param int $id
* @return array
*/
public function getInfoByKey(string $key)
{
return $this->model->where([ [ 'key', '=', $key ] ])->field('title, icon, key, desc, status, cover')->findOrEmpty()->toArray();
}
}

View File

@ -53,8 +53,8 @@ class AuthSiteService extends BaseAdminService
* @param int|string $status
* @return mixed
*/
public function getMenuList(int $is_tree, int|string $status, $addon = 'all'){
return (new SiteService())->getMenuList($this->site_id, $is_tree, $status, $addon);
public function getMenuList(int $is_tree, int|string $status, $addon = 'all', int $is_button = 1){
return (new SiteService())->getMenuList($this->site_id, $is_tree, $status, $addon, $is_button);
}
/**

View File

@ -85,7 +85,7 @@ class AdminApiRouteGenerator extends BaseGenerator
$dir = dirname(root_path());
if(!empty($this->addonName))
{
$file = $dir.'\niucloud\addon\\'.$this->addonName.'\app/adminapi\route\route.php';
$file = $dir.'\niucloud\addon\\'.$this->addonName.'\app\adminapi\route\route.php';
}else{
$file = $dir.'\niucloud\app\adminapi\route\\'.$this->moduleName.'php';
}
@ -93,12 +93,12 @@ class AdminApiRouteGenerator extends BaseGenerator
if(file_exists($file))
{
$content = file_get_contents($file);
$code_begin = 'USER_CODE_BEGIN -- '.$this->getTableName();
$code_end = 'USER_CODE_END -- '.$this->getTableName();
$code_begin = 'USER_CODE_BEGIN -- '.$this->getTableName() . PHP_EOL;
$code_end = 'USER_CODE_END -- '.$this->getTableName() . PHP_EOL;
if(strpos($content,$code_begin) !== false && strpos($content,$code_end) !== false)
{
// 清除相应对应代码块
$pattern = "/\s+\/\/ {$code_begin}[\S\s]+\/\/ {$code_end}(\n,)?/";
$pattern = "/\/\/\s+{$code_begin}[\S\s]+{$code_end}?/";
$route = preg_replace($pattern, '', $content);
}else{
$route = $content;

View File

@ -146,7 +146,7 @@ abstract class BaseGenerator
// 设置模块名
$this->setModuleName($table['module_name'] ?? '');
// 设置类名
$this->setClassName($table['class_name'] ?? '');
$this->setClassName($table['class_name'] ?? $table['table_name']);
// 设置插件名
$this->setAddonName($table['addon_name'] ?? '');
// 替换模板中的文本
@ -159,19 +159,24 @@ abstract class BaseGenerator
*/
public function generate()
{
$paths = [];
if($this->table['generate_type'] == 2)
{
// 生成到runtime目录(下载)
$path = $this->getRuntimeOutDir() . $this->getFileName();
$paths[] = $this->getRuntimeOutDir() . $this->getFileName();
}else if($this->table['generate_type'] == 3){
// 生成到代码中
$path = $this->getObjectOutDir() . $this->getFileName();
$paths[] = $this->getObjectOutDir() . $this->getFileName();
// 生成到插件中
if ($this->addonName && method_exists($this, 'getAddonObjectOutDir')) $paths[] = $this->getAddonObjectOutDir() . $this->getFileName();
}
// 写入内容
if(!empty($this->getFileName()))
{
file_put_contents($path, $this->text);
foreach ($paths as $path) {
file_put_contents($path, $this->text);
}
}
}

View File

@ -146,7 +146,7 @@ class ControllerGenerator extends BaseGenerator
$last_field = end($this->table['fields'])['column_name'];
foreach ($this->table['fields'] as $v){
if(!$v['is_pk'] && $v['is_search'] && $v['column_name'] != 'site_id'){
if($v['view_type'] == 'datetime'){
if($v['query_type'] == 'BETWEEN'){
$str .= ' ["'.$v['column_name'].'",'.'["",""]'.']';
}else{
$str .= ' ["'.$v['column_name'].'",'.'""'.']';

View File

@ -58,15 +58,40 @@ class MenuSqlGenerator extends BaseGenerator
$dir = dirname(root_path());
$file = $dir.'\niucloud\addon\\'.$this->addonName.'\\sql\\install.sql';
$res = $this->getMenuSql();
$key = $res['data'][0]['menu_key'];
$result = (new SysMenu())->where([['menu_key','=',$key]])->find()->toArray();
if(!$result){
$addSql = $res['sql'];
file_put_contents($file,$addSql,FILE_APPEND);
}
$addSql = $res['sql'];
$sql = PHP_EOL . $this->getBegin() . PHP_EOL;
$sql .= $addSql . PHP_EOL;
$sql .= $this->getEnd() . PHP_EOL;
if (file_exists($file)) {
$content = file_get_contents($file);
$code_begin = '-- USER_CODE_BEGIN -- '.$this->getTableName() . PHP_EOL;
$code_end = '-- USER_CODE_END -- '.$this->getTableName() . PHP_EOL;
if(strpos($content,$code_begin) !== false && strpos($content,$code_end) !== false)
{
$pattern = "/\s+{$code_begin}[\S\s]+{$code_end}?/";
$replace_sql = preg_replace($pattern, $sql, $content);
file_put_contents($file, $replace_sql);
return;
}
}
file_put_contents($file, $sql, FILE_APPEND);
}
}
public function getBegin()
{
$begin = '-- USER_CODE_BEGIN -- '.$this->getTableName();
return $begin;
}
public function getEnd()
{
$end = '-- USER_CODE_END -- '.$this->getTableName();
return $end;
}
/**
* 获取文件生成到模块的文件夹路径
* @return string
@ -160,9 +185,9 @@ class MenuSqlGenerator extends BaseGenerator
}
if(!empty($this->addonName))
{
$key = $this->addonName.'_'.$this->table['table_name'].'_'.$this->moduleName.'_'.$name;
$key = $this->addonName.'_'.$this->moduleName.'_'.$name;
}else{
$key = $this->table['table_name'].'_'.$this->moduleName.'_'.$name;
$key = $this->moduleName.'_'.$name;
}
$data = [
[
@ -192,8 +217,8 @@ class MenuSqlGenerator extends BaseGenerator
'menu_type' => 1,
'icon' => '',
'api_url' => $this->getRouteName(),
'router_path' => 'list',
'view_path' => $this->moduleName.'/'.'list',
'router_path' => $this->className ? Str::lower($this->className) : 'list',
'view_path' => $this->moduleName.'/'.($this->className ? Str::lower($this->className) : 'list'),
'methods' => 'get',
'sort' => 90,
'status' => 1,
@ -203,38 +228,20 @@ class MenuSqlGenerator extends BaseGenerator
'addon' => $this->addonName,
'source' => MenuDict::GENERATOR
],
// [
// 'menu_name' => $table_content.'详情',
// 'menu_key' => $key.'_info',
// 'parent_key' => $key,
// 'menu_type' => 1,
// 'icon' => '',
// 'api_url' => $this->getRouteName().'/<'.'id>',
// 'router_path' => $this->moduleName,
// 'view_path' => $this->moduleName.'/'.$this->className.'_list',
// 'methods' => 'get',
// 'sort' => 80,
// 'status' => 1,
// 'is_show' => 1,
// 'create_time' => time(),
// 'delete_time' => 0,
// 'addon' => $this->addonName,
// 'source' => MenuDict::GENERATOR
// ],
[
'app_type' => 'site',
'menu_name' => $table_content.'添加',
'menu_key' => $key.'_add',
'parent_key' => $key,
'menu_type' => 2,
'menu_type' => $this->table['edit_type'] == 1 ? 2 : 1,
'icon' => '',
'api_url' => $this->getRouteName(),
'router_path' => 'edit',
'view_path' => $this->moduleName.'/'.'edit',
'router_path' => $this->table['edit_type'] == 2 ? ($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'view_path' => $this->table['edit_type'] == 2 ? $this->moduleName.'/'.($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'methods' => 'post',
'sort' => 70,
'status' => 1,
'is_show' => 1,
'is_show' => 0,
'create_time' => time(),
'delete_time' => 0,
'addon' => $this->addonName,
@ -245,17 +252,15 @@ class MenuSqlGenerator extends BaseGenerator
'menu_name' => $table_content.'编辑',
'menu_key' => $key.'_edit',
'parent_key' => $key,
'menu_type' => 2,
'menu_type' => $this->table['edit_type'] == 1 ? 2 : 1,
'icon' => '',
'api_url' => $this->getRouteName().'/<'.'id>',
'router_path' => 'edit',
'view_path' => $this->moduleName.'/'.'edit',
// 'router_path' => $this->className.'_edit',
// 'view_path' => $this->moduleName.'/'.$this->className.'_edit',
'api_url' => $this->getRouteName().'/<id>',
'router_path' => $this->table['edit_type'] == 2 ? ($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'view_path' => $this->table['edit_type'] == 2 ? $this->moduleName.'/'.($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'methods' => 'put',
'sort' => 60,
'status' => 1,
'is_show' => 1,
'is_show' => 0,
'create_time' => time(),
'delete_time' => 0,
'addon' => $this->addonName,
@ -268,13 +273,13 @@ class MenuSqlGenerator extends BaseGenerator
'parent_key' => $key,
'menu_type' => 2,
'icon' => '',
'api_url' => $this->getRouteName().'/<'.'id>',
'api_url' => $this->getRouteName().'/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => 50,
'status' => 1,
'is_show' => 1,
'is_show' => 0,
'create_time' => time(),
'delete_time' => 0,
'addon' => $this->addonName,
@ -286,11 +291,9 @@ class MenuSqlGenerator extends BaseGenerator
$sql = str_replace(' (', PHP_EOL.'(', $sql);
$res = [
'data' => $data,
'sql' => $sql
'sql' => $sql . ';'
];
return $res;
}
/**
@ -299,12 +302,14 @@ class MenuSqlGenerator extends BaseGenerator
*/
public function getRouteName()
{
//如果是某个模块下的功能,公用一个路由
$group_name = !empty($this->addonName) ? $this->addonName : $this->moduleName;
if($this->moduleName && ($this->getLCaseTableName() != $this->moduleName) && $this->className){
return Str::lower($this->className);
$route_name = Str::lower($this->className);
}else{
return $this->getLCaseTableName();
$route_name = $this->getLCaseTableName();
}
return $group_name .'/' . $route_name;
}
/**
@ -366,8 +371,8 @@ class MenuSqlGenerator extends BaseGenerator
'menu_type' => 1,
'icon' => '',
'api_url' => $this->getRouteName(),
'router_path' => 'list',
'view_path' => $this->moduleName.'/'.'list',
'router_path' => $this->className ? Str::lower($this->className) : 'list',
'view_path' => $this->moduleName.'/'.($this->className ? Str::lower($this->className) : 'list'),
'methods' => 'get',
'sort' => 90,
'status' => 1,
@ -377,38 +382,20 @@ class MenuSqlGenerator extends BaseGenerator
'addon' => $this->addonName,
'source' => MenuDict::GENERATOR
],
// [
// 'menu_name' => $table_content.'详情',
// 'menu_key' => $key.'_info',
// 'parent_key' => $key,
// 'menu_type' => 1,
// 'icon' => '',
// 'api_url' => $this->getRouteName().'/<'.'id>',
// 'router_path' => $this->moduleName,
// 'view_path' => $this->moduleName.'/'.$this->className.'_list',
// 'methods' => 'get',
// 'sort' => 80,
// 'status' => 1,
// 'is_show' => 1,
// 'create_time' => time(),
// 'delete_time' => 0,
// 'addon' => $this->addonName,
// 'source' => MenuDict::GENERATOR
// ],
[
'app_type' => 'site',
'menu_name' => $table_content.'添加',
'menu_key' => $key.'_add',
'parent_key' => $key,
'menu_type' => 2,
'menu_type' => $this->table['edit_type'] == 1 ? 2 : 1,
'icon' => '',
'api_url' => $this->getRouteName(),
'router_path' => 'edit',
'view_path' => $this->moduleName.'/'.'edit',
'router_path' => $this->table['edit_type'] == 2 ? ($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'view_path' => $this->table['edit_type'] == 2 ? $this->moduleName.'/'.($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'methods' => 'post',
'sort' => 70,
'status' => 1,
'is_show' => 1,
'is_show' => 0,
'create_time' => time(),
'delete_time' => 0,
'addon' => $this->addonName,
@ -419,17 +406,15 @@ class MenuSqlGenerator extends BaseGenerator
'menu_name' => $table_content.'编辑',
'menu_key' => $key.'_edit',
'parent_key' => $key,
'menu_type' => 2,
'menu_type' => $this->table['edit_type'] == 1 ? 2 : 1,
'icon' => '',
'api_url' => $this->getRouteName().'/<'.'id>',
'router_path' => 'edit',
'view_path' => $this->moduleName.'/'.'edit',
// 'router_path' => $this->className.'_edit',
// 'view_path' => $this->moduleName.'/'.$this->className.'_edit',
'api_url' => $this->getRouteName().'/<id>',
'router_path' => $this->table['edit_type'] == 2 ? ($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'view_path' => $this->table['edit_type'] == 2 ? $this->moduleName.'/'.($this->className ? Str::lower($this->className) . '_edit' : 'edit') : '',
'methods' => 'put',
'sort' => 60,
'status' => 1,
'is_show' => 1,
'is_show' => 0,
'create_time' => time(),
'delete_time' => 0,
'addon' => $this->addonName,
@ -442,13 +427,13 @@ class MenuSqlGenerator extends BaseGenerator
'parent_key' => $key,
'menu_type' => 2,
'icon' => '',
'api_url' => $this->getRouteName().'/<'.'id>',
'api_url' => $this->getRouteName().'/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => 50,
'status' => 1,
'is_show' => 1,
'is_show' => 0,
'create_time' => time(),
'delete_time' => 0,
'addon' => $this->addonName,
@ -457,13 +442,11 @@ class MenuSqlGenerator extends BaseGenerator
];
$menu_model = new SysMenu();
$result = (new SysMenu())->where([['menu_key','=',$key]])->find();
(new SysMenu())->where([['app_type', '=', 'site'],['menu_key','in', array_column($data, 'menu_key') ]])->select()->delete();
if(empty($result)){
(new $menu_model())->saveAll($data);
$cache_tag_name = 'menu_cache';
Cache::tag($cache_tag_name)->clear();
}
(new $menu_model())->saveAll($data);
$cache_tag_name = 'menu_cache';
Cache::tag($cache_tag_name)->clear();
return true;
}

View File

@ -162,14 +162,19 @@ class ModelGenerator extends BaseGenerator
public function getSearchContent(array $column_info){
$type = $column_info['query_type'];
if ($type == 'BETWEEN') {
$function_str = ' $start_time = empty($value[0]) ? 0 : strtotime($value[0]);'.PHP_EOL;
$function_str .= ' $end_time = empty($value[1]) ? 0 : strtotime($value[1]);'.PHP_EOL;
$function_str .= ' if ($start_time > 0 && $end_time > 0) {'.PHP_EOL;
$function_str .= ' $query->whereBetweenTime("' . $column_info['column_name'] . '", $start_time, $end_time);'.PHP_EOL;
$function_str .= ' } else if ($start_time > 0 && $end_time == 0) {'.PHP_EOL;
$function_str .= ' $query->where([["' . $column_info['column_name'] . '", ">=", $start_time]]);'.PHP_EOL;
$function_str .= ' } else if ($start_time == 0 && $end_time > 0) {'.PHP_EOL;
$function_str .= ' $query->where([["' . $column_info['column_name'] . '", "<=", $end_time]]);'.PHP_EOL;
if ($column_info['view_type'] == 'datetime') {
$function_str = ' $start = empty($value[0]) ? 0 : strtotime($value[0]);'.PHP_EOL;
$function_str .= ' $end = empty($value[1]) ? 0 : strtotime($value[1]);'.PHP_EOL;
} else {
$function_str = ' $start = empty($value[0]) ? 0 : $value[0];'.PHP_EOL;
$function_str .= ' $end = empty($value[1]) ? 0 : $value[1];'.PHP_EOL;
}
$function_str .= ' if ($start > 0 && $end > 0) {'.PHP_EOL;
$function_str .= ' $query->where([["' . $column_info['column_name'] . '", "between", [$start, $end]]]);'.PHP_EOL;
$function_str .= ' } else if ($start > 0 && $end == 0) {'.PHP_EOL;
$function_str .= ' $query->where([["' . $column_info['column_name'] . '", ">=", $start]]);'.PHP_EOL;
$function_str .= ' } else if ($start == 0 && $end > 0) {'.PHP_EOL;
$function_str .= ' $query->where([["' . $column_info['column_name'] . '", "<=", $end]]);'.PHP_EOL;
$function_str .= ' }'.PHP_EOL;
return $function_str;
} else {
@ -345,7 +350,7 @@ class ModelGenerator extends BaseGenerator
$waitReplace = [
$config['name'],
$config['model'],
'\\'. $config['model'],
$config['foreign_key'],
$config['local_key'],
];

View File

@ -110,6 +110,7 @@ class ServiceGenerator extends BaseGenerator
}
$field[] = '"'.$column['column_name'].'"';
}
return implode(',', $field);
}

View File

@ -85,11 +85,10 @@ class WebApiGenerator extends BaseGenerator
{
if(!empty($this->addonName))
{
$dir = dirname(app()->getRootPath()) . '/admin/src/api/';
$dir = dirname(app()->getRootPath()) . '/admin/src/'. $this->addonName .'/api/';
}else{
$dir = dirname(app()->getRootPath()) . '/admin/src/app/api/';
}
$this->checkDir($dir);
return $dir;
}
@ -113,14 +112,13 @@ class WebApiGenerator extends BaseGenerator
{
$content = file_get_contents($file);
$code_begin = 'USER_CODE_BEGIN -- '.$this->getTableName();
$code_end = 'USER_CODE_END -- '.$this->getTableName();
$code_begin = 'USER_CODE_BEGIN -- '.$this->getTableName() . PHP_EOL;
$code_end = 'USER_CODE_END -- '.$this->getTableName(). PHP_EOL;
if(strpos($content,$code_begin) !== false && strpos($content,$code_end) !== false)
{
// 清除相应对应代码块
$pattern = "/\s+\/\/ {$code_begin}[\S\s]+\/\/ {$code_end}(\n,)?/";
$pattern = "/\/\/\s+{$code_begin}[\S\s]+{$code_end}?/";
$import = preg_replace($pattern, '', $content);
}else{
@ -153,12 +151,11 @@ class WebApiGenerator extends BaseGenerator
{
if(!empty($this->addonName))
{
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/src/api/';
$dir = $this->outDir . 'addon/'.$this->addonName.'/admin/api/';
}else{
$dir = $this->outDir . 'admin/src/api/';
$dir = $this->outDir . 'admin/src/app/api/';
}
$this->checkDir($dir);
return $dir;
}
@ -180,12 +177,21 @@ class WebApiGenerator extends BaseGenerator
return $dir;
}
/**
* 获取文件生成到插件中
* @return void
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . '/niucloud/addon/'.$this->addonName.'/admin/api/';
$this->checkDir($dir);
return $dir;
}
public function getFilePath()
{
if(!empty($this->addonName))
{
$dir = 'addon/'.$this->addonName.'/admin/'.$this->addonName.'/api/';
$dir = 'addon/'.$this->addonName.'/admin/api/';
}else{
$dir = 'admin/app/api/';
}

View File

@ -223,7 +223,7 @@ class WebEditGenerator extends BaseGenerator
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if (empty($column['dict_type']) || $column['is_pk']) {
if (empty($column['dict_type']) || $column['is_pk'] || $column['column_name'] == 'site_id') {
continue;
}
if (in_array($column['dict_type'], $isExist)) {
@ -274,7 +274,6 @@ class WebEditGenerator extends BaseGenerator
if (!empty($content)) {
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
@ -290,10 +289,7 @@ class WebEditGenerator extends BaseGenerator
$specDictType = ['input', 'textarea', 'editor'];
foreach ($this->tableColumn as $column) {
// if (!$column['is_pk']) {
// continue;
// }
if (!$column['is_insert'] || !$column['is_update'] || $column['column_name'] == 'site_id') {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk'] || $column['column_name'] == 'site_id') {
continue;
}
if (in_array($column['column_name'], $isExist)) {
@ -392,7 +388,7 @@ class WebEditGenerator extends BaseGenerator
}
if(!empty($this->addonName))
{
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/src/views/' . $this->moduleName . '/';
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/views/' . $this->moduleName . '/';
}else{
$dir = $this->outDir . 'admin/src/app/views/' . $this->moduleName . '/';
}
@ -421,6 +417,16 @@ class WebEditGenerator extends BaseGenerator
return $dir;
}
/**
* 获取文件生成到插件中
* @return void
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . '/niucloud/addon/'.$this->addonName.'/admin/views/'. $this->moduleName . '/components/';
$this->checkDir($dir);
return $dir;
}
public function getFilePath()
{
if($this->table['edit_type'] != 1) {
@ -446,6 +452,9 @@ class WebEditGenerator extends BaseGenerator
if($this->table['edit_type'] != 1) {
return '';
}
if($this->className){
return str_replace('_', '-', Str::lower($this->className)).'-edit.vue';
}
return 'edit.vue';
}
@ -479,6 +488,9 @@ class WebEditGenerator extends BaseGenerator
continue;
}
$content.= 'let '.$column['column_name'].'List = ref([])'.PHP_EOL.'const '.$column['column_name'].'DictList = async () => {'.PHP_EOL.$column['column_name'].'List.value = await (await useDictionary(' ."'".$column['dict_type']."'".')).data.dictionary'.PHP_EOL.'}'.PHP_EOL. $column['column_name'].'DictList();'.PHP_EOL;
if ($column['view_type'] == 'radio' || $column['view_type'] == 'select') {
$content .= 'watch(() => '.$column['column_name'].'List.value, () => { formData.'.$column['column_name'].' = '.$column['column_name'].'List.value[0].value })'.PHP_EOL;
}
}
if(!empty($content))

View File

@ -90,7 +90,12 @@ class WebEditLangGenerator extends BaseGenerator
if($this->table['edit_type'] != 2) {
return '';
}
$dir = dirname(app()->getRootPath()) . '/admin/src/lang/zh-cn/';
if(!empty($this->addonName))
{
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/lang/zh-cn/';
}else{
$dir = $this->outDir . 'admin/src/app/lang/zh-cn/';
}
$this->checkDir($dir);
return $dir;
}
@ -107,13 +112,10 @@ class WebEditLangGenerator extends BaseGenerator
}
if(!empty($this->addonName))
{
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/src/lang/zh-cn/';
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/lang/zh-cn/';
}else{
$dir = $this->outDir . 'admin/src/lang/zh-cn/';
$dir = $this->outDir . 'admin/src/app/lang/zh-cn/';
}
$this->checkDir($dir);
return $dir;
}
@ -139,6 +141,16 @@ class WebEditLangGenerator extends BaseGenerator
return $dir;
}
/**
* 获取文件生成到插件中
* @return void
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . '/niucloud/addon/'.$this->addonName.'/admin/lang/zh-cn/';
$this->checkDir($dir);
return $dir;
}
public function getFilePath()
{
if($this->table['edit_type'] != 2) {
@ -146,7 +158,7 @@ class WebEditLangGenerator extends BaseGenerator
}
if(!empty($this->addonName))
{
$dir = 'addon/'.$this->addonName.'/admin/'.$this->addonName.'/lang/zh-cn/';
$dir = 'addon/'.$this->addonName.'/admin/lang/zh-cn/';
}else{
$dir = 'admin/app/lang/zh-cn/';

View File

@ -81,7 +81,7 @@ class WebEditPageGenerator extends BaseGenerator
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if (empty($column['dict_type']) || $column['is_pk']) {
if (empty($column['dict_type']) || $column['is_pk'] || $column['column_name'] == 'site_id') {
continue;
}
if (in_array($column['dict_type'], $isExist)) {
@ -110,6 +110,9 @@ class WebEditPageGenerator extends BaseGenerator
continue;
}
$content.= 'let '.$column['column_name'].'List = ref([])'.PHP_EOL.'const '.$column['column_name'].'DictList = async () => {'.PHP_EOL.$column['column_name'].'List.value = await (await useDictionary(' ."'".$column['dict_type']."'".')).data.dictionary'.PHP_EOL.'}'.PHP_EOL. $column['column_name'].'DictList();'.PHP_EOL;
if ($column['view_type'] == 'radio' || $column['view_type'] == 'select') {
$content .= 'watch(() => '.$column['column_name'].'List.value, () => { formData.'.$column['column_name'].' = '.$column['column_name'].'List.value[0].value })'.PHP_EOL;
}
}
if(!empty($content))
@ -199,7 +202,7 @@ class WebEditPageGenerator extends BaseGenerator
$vmItemValue = 'item.value';
$intFieldValue = ['tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint'];
if (in_array($column['column_type'], $intFieldValue)) {
$vmItemValue = 'parseInt(item.value)';
$vmItemValue = 'item.value';
}
$old[] = '{ITEM_VALUE}';
$new[] = $vmItemValue;
@ -223,7 +226,6 @@ class WebEditPageGenerator extends BaseGenerator
}
$old[] = '{RULE}';
$new[] = $rule;
dd($rule);
}else{
$old[] = '{RULE}';
$new[] = '';
@ -249,6 +251,7 @@ class WebEditPageGenerator extends BaseGenerator
{
$content = '';
$isExist = [];
foreach ($this->tableColumn as $column) {
if ((!$column['is_insert'] || !$column['is_update'] || $column['column_name'] == 'site_id') && !$column['is_pk']) {
continue;
@ -284,13 +287,12 @@ class WebEditPageGenerator extends BaseGenerator
$content = '';
$isExist = [];
$specDictType = ['input', 'textarea', 'editor'];
unset($this->tableColumn[1]);
unset($this->tableColumn[2]);
unset($this->tableColumn[3]);
foreach ($this->tableColumn as $column) {
if (!$column['is_insert'] || !$column['is_update'] || $column['column_name'] == 'site_id') {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk'] || $column['column_name'] == 'site_id') {
continue;
}
if (in_array($column['column_name'], $isExist)) {
continue;
}
@ -374,7 +376,12 @@ class WebEditPageGenerator extends BaseGenerator
if($this->table['edit_type'] != 2) {
return '';
}
$dir = dirname(app()->getRootPath()) . '/admin/src/views/' . $this->moduleName . '/';
if(!empty($this->addonName))
{
$dir = dirname(app()->getRootPath()) . '/admin/src/'. $this->moduleName .'/views/' . $this->moduleName . '/';
} else {
$dir = dirname(app()->getRootPath()) . '/admin/src/app/views/' . $this->moduleName . '/';
}
$this->checkDir($dir);
return $dir;
}
@ -391,7 +398,7 @@ class WebEditPageGenerator extends BaseGenerator
}
if(!empty($this->addonName))
{
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/src/views/' . $this->moduleName . '/';
$dir = $this->outDir . '/addon/'.$this->addonName.'/admin/views/' . $this->moduleName . '/';
}else{
$dir = $this->outDir . 'admin/src/app/views/' . $this->moduleName . '/';
}
@ -422,6 +429,16 @@ class WebEditPageGenerator extends BaseGenerator
return $dir;
}
/**
* 获取文件生成到插件中
* @return void
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . '/niucloud/addon/'.$this->addonName.'/admin/views/'. $this->moduleName . '/';
$this->checkDir($dir);
return $dir;
}
public function getFilePath()
{
if($this->table['edit_type'] != 2) {
@ -447,9 +464,9 @@ class WebEditPageGenerator extends BaseGenerator
if($this->table['edit_type'] != 2) {
return '';
}
// if($this->className){
// return Str::lower($this->className).'_edit.vue';
// }
if($this->className){
return Str::lower($this->className).'_edit.vue';
}
return 'edit.vue';
}

View File

@ -15,6 +15,7 @@ namespace app\service\admin\generator\core;
use app\service\core\menu\CoreMenuService;
use think\helper\Str;
/**
@ -106,9 +107,9 @@ class WebIndexGenerator extends BaseGenerator
$path = 'components/';
// $file_name = str_replace('_', '-', Str::lower($this->getTableName())).'-edit.vue';
$file_name = 'edit.vue';
// if($this->className){
// $file_name = Str::lower($this->className) . '-edit.vue';
// }
if($this->className){
$file_name = str_replace('_', '-', Str::lower($this->className)) . '-edit.vue';
}
if(!empty($this->addonName))
{
return "import "."Edit from '@/".$this->addonName."/views/".$this->moduleName."/".$path.$file_name."'";
@ -146,8 +147,12 @@ class WebIndexGenerator extends BaseGenerator
{
$class_name = $this->className ? '/'.Str::lower($this->className) : '';
if($this->table['edit_type'] == 2){
$route = '';
if (!empty($this->table['parent_menu'])) {
$route = '/' . (new CoreMenuService())->getRoutePathByMenuKey($this->table['parent_menu']);
}
//打开新页面
$content = "router.push('/".$this->moduleName."/edit')";
$content = "router.push('".$route."/".$this->moduleName."/". Str::lower($this->className) ."_edit')";
}else{
$content = 'edit'.$this->getUCaseClassName().'Dialog.value.setFormData()'.PHP_EOL.'edit'.$this->getUCaseClassName().'Dialog.value.showDialog = true';
}
@ -164,7 +169,11 @@ class WebIndexGenerator extends BaseGenerator
{
$class_name = $this->className ? '/'.Str::lower($this->className) : '';
if($this->table['edit_type'] == 2){
$content = "router.push('/".$this->moduleName."/edit?id='+data.".$this->getPk().")";
$route = '';
if (!empty($this->table['parent_menu'])) {
$route = '/' . (new CoreMenuService())->getRoutePathByMenuKey($this->table['parent_menu']);
}
$content = "router.push('".$route."/".$this->moduleName."/". Str::lower($this->className) ."_edit?id='+data.".$this->getPk().")";
}else{
$content = 'edit'.$this->getUCaseClassName().'Dialog.value.setFormData(data)'.PHP_EOL.'edit'.$this->getUCaseClassName().'Dialog.value.showDialog = true';
}
@ -224,6 +233,9 @@ class WebIndexGenerator extends BaseGenerator
$searchVmType = 'select';
}
}
if ($column['query_type'] == 'BETWEEN') {
$searchVmType = $column['view_type'] == 'datetime' ? 'datetime' : 'rangeInput';
}
$vmPath = $this->getvmPath('search/' . $searchVmType);
if (!file_exists($vmPath)) {
@ -247,13 +259,18 @@ class WebIndexGenerator extends BaseGenerator
*/
public function getSearchParams()
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_search'] || $column['is_pk']) {
continue;
}
$content .= '"'.$column['column_name'].'":"",' . PHP_EOL;
if ($column['query_type'] == 'BETWEEN') {
$content .= '"'.$column['column_name'].'":[],' . PHP_EOL;
} else {
$content .= '"'.$column['column_name'].'":"",' . PHP_EOL;
}
}
if (!empty($content)) {
@ -279,12 +296,14 @@ class WebIndexGenerator extends BaseGenerator
$old = [
'{COLUMN_COMMENT}',
'{COLUMN_NAME}',
'{LANG}'
'{LANG}',
'{DICT_TYPE}'
];
$new = [
$column['column_comment'],
$column['column_name'],
Str::camel($column['column_name'])
Str::camel($column['column_name']),
$column['column_name'].'List'
];
$vmPath = $this->getvmPath('table/default');
@ -295,6 +314,11 @@ class WebIndexGenerator extends BaseGenerator
if ($column['column_type'] == 'int' && $column['view_type'] == 'datetime') {
$vmPath = $this->getvmPath('table/datetime');
}
if ($column['dict_type']) {
$vmPath = $this->getvmPath('table/dictcolumn');
}
if (!file_exists($vmPath)) {
continue;
}
@ -341,7 +365,12 @@ class WebIndexGenerator extends BaseGenerator
*/
public function getModuleOutDir()
{
$dir = dirname(app()->getRootPath()) . '/admin/src/views/' . $this->moduleName . '/';
if(!empty($this->addonName))
{
$dir = dirname(app()->getRootPath()) . '/admin/src/'. $this->addonName .'/views/';
}else{
$dir = dirname(app()->getRootPath()) . '/admin/src/app/views/';
}
$this->checkDir($dir);
return $dir;
@ -356,10 +385,10 @@ class WebIndexGenerator extends BaseGenerator
{
if(!empty($this->addonName))
{
$dir = $this->outDir . 'addon/'.$this->addonName.'/admin/src/views/' . $this->moduleName . '/';
$dir = $this->outDir . 'addon/'.$this->addonName.'/admin/views/' . $this->moduleName . '/';
}else{
$dir = $this->outDir . 'admin/src/views/' . $this->moduleName . '/';
$dir = $this->outDir . 'admin/src/app/views/' . $this->moduleName . '/';
}
@ -385,6 +414,16 @@ class WebIndexGenerator extends BaseGenerator
return $dir;
}
/**
* 获取文件生成到插件中
* @return void
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . '/niucloud/addon/'.$this->addonName.'/admin/views/'. $this->moduleName . '/';
$this->checkDir($dir);
return $dir;
}
public function getFilePath()
{
if(!empty($this->addonName))
@ -402,7 +441,7 @@ class WebIndexGenerator extends BaseGenerator
*/
public function getFileName()
{
// if($this->className) return Str::lower($this->className).'_list.vue';
if($this->className) return Str::lower($this->className).'.vue';
return 'list.vue';
}
@ -454,18 +493,13 @@ class WebIndexGenerator extends BaseGenerator
{
continue;
}
if($column['view_type'] == 'select')
{
$content.= 'let '.$column['column_name'].'List = ref([])'.PHP_EOL.'const '.$column['column_name'].'DictList = async () => {'.PHP_EOL.$column['column_name'].'List.value = await (await useDictionary(' ."'".$column['dict_type']."'".')).data.dictionary'.PHP_EOL.'}'.PHP_EOL. $column['column_name'].'DictList();'.PHP_EOL;
}
$content.= 'const '.$column['column_name'].'List = ref([])'.PHP_EOL.'const '.$column['column_name'].'DictList = async () => {'.PHP_EOL.$column['column_name'].'List.value = await (await useDictionary(' ."'".$column['dict_type']."'".')).data.dictionary'.PHP_EOL.'}'.PHP_EOL. $column['column_name'].'DictList();'.PHP_EOL;
}
if(!empty($content))
{
$content = substr($content, 0, -1);
}
return $this->setBlankSpace($content, ' ');
}
}

View File

@ -76,6 +76,8 @@ class WebLangGenerator extends BaseGenerator
$lang .= '"add'.$this->getUCaseClassName() .'":"添加'.$table_content.'",'.PHP_EOL;
$lang .= '"update'.$this->getUCaseClassName() .'":"编辑'.$table_content.'",'.PHP_EOL;
$lang .= '"'.$this->getLCaseClassName() .'DeleteTips":"确定要删除该数据吗?",'.PHP_EOL;
$lang .= '"startDate":"请选择开始时间",'.PHP_EOL;
$lang .= '"endDate":"请选择结束时间",'.PHP_EOL;
$lang = trim(trim($lang), ',');
return '{'.PHP_EOL.$this->setBlankSpace($lang, " ").PHP_EOL.'}';
}
@ -86,7 +88,12 @@ class WebLangGenerator extends BaseGenerator
*/
public function getModuleOutDir()
{
$dir = dirname(app()->getRootPath()) . '/admin/src/lang/zh-cn/';
if(!empty($this->addonName))
{
$dir = dirname(app()->getRootPath()) . '/admin/src/'. $this->addonName .'/lang/zh-cn/';
} else {
$dir = dirname(app()->getRootPath()) . '/admin/src/app/lang/zh-cn/';
}
$this->checkDir($dir);
return $dir;
}
@ -100,10 +107,10 @@ class WebLangGenerator extends BaseGenerator
{
if(!empty($this->addonName))
{
$dir = $this->outDir . 'addon/'.$this->addonName.'/admin/src/lang/zh-cn/';
$dir = $this->outDir . 'addon/'.$this->addonName.'/admin/lang/zh-cn/';
}else{
$dir = $this->outDir . 'admin/src/lang/zh-cn/';
$dir = $this->outDir . 'admin/src/app/lang/zh-cn/';
}
$this->checkDir($dir);
@ -127,11 +134,21 @@ class WebLangGenerator extends BaseGenerator
return $dir;
}
/**
* 获取文件生成到插件中
* @return void
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . '/niucloud/addon/'.$this->addonName.'/admin/lang/zh-cn/';
$this->checkDir($dir);
return $dir;
}
public function getFilePath()
{
if(!empty($this->addonName))
{
$dir = 'addon/'.$this->addonName.'/admin/'.$this->addonName.'/lang/zh-cn/';
$dir = 'addon/'.$this->addonName.'/admin/lang/zh-cn/';
}else{
$dir = 'admin/app/lang/zh-cn/';
@ -146,7 +163,7 @@ class WebLangGenerator extends BaseGenerator
public function getFileName()
{
if($this->className){
return $this->moduleName.'.'.'list.json';
return $this->moduleName.'.'. Str::lower($this->className) .'.json';
}
return $this->moduleName.'.list.json';
}

View File

@ -1,6 +1,4 @@
<el-form-item :label="t('{LCASE_COLUMN_NAME}')" prop="{COLUMN_NAME}">
<daterange-picker
v-model:startTime="{LCASE_CLASS_NAME}Table.searchParam.start_time"
v-model:endTime="{LCASE_CLASS_NAME}Table.searchParam.end_time"
/>
<el-date-picker v-model="{LCASE_CLASS_NAME}Table.searchParam.{COLUMN_NAME}" type="datetimerange" format="YYYY-MM-DD hh:mm:ss"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
</el-form-item>

View File

@ -0,0 +1,3 @@
<el-form-item :label="t('{LCASE_COLUMN_NAME}')" prop="{COLUMN_NAME}">
<range-input v-model="{LCASE_CLASS_NAME}Table.searchParam.{COLUMN_NAME}"/>
</el-form-item>

View File

@ -1,4 +1,4 @@
<el-table-column :label="t('{LANG}')" min-width="180" align="center">
<el-table-column :label="t('{LANG}')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.{COLUMN_NAME} || '' }}
</template>

View File

@ -1 +1 @@
<el-table-column prop="{COLUMN_NAME}" :label="t('{LANG}')" min-width="120" />
<el-table-column prop="{COLUMN_NAME}" :label="t('{LANG}')" min-width="120" :show-overflow-tooltip="true"/>

View File

@ -0,0 +1,7 @@
<el-table-column :label="t('{LANG}')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in {DICT_TYPE}">
<div v-if="item.value == row.{COLUMN_NAME}">{{ item.name }}</div>
</div>
</template>
</el-table-column>

View File

@ -10,13 +10,13 @@
// +----------------------------------------------------------------------
{NAMESPACE}
use think\Validate;
use core\base\BaseValidate;
/**
* {CLASS_COMMENT}
* Class {UCASE_NAME}
* @package {PACKAGE_NAME}
*/
class {UCASE_NAME} extends Validate
class {UCASE_NAME} extends BaseValidate
{
protected $rule = {RULE};

View File

@ -1,8 +1,6 @@
{IMPORT}
{BEGIN}
/**
* 获取{NOTES}列表
* @param params

View File

@ -17,7 +17,7 @@
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'

View File

@ -23,7 +23,7 @@
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { ref, reactive, computed, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import type { FormInstance } from 'element-plus'
@ -36,6 +36,7 @@ const loading = ref(false)
const pageName = route.meta.title
/**
* 表单数据
*/

View File

@ -75,6 +75,7 @@ const selectData = ref<any[]>([])
// 字典数据
{DICT_LIST}
/**
* 获取{NOTES}列表
*/

View File

@ -0,0 +1,67 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\admin\pay;
use app\dict\pay\PayDict;
use app\model\pay\Pay;
use app\model\pay\Refund;
use app\service\core\pay\CoreRefundService;
use app\service\core\paytype\CoreOfflineService;
use core\base\BaseAdminService;
/**
* 退款服务层
*/
class RefundService extends BaseAdminService
{
public function __construct()
{
parent::__construct();
$this->model = new Refund();
}
/**
* 退款账户记录
* @param array $where
* @return mixed
*/
public function getPage(array $where){
$field = 'id,refund_no,out_trade_no,type,channel,money,reason,status,create_time,refund_time,close_time,fail_reason,voucher,trade_type,trade_id,refund_type,main_type,main_id';
$search_model = $this->model->where([ [ 'site_id', '=', $this->site_id ] ])->withSearch([ 'create_time', 'out_trade_no', 'refund_no', 'status' ], $where)->field($field)->append([ 'type_name', 'status_name' ])->order('create_time desc');
return $this->pageQuery($search_model);
}
/**
* 获取退款详情
* @param string $refund_no
* @return void
*/
public function getDetail(string $refund_no){
$field = 'id,refund_no,out_trade_no,type,channel,money,reason,status,create_time,refund_time,close_time,fail_reason,voucher,trade_type,trade_id,refund_type,main_type,main_id';
return $this->model->where([ ['refund_no', '=', $refund_no ], [ 'site_id', '=', $this->site_id ] ])
->field($field)
->append([ 'type_name', 'status_name', 'refund_type_name' ])
->findOrEmpty()
->toArray();
}
/**
* 支付审核通过
* @param array $data
* @return null
*/
public function refund(array $data) {
return (new CoreRefundService())->refund($this->site_id, $data['refund_no'], $data['voucher'], $data['refund_type'], PayDict::USER, $this->uid);
}
}

View File

@ -61,7 +61,12 @@ class SiteService extends BaseAdminService
[ 'app_type', '<>', 'admin' ]
];
$search_model = $this->model->where($condition)->withSearch([ 'create_time', 'expire_time', 'keywords', 'status', 'group_id', 'app' ], $where)->with(['groupName', 'addonName'])->field($field)->append([ 'status_name' ])->order('create_time desc');
return $this->pageQuery($search_model);
return $this->pageQuery($search_model, function ($item){
$item['admin'] = (new SysUserRole())->where([ ['site_id', '=', $item['site_id'] ], ['is_admin', '=', 1] ])
->field('uid')
->with(['userinfo'])
->find()->toArray();
});
}
/**
@ -93,7 +98,7 @@ class SiteService extends BaseAdminService
$user_service = new UserService();
if ($user_service->checkUsername($data[ 'username' ])) throw new AdminException('USERNAME_REPEAT');
$site_group = (new SiteGroup())->where([ ['group_id', '=', $data[ 'group_id' ] ] ])->field('app')->findOrEmpty();
$site_group = (new SiteGroup())->where([ ['group_id', '=', $data[ 'group_id' ] ] ])->field('app,addon')->findOrEmpty();
$data[ 'app_type' ] = 'site';
//添加站点
@ -128,7 +133,7 @@ class SiteService extends BaseAdminService
}
//添加站点成功事件
event("AddSiteAfter", [ 'site_id' => $site_id ]);
event("AddSiteAfter", [ 'site_id' => $site_id, 'main_app' => $site_group['app'], 'site_addons' => $site_group['addon'] ]);
Cache::delete('user_role_list_' . $data['uid']);
@ -197,21 +202,21 @@ class SiteService extends BaseAdminService
* @throws DbException
* @throws ModelNotFoundException
*/
public function getMenuList(int $site_id, $is_tree, $status, $addon = 'all')
public function getMenuList(int $site_id, $is_tree, $status, $addon = 'all', int $is_button = 1)
{
$site_info = $this->getSiteCache($site_id);
if (empty($site_info))
return [];
$app_type = $site_info[ 'app_type' ];
if ($app_type == AppTypeDict::ADMIN) {
return ( new MenuService() )->getAllMenuList($app_type, $status, $is_tree, 1);
return ( new MenuService() )->getAllMenuList($app_type, $status, $is_tree, $is_button);
} else {
$addons = ( new AddonService() )->getAddonKeysBySiteId($site_id);
$addons[] = '';
if($addon != 'all'){
$addons = [$addon];
}
return ( new MenuService() )->getMenuListBySystem($this->app_type, $addons, $is_tree);
return ( new MenuService() )->getMenuListBySystem($this->app_type, $addons, $is_tree, $is_button);
}

View File

@ -73,6 +73,29 @@ class AreaService extends BaseAdminService
);
}
public function getAreaByAreaCode($id) {
$cache_name = self::$cache_tag_name.'_area_'. $id;
return cache_remember(
$cache_name,
function() use($id) {
$level = [1 => 'province', 2 => 'city', 3 => 'district'];
$tree = [];
$area = $this->model->where([ ['id', '=', $id] ])->field('id,level,pid,name')->findOrEmpty();
if (!$area->isEmpty()) {
$tree[ $level[ $area['level'] ] ] = $area->toArray();
while ($area['level'] > 1) {
$area = $this->model->where([ ['id', '=', $area['pid'] ] ])->field('id,level,pid,name')->findOrEmpty();
$tree[ $level[ $area['level'] ] ] = $area->toArray();
}
}
return $tree;
},
[self::$cache_tag_name]
);
}
/**
* @param string $address
* @return int|mixed

View File

@ -61,9 +61,10 @@ class MenuService extends BaseAdminService
* @param array $data
* @return SysMenu
*/
public function edit(string $menu_key, array $data)
public function edit(string $app_type, string $menu_key, array $data)
{
$where = array(
['app_type', '=', $app_type],
['menu_key', '=', $menu_key]
);
$res = $this->model->update($data, $where);
@ -76,8 +77,8 @@ class MenuService extends BaseAdminService
* @param string $menu_key
* @return array
*/
public function get(string $menu_key){
return $this->model->where([['menu_key', '=', $menu_key]])->findOrEmpty()->toArray();
public function get(string $app_type, string $menu_key){
return $this->model->where([['app_type', '=', $app_type],['menu_key', '=', $menu_key]])->findOrEmpty()->toArray();
}
/**
@ -104,10 +105,10 @@ class MenuService extends BaseAdminService
* @return bool
* @throws DbException
*/
public function del(string $menu_key){
public function del(string $app_type, string $menu_key){
//查询是否有下级菜单或按钮
$menu = $this->find($menu_key);
if($this->model->where([['parent_key', '=', $menu_key]])->count() > 0)
$menu = $this->find($menu_key, $app_type);
if($this->model->where([['parent_key', '=', $menu_key], ['app_type', '=', $app_type]])->count() > 0)
throw new AdminException('MENU_NOT_ALLOW_DELETE');
$res = $menu->delete();
@ -480,7 +481,7 @@ class MenuService extends BaseAdminService
* @throws DbException
* @throws ModelNotFoundException
*/
public function getMenuListBySystem(string $app_type, array $addons, int $is_tree = 0)
public function getMenuListBySystem(string $app_type, array $addons, int $is_tree = 0, int $is_button = 1)
{
sort($addons);
$cache_name = 'menu' . md5(implode("_", $addons)) . $is_tree;
@ -521,7 +522,7 @@ class MenuService extends BaseAdminService
$v['view_path'] = $view_path;
}
}
return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', 1) : $menu_list;
return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', $is_button) : $menu_list;
}

View File

@ -55,9 +55,9 @@ class AuthService extends BaseApiService
$site_id = $request->apiSiteId();//todo 可以是依赖传值,也可以通过domain域名来获取site_id
$site_info = (new CoreSiteService())->getSiteCache($site_id);
if(empty($site_info)) throw new AuthException('SITE_NOT_EXIST');
if($site_info['status'] == SiteDict::CLOSE){
$rule = strtolower(trim($request->rule()->getRule()));
if($rule != 'site') throw new AuthException('SITE_CLOSE_NOT_ALLOW');
$rule = strtolower(trim($request->rule()->getRule()));
if($rule != 'site'){
if ($site_info['status'] == SiteDict::CLOSE || $site_info['expire_time'] < time()) throw new AuthException('SITE_CLOSE_NOT_ALLOW');
}
$request->siteId($site_id);
return true;

View File

@ -0,0 +1,101 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\member;
use app\model\member\MemberAddress;
use core\base\BaseApiService;
/**
* 会员收货地址服务层
* Class AddressService
* @package app\service\admin\address
*/
class AddressService extends BaseApiService
{
public function __construct()
{
parent::__construct();
$this->model = new MemberAddress();
}
/**
* 获取会员收货地址列表
* @param array $where
* @return array
*/
public function getList(array $where = [])
{
$field = 'id,member_id,name,mobile,address,address_name,full_address,is_default,type';
$order = 'is_default desc, id desc';
$list = $this->model->where([ ['site_id', '=', $this->site_id],['member_id', '=', $this->member_id ] ])->withSearch(["type"], $where)->field($field)->order($order)->select()->toArray();
return $list;
}
/**
* 获取会员收货地址信息
* @param int $id
* @return array
*/
public function getInfo(int $id)
{
$field = 'id,member_id,name,mobile,province_id,city_id,district_id,address,address_name,full_address,lng,lat,is_default,type';
$info = $this->model->field($field)->where([ ['id', '=', $id], ['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id ] ])->findOrEmpty()->toArray();
return $info;
}
/**
* 添加会员收货地址
* @param array $data
* @return mixed
*/
public function add(array $data)
{
if ($data['is_default']) {
$this->model->where([ ['member_id', '=', $this->member_id ], ['type', '=', $data['type']] ])->update(['is_default' => 0]);
}
$data['member_id'] = $this->member_id;
$data['site_id'] = $this->site_id;
$res = $this->model->create($data);
return $res->id;
}
/**
* 会员收货地址编辑
* @param int $id
* @param array $data
* @return bool
*/
public function edit(int $id, array $data)
{
if ($data['is_default']) {
$this->model->where([ ['member_id', '=', $this->member_id ], ['type', '=', $data['type']] ])->update(['is_default' => 0]);
}
$this->model->where([ ['id', '=', $id], ['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id ] ])->update($data);
return true;
}
/**
* 删除会员收货地址
* @param int $id
* @return bool
*/
public function del(int $id)
{
$model = $this->model->where([ ['id', '=', $id], ['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id ] ])->find();
$res = $model->delete();
return $res;
}
}

View File

@ -0,0 +1,100 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\sys;
use app\model\sys\SysArea;
use app\service\admin\sys\ConfigService;
use core\base\BaseApiService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
/**
* 地区服务层
* Class AreaService
* @package app\service\admin\sys
*/
class AreaService extends BaseApiService
{
public static $cache_tag_name = 'area_cache';
public function __construct()
{
parent::__construct();
$this->model = new SysArea();
}
/**
* 获取地区信息
* @param int $pid //上级pid
* @return mixed
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function getListByPid(int $pid = 0)
{
$cache_name = self::$cache_tag_name.'_api_pid_'.$pid;
return cache_remember(
$cache_name,
function() use($pid) {
return $this->model->where([['pid', '=', $pid]])->field('id, name')->select()->toArray();
},
[self::$cache_tag_name]
);
}
/**
* 查询地区树列表
* @param int $level //层级1,2,3
* @return mixed
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function getAreaTree(int $level = 3)
{
$cache_name = self::$cache_tag_name.'_api_tree_'.$level;
return cache_remember(
$cache_name,
function() use($level) {
$list = $this->model->where([['level', '<=', $level]])->field('id, pid, name')->select()->toArray();
return list_to_tree($list);
},
[self::$cache_tag_name]
);
}
public function getAreaByAreaCode($id) {
$cache_name = self::$cache_tag_name.'_api_area_'. $id;
return cache_remember(
$cache_name,
function() use($id) {
$level = [1 => 'province', 2 => 'city', 3 => 'district'];
$tree = [];
$area = $this->model->where([ ['id', '=', $id] ])->field('id,level,pid,name')->findOrEmpty();
if (!$area->isEmpty()) {
$tree[ $level[ $area['level'] ] ] = $area->toArray();
while ($area['level'] > 1) {
$area = $this->model->where([ ['id', '=', $area['pid'] ] ])->field('id,level,pid,name')->findOrEmpty();
$tree[ $level[ $area['level'] ] ] = $area->toArray();
}
}
return $tree;
},
[self::$cache_tag_name]
);
}
}

View File

@ -241,7 +241,6 @@ class CoreAddonInstallService extends CoreAddonBaseService
}
Cache::set('install_task', null);
Cache::set($this->cache_key . '_install_check', null);
}
/**

View File

@ -0,0 +1,56 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\core\member;
use app\model\member\MemberAddress;
use app\model\member\MemberLabel;
use core\base\BaseCoreService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Cache;
/**
* 会员标签服务层
* Class CoreMemberAccountService
* @package app\service\core\member
*/
class CoreMemberAddressService extends BaseCoreService
{
public function __construct()
{
parent::__construct();
$this->model = new MemberAddress();
}
/**
* 获取会员默认地址
* @param int $member_id
* @return array
*/
public function getDefaultAddressByMemberId(int $member_id, $type = 'address'){
$field = 'id,member_id,name,mobile,province_id,city_id,district_id,address,full_address,lng,lat,is_default,type';
return $this->model->where([['member_id', '=', $member_id], ['type', '=', $type] ])->field($field)->order('is_default desc')->findOrEmpty()->toArray();
}
/**
* 获取收货地址
* @param int $id
* @return array
*/
public function getMemberAddressById(int $id, int $member_id){
$field = 'id,member_id,name,mobile,province_id,city_id,district_id,address,full_address,lng,lat,is_default,type';
return $this->model->where([['id', '=', $id], ['member_id', '=', $member_id]])->field($field)->findOrEmpty()->toArray();
}
}

View File

@ -62,12 +62,12 @@ class CoreMemberService extends BaseCoreService
* @param int $member_id
* @return array
*/
public function getInfoByMemberId(int $site_id, int $member_id){
public function getInfoByMemberId(int $site_id, int $member_id, string $field = '*'){
$where = array(
['site_id', '=', $site_id],
['member_id', '=', $member_id]
);
return $this->model->where($where)->findOrEmpty()->toArray();
return $this->model->where($where)->field($field)->findOrEmpty()->toArray();
}
/**

View File

@ -84,4 +84,15 @@ class CoreModuleService extends BaseNiucloudClient
{
return $this->httpGet('member_app_action/'.$action, $data);
}
/**
* 校验key是否被占用
* @param $key
* @return array|Response|object|ResponseInterface
* @throws GuzzleException
*/
public function checkKey($key)
{
return $this->httpGet('store/app_check/'.$key, ['product_key' => self::PRODUCT])['data'] ?? false;
}
}

View File

@ -139,12 +139,14 @@ class CorePayService extends BaseCoreService
*/
public function getInfoByTrade(int $site_id, string $trade_type, string $trade_id, string $channel)
{
$where = array(
['site_id', '=', $site_id],
['trade_type', '=', $trade_type],
['trade_id', '=', $trade_id],
);
$pay = $this->model->where($where)->append(['type_name', 'status_name'])->findOrEmpty()->toArray();
$pay = $this->findPayInfoByTrade($site_id, $trade_type, $trade_id);
if ($pay->isEmpty()) {
//创建新的支付单据
$pay = $this->createByTrade($site_id, $trade_type, $trade_id);
}
if(!is_array($pay)){
$pay = $pay->toArray();
}
if (!empty($pay)) {
//todo 校验场景控制支付方式
$pay['pay_type_list'] = array_values((new CorePayChannelService())->getAllowPayTypeByChannel($site_id, $channel, $pay['trade_type']));
@ -195,10 +197,10 @@ class CorePayService extends BaseCoreService
if (!in_array($type, array_column((new CorePayChannelService())->getAllowPayTypeByChannel($site_id, $channel, $trade_type), 'key'))) throw new PayException('PAYMENT_METHOD_NOT_SCENE');//场景不支持
$pay_result = $this->pay_event->init($site_id, $channel, $type)->pay($out_trade_no, $money, $body, $return_url, $quit_url, $buyer_id, $openid ?? '', $voucher);
//todo 特殊支付方式会直接返回支付状态,状态如果为已支付会直接支付
if (!empty($pay_result['status']) && $pay_result['status'] == PayDict::STATUS_ED) {
if (!empty($pay_result['status']) && $pay_result['status'] == PayDict::STATUS_FINISH) {
$pay->save([ 'channel' => $channel ]);
$this->paySuccess($site_id, [
'status' => PayDict::STATUS_ED,
'status' => PayDict::STATUS_FINISH,
'type' => $type,
'out_trade_no' => $out_trade_no
]);
@ -249,7 +251,7 @@ class CorePayService extends BaseCoreService
//创建新的支付单据
$pay = $this->createByTrade($site_id, $trade_type, $trade_id);
}
if ($pay['status'] == PayDict::STATUS_ED) throw new PayException('PAY_SUCCESS');
if ($pay['status'] == PayDict::STATUS_FINISH) throw new PayException('PAY_SUCCESS');
if ($pay['status'] == PayDict::STATUS_CALCLE) throw new PayException('PAY_IS_REMOVE');
if ($pay['status'] == PayDict::STATUS_ING) {
//尝试关闭原有的支付单据
@ -269,9 +271,19 @@ class CorePayService extends BaseCoreService
*/
public function createByTrade($site_id, $trade_type, $trade_id){
//创建新的支付单据
$data = event('PayCreate', ['site_id' => $site_id, 'trade_type' => $trade_type, 'trade_id' => $trade_id])[0] ?? [];
$out_trade_no = $this->create($site_id, $data['main_type'], $data['main_id'], $data['money'], $data['trade_type'], $data['trade_id'], $data['body']);
return $this->findPayInfoByOutTradeNo($site_id, $out_trade_no);
$data = array_values(array_filter(event('PayCreate', ['site_id' => $site_id,'trade_type' => $trade_type, 'trade_id' => $trade_id])))[0] ?? [];
if(empty($data)) throw new PayException('PAY_NOT_FOUND_TRADE');//找不到可支付的交易
if(isset($data['status']) && $data['money'] == 0){
$data['status'] = PayDict::STATUS_FINISH;
$data['status_name'] = PayDict::getStatus()[$data['status']] ?? '';
$data['type'] = PayDict::BALANCEPAY;
$data['type_name'] = PayDict::getPayType()[$data['type']]['name'] ?? '';
return $data;
}else{
$out_trade_no = $this->create($site_id, $data['main_type'], $data['main_id'], $data['money'], $data['trade_type'], $data['trade_id'], $data['body']);
return $this->findPayInfoByOutTradeNo($site_id, $out_trade_no);
}
}
/**
@ -311,23 +323,26 @@ class CorePayService extends BaseCoreService
{
$pay = $this->findPayInfoByOutTradeNo($site_id, $out_trade_no);
if ($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');
if (empty($pay->type)) throw new PayException('TREAT_PAYMENT_IS_OPEN');
if($pay['status'] == PayDict::STATUS_CALCLE) return true;
if (!in_array($pay['status'], [
PayDict::STATUS_WAIT,
PayDict::STATUS_ING
])) throw new PayException('TREAT_PAYMENT_IS_OPEN');
])) throw new PayException('TREAT_PAYMENT_IS_OPEN++');
if ($pay['status'] == PayDict::STATUS_ING) {
//尝试取消或关闭第三方支付
$close = $this->pay_event->init($site_id, $pay->channel, $pay->type)->close($out_trade_no);
if (!$close) {//有问题查询第三方订单详情
$order = $this->pay_event->init($site_id, $pay->channel, $pay->type)->getOrder($out_trade_no);
if (!empty($order)) {
if ($order['status'] == OnlinePayDict::SUCCESS) {//如果已支付,就将支付调整为已支付
$this->paySuccess($site_id, [
'out_trade_no' => $out_trade_no,
'type' => $pay->type
]);
return false;
if (!empty($pay->type)) {
//尝试取消或关闭第三方支付
$close = $this->pay_event->init($site_id, $pay->channel, $pay->type)->close($out_trade_no);
if (!$close) {//有问题查询第三方订单详情
$order = $this->pay_event->init($site_id, $pay->channel, $pay->type)->getOrder($out_trade_no);
if (!empty($order)) {
if ($order['status'] == OnlinePayDict::SUCCESS) {//如果已支付,就将支付调整为已支付
$this->paySuccess($site_id, [
'out_trade_no' => $out_trade_no,
'type' => $pay->type
]);
return false;
}
}
}
}
@ -350,12 +365,12 @@ class CorePayService extends BaseCoreService
{
$pay = $this->findPayInfoByTrade($site_id, $trade_type, $trade_id);
if ($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');
if ($pay['status'] == PayDict::STATUS_ED) throw new PayException('DOCUMENT_IS_PAID');//当前单据已支付
if ($pay['status'] == PayDict::STATUS_FINISH) throw new PayException('DOCUMENT_IS_PAID');//当前单据已支付
if (!in_array($pay['status'], [
PayDict::STATUS_WAIT,
PayDict::STATUS_ING
])) throw new PayException('IS_PAY_REMOVE_NOT_RESETTING');//只有待支付可以关闭支付
if (!$this->close($site_id, $pay)) {
if (!$this->close($site_id, $pay['out_trade_no'])) {
throw new PayException('DOCUMENT_IS_PAY_REMOVE');
}
return true;
@ -374,7 +389,7 @@ class CorePayService extends BaseCoreService
$pay = $this->findPayInfoByOutTradeNo($site_id, $out_trade_no);
if ($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');
if ($pay['status'] == PayDict::STATUS_ED) throw new PayException('DOCUMENT_IS_PAID');
if ($pay['status'] == PayDict::STATUS_FINISH) throw new PayException('DOCUMENT_IS_PAID');
if ($pay['status'] == PayDict::STATUS_CALCLE) throw new PayException('PAY_IS_REMOVE');
$status = $params['status'];
switch ($status) {
@ -442,7 +457,7 @@ class CorePayService extends BaseCoreService
$out_trade_no = $data['out_trade_no'];
$pay = $this->findPayInfoByOutTradeNo($site_id, $out_trade_no);
if ($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');
if ($pay['status'] == PayDict::STATUS_ED) throw new PayException('PAY_SUCCESS');//单据已支付
if ($pay['status'] == PayDict::STATUS_FINISH) throw new PayException('PAY_SUCCESS');//单据已支付
if ($pay['status'] == PayDict::STATUS_CALCLE) throw new PayException('PAY_IS_REMOVE');//单据已取消
//查询第三方支付单据
$pay_info = $this->pay_event->init($site_id, $pay->channel, $pay->type)->getOrder($out_trade_no);
@ -489,7 +504,7 @@ class CorePayService extends BaseCoreService
$trade_id = $pay->trade_id;
$data = array(
'pay_time' => time(),
'status' => PayDict::STATUS_ED,
'status' => PayDict::STATUS_FINISH,
'type' => $type,
'trade_no' => $params['trade_no'] ?? '',
'voucher' => $params['voucher'] ?? '',

View File

@ -11,6 +11,7 @@
namespace app\service\core\pay;
use app\dict\pay\PayDict;
use app\dict\pay\RefundDict;
use app\model\pay\Refund;
use core\base\BaseCoreService;
@ -41,7 +42,7 @@ class CoreRefundService extends BaseCoreService
* @param string $reason
* @return string|null
*/
public function create(int $site_id, string $out_trade_no, float $money, string $reason = ''){
public function create(int $site_id, string $out_trade_no, float $money, string $reason = '', $trade_type = '', $trade_id = ''){
//通过交易流水号获取支付单据
$pay = (new CorePayService())->findPayInfoByOutTradeNo($site_id, $out_trade_no);
if($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');//单据不存在
@ -56,7 +57,9 @@ class CoreRefundService extends BaseCoreService
'out_trade_no' => $out_trade_no,
'refund_no' => $refund_no,
'status' => RefundDict::WAIT,
'reason' => $reason
'reason' => $reason,
'trade_type' => $trade_type,
'trade_id' => $trade_id
);
$this->model->create($data);
return $refund_no;
@ -69,15 +72,23 @@ class CoreRefundService extends BaseCoreService
* @param string $voucher
* @return true
*/
public function refund(int $site_id, string $refund_no, $voucher = ''){
public function refund(int $site_id, string $refund_no, $voucher = '', $refund_type = RefundDict::BACK, $main_type = '', $main_id = 0){
$refund = $this->findByRefundNo($site_id, $refund_no);
if($refund->isEmpty()) throw new PayException('REFUND_NOT_EXIST');
$out_trade_no = $refund->out_trade_no;
$money = $refund->money;
try{
//判断成功的话,可以直接调用退款成功
$pay_result = $this->pay_event->init($site_id, $refund->channel, $refund->type)->refund($out_trade_no, $money, $money, $refund_no, $voucher);
$this->refundNotify($site_id, $out_trade_no, $refund->type, $pay_result);
//存入退款方式
$refund->save(['refund_type' => $refund_type]);
if($refund_type == RefundDict::BACK){
//判断成功的话,可以直接调用退款成功
$pay_result = $this->pay_event->init($site_id, $refund->channel, $refund->type)->refund($out_trade_no, $money, $money, $refund_no, $voucher);
$this->refundNotify($site_id, $out_trade_no, $refund->type, $pay_result);
}else if($refund_type == RefundDict::OFFLINE){
$pay_result = $this->pay_event->init($site_id, $refund->channel, PayDict::OFFLINEPAY)->refund($out_trade_no, $money, $money, $refund_no, $voucher);
$this->refundNotify($site_id, $out_trade_no, $refund->type, $pay_result, $main_type, $main_id);
}
}catch ( Throwable $e) {
throw new PayException($e->getMessage());
}
@ -99,7 +110,7 @@ class CoreRefundService extends BaseCoreService
public function refundNotify(int $site_id, $out_trade_no, string $type, array $params = []){
public function refundNotify(int $site_id, $out_trade_no, string $type, array $params = [], $main_type = '', $main_id = 0){
$refund_no = $params['refund_no'];
$refund = $this->findByRefundNo($site_id, $refund_no);
@ -116,6 +127,10 @@ class CoreRefundService extends BaseCoreService
$this->refundSuccess($site_id, [
'out_trade_no' => $out_trade_no,
'refund_no' => $refund_no,
'trade_type' => $refund['trade_type'],
'trade_id' => $refund['trade_id'],
'main_type' => $main_type,
'main_id' => $main_id
]);
break;
case RefundDict::DEALING://退款处理中
@ -200,7 +215,7 @@ class CoreRefundService extends BaseCoreService
'status' => RefundDict::SUCCESS
]);
$pay = (new CorePayService())->findPayInfoByOutTradeNo($site_id, $out_trade_no);
$result = event('RefundSuccess', ['refund_no' => $refund_no, 'trade_type' => $pay->trade_type, 'site_id' => $site_id]);
$result = event('RefundSuccess', ['refund_no' => $refund_no, 'trade_type' => $pay->trade_type, 'site_id' => $site_id, 'trade_id' => $data['trade_id']]);
if(!check_event_result($result)){
return false;
}

View File

@ -68,7 +68,7 @@ class CoreBalanceService extends BaseCoreService
break;
}
return [
'status' => PayDict::STATUS_ED,
'status' => PayDict::STATUS_FINISH,
'out_trade_no' => $out_trade_no,
];
//业务主体id

View File

@ -105,7 +105,7 @@ class CoreOfflineService extends BaseCoreService
if ($pay->type != PayDict::OFFLINEPAY) throw new CommonException('ONLY_OFFLINEPAY_CAN_AUDIT');
return (new CorePayService())->paySuccess($site_id, [
'status' => PayDict::STATUS_ED,
'status' => PayDict::STATUS_FINISH,
'type' => $pay->type,
'out_trade_no' => $out_trade_no,
'voucher' => $pay->voucher

View File

@ -52,7 +52,7 @@ class CoreScheduleService extends BaseCoreService
$list = $this->model->withSearch(['key','status'],$where)->field($field)->order('id desc')->append(['status_name'])->select()->toArray();
$template_list = array_column($this->getTemplateList(), null, 'key');
foreach($list as &$item){
$item = array_merge($template_list[$item['key']], $item);
$item = array_merge($template_list[$item['key']] ?? [], $item);
}
return $list;
}

View File

@ -0,0 +1,47 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\validate\member;
use core\base\BaseValidate;
/**
* 会员收货地址验证器
* Class Address
* @package addon\app\validate\member
*/
class Address extends BaseValidate
{
protected $rule = [
'name' => 'require',
'mobile' => 'require',
'province_id' => 'require',
'city_id' => 'require',
'district_id' => 'require',
'address' => 'require',
'full_address' => 'require',
'type' => 'require',
];
protected $message = [
'name.require' => ['common_validate.require', ['name']],
'mobile.require' => ['common_validate.require', ['mobile']],
'address.require' => ['common_validate.require', ['address']],
'full_address.require' => ['common_validate.require', ['full_address']],
'type.require' => ['common_validate.require', ['type']],
];
protected $scene = [
"add" => ['name', 'mobile', 'address', 'full_address', 'lng', 'lat', 'type'],
"edit" => ['name', 'mobile', 'address', 'full_address', 'lng', 'lat', 'type']
];
}

View File

@ -29,7 +29,7 @@
"topthink/think-image": "v1.0.7",
"topthink/think-queue": "v3.0.7",
"firebase/php-jwt": "v5.5.1",
"overtrue/wechat": "v5.30.0",
"w7corp/easywechat": "v5.30.0",
"spatie/macroable": "v1.0.1",
"dh2y/think-qrcode": "v2.0",
"dragonmantank/cron-expression": "v3.3.1",
@ -52,7 +52,8 @@
"kosinix/grafika": "dev-master",
"yunwuxin/think-cron": "v3.0.5",
"nesbot/carbon": "2.66.0",
"ext-zip": "*"
"ext-zip": "*",
"mjaschen/phpgeo": "4.2.0"
},
"require-dev": {
"symfony/var-dumper": "v4.4.47",
@ -64,8 +65,7 @@
"app\\": "app",
"core\\": "core"
},
"psr-0": {
}
"psr-0": {}
},
"config": {
"preferred-install": "dist",

278
niucloud/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d2848be223c791847af703c27d6c523b",
"content-hash": "200584e34d312fccad002d61ce5e76e7",
"packages": [
{
"name": "adbario/php-dot-notation",
@ -1617,6 +1617,85 @@
},
"time": "2022-12-02T22:17:43+00:00"
},
{
"name": "mjaschen/phpgeo",
"version": "4.2.0",
"source": {
"type": "git",
"url": "https://github.com/mjaschen/phpgeo.git",
"reference": "b2e593cf1e9aceea36510158ddb80c7395a80d5a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mjaschen/phpgeo/zipball/b2e593cf1e9aceea36510158ddb80c7395a80d5a",
"reference": "b2e593cf1e9aceea36510158ddb80c7395a80d5a",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3.6",
"vimeo/psalm": "^4.13"
},
"type": "library",
"autoload": {
"psr-4": {
"Location\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marcus Jaschen",
"email": "mjaschen@gmail.com",
"homepage": "https://www.marcusjaschen.de/"
}
],
"description": "Simple Yet Powerful Geo Library",
"homepage": "https://phpgeo.marcusjaschen.de/",
"keywords": [
"Polygon",
"area",
"bearing",
"bounds",
"calculation",
"coordinate",
"distance",
"earth",
"ellipsoid",
"geo",
"geofence",
"gis",
"gps",
"haversine",
"length",
"perpendicular",
"point",
"polyline",
"projection",
"simplify",
"track",
"vincenty"
],
"support": {
"docs": "https://phpgeo.marcusjaschen.de/Installation.html",
"email": "mjaschen@gmail.com",
"issues": "https://github.com/mjaschen/phpgeo/issues",
"source": "https://github.com/mjaschen/phpgeo/tree/4.2.0"
},
"time": "2022-07-25T08:36:36+00:00"
},
{
"name": "monolog/monolog",
"version": "2.9.1",
@ -2045,105 +2124,6 @@
],
"time": "2023-07-17T08:56:49+00:00"
},
{
"name": "overtrue/wechat",
"version": "5.30.0",
"source": {
"type": "git",
"url": "https://github.com/w7corp/easywechat.git",
"reference": "245d1e821bc5a4609625c3244b111f570692cfc2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/w7corp/easywechat/zipball/245d1e821bc5a4609625c3244b111f570692cfc2",
"reference": "245d1e821bc5a4609625c3244b111f570692cfc2",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"easywechat-composer/easywechat-composer": "^1.1",
"ext-fileinfo": "*",
"ext-libxml": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.2 || ^7.0",
"monolog/monolog": "^1.22 || ^2.0",
"overtrue/socialite": "^3.2 || ^4.0",
"php": ">=7.4",
"pimple/pimple": "^3.0",
"psr/simple-cache": "^1.0||^2.0||^3.0",
"symfony/cache": "^3.3 || ^4.3 || ^5.0 || ^6.0",
"symfony/event-dispatcher": "^4.3 || ^5.0 || ^6.0",
"symfony/http-foundation": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0",
"symfony/psr-http-message-bridge": "^0.3 || ^1.0 || ^2.0"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.7",
"dms/phpunit-arraysubset-asserts": "^0.2.0",
"friendsofphp/php-cs-fixer": "^3.5.0",
"mikey179/vfsstream": "^1.6",
"mockery/mockery": "^1.2.3",
"phpstan/phpstan": "^0.12.0",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer test",
"composer fix-style"
],
"pre-push": [
"composer test",
"composer fix-style"
]
}
},
"autoload": {
"files": [
"src/Kernel/Support/Helpers.php",
"src/Kernel/Helpers.php"
],
"psr-4": {
"EasyWeChat\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "anzhengchao@gmail.com"
}
],
"description": "微信SDK",
"keywords": [
"easywechat",
"sdk",
"wechat",
"weixin",
"weixin-sdk"
],
"support": {
"issues": "https://github.com/w7corp/easywechat/issues",
"source": "https://github.com/w7corp/easywechat/tree/5.30.0"
},
"funding": [
{
"url": "https://github.com/overtrue",
"type": "github"
}
],
"abandoned": "w7corp/easywechat",
"time": "2022-09-05T08:22:34+00:00"
},
{
"name": "php-di/invoker",
"version": "2.3.3",
@ -5095,6 +5075,104 @@
},
"time": "2019-11-06T11:40:13+00:00"
},
{
"name": "w7corp/easywechat",
"version": "5.30.0",
"source": {
"type": "git",
"url": "https://github.com/w7corp/easywechat.git",
"reference": "245d1e821bc5a4609625c3244b111f570692cfc2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/w7corp/easywechat/zipball/245d1e821bc5a4609625c3244b111f570692cfc2",
"reference": "245d1e821bc5a4609625c3244b111f570692cfc2",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"easywechat-composer/easywechat-composer": "^1.1",
"ext-fileinfo": "*",
"ext-libxml": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.2 || ^7.0",
"monolog/monolog": "^1.22 || ^2.0",
"overtrue/socialite": "^3.2 || ^4.0",
"php": ">=7.4",
"pimple/pimple": "^3.0",
"psr/simple-cache": "^1.0||^2.0||^3.0",
"symfony/cache": "^3.3 || ^4.3 || ^5.0 || ^6.0",
"symfony/event-dispatcher": "^4.3 || ^5.0 || ^6.0",
"symfony/http-foundation": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0",
"symfony/psr-http-message-bridge": "^0.3 || ^1.0 || ^2.0"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.7",
"dms/phpunit-arraysubset-asserts": "^0.2.0",
"friendsofphp/php-cs-fixer": "^3.5.0",
"mikey179/vfsstream": "^1.6",
"mockery/mockery": "^1.2.3",
"phpstan/phpstan": "^0.12.0",
"phpunit/phpunit": "^9.3"
},
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer test",
"composer fix-style"
],
"pre-push": [
"composer test",
"composer fix-style"
]
}
},
"autoload": {
"files": [
"src/Kernel/Support/Helpers.php",
"src/Kernel/Helpers.php"
],
"psr-4": {
"EasyWeChat\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "anzhengchao@gmail.com"
}
],
"description": "微信SDK",
"keywords": [
"easywechat",
"sdk",
"wechat",
"weixin",
"weixin-sdk"
],
"support": {
"issues": "https://github.com/w7corp/easywechat/issues",
"source": "https://github.com/w7corp/easywechat/tree/5.30.0"
},
"funding": [
{
"url": "https://github.com/overtrue",
"type": "github"
}
],
"time": "2022-09-05T08:22:34+00:00"
},
{
"name": "webmozart/assert",
"version": "1.11.0",

View File

@ -1,6 +1,6 @@
<?php
return [
'version' => '0.0.4',
'code' => '202311300001'
'version' => '0.0.5',
'code' => '202312150001'
];

View File

@ -0,0 +1,46 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
declare (strict_types=1);
namespace core\base;
use think\Validate;
/**
* 验证器器基类
* Class BaseValidate
* @package core\base
*/
class BaseValidate extends Validate
{
public function __construct()
{
parent::__construct();
$this->parseMsg();
}
public function parseMsg(){
if(!empty($this->message))
{
foreach ($this->message as $key => $value)
{
if(is_array($value))
{
$this->message[$key] = get_lang($value[0], $value[1]);
}
}
}
}
}

View File

@ -11,6 +11,8 @@
namespace core\dict;
use app\service\admin\addon\AddonService;
class Notice extends BaseDict
{
/**
@ -25,7 +27,7 @@ class Notice extends BaseDict
if (is_file($system_path)) {
$template_files[] = $system_path;
}
$addons = $this->getLocalAddons();
$addons = (new AddonService())->getAddonKeysBySiteId(request()->siteId());
foreach ($addons as $v) {
$template_path = $this->getAddonDictPath($v) . "notice" . DIRECTORY_SEPARATOR . $data[ 'type' ] . ".php";
if (is_file($template_path)) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

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