第一次更新,完成了初版调整
This commit is contained in:
Generated
+8
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/../../../../:\tpProject\oil\.idea/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/oil.iml" filepath="$PROJECT_DIR$/.idea/oil.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+67
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/process" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/polyfill-php80" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/var-dumper" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/nesbot/carbon" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/translation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/deprecation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/translation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/carbonphp/carbon-doctrine-types" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/aliyuncs/oss-sdk-php" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/maennchen/zipstream-php" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/php-webdriver/webdriver" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/predis/predis" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-queue" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/ezyang/htmlpurifier" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/kosinix/grafika" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/framework" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/predis/src" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-helper" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/overtrue/easy-sms" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-multi-app" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-worker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-orm" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/predis/docker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-filesystem" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/topthink/think-trace" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/lvht/geohash" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/guzzlehttp/guzzle-services" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/qiniu/php-sdk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/guzzlehttp/uri-template" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/guzzlehttp/guzzle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/guzzlehttp/promises" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/guzzlehttp/command" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/guzzlehttp/psr7" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/league/mime-type-detection" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/league/flysystem" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/markbaker/matrix" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/markbaker/complex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/composer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/qcloud/cos-sdk-v5" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/dashingunique/think-generator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/simple-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/http-message" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/log" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/container" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/http-client" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/clock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/setasign/fpdf" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/psr/http-factory" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/setasign/fpdi" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/yiovo/tp6-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/yiovo/tp6-captcha" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/ralouphie/getallheaders" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/myclabs/php-enum" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/phpoffice/phpspreadsheet" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/workerman/gateway-worker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/symfony/polyfill-mbstring" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/workerman/workerman" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/server-tp6/vendor/picqer/php-barcode-generator" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+68
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PhpIncludePathManager">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/process" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/polyfill-php80" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/var-dumper" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/nesbot/carbon" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/translation" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/deprecation-contracts" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/translation-contracts" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/carbonphp/carbon-doctrine-types" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/aliyuncs/oss-sdk-php" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/maennchen/zipstream-php" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/php-webdriver/webdriver" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/predis/predis" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-queue" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/ezyang/htmlpurifier" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/kosinix/grafika" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/framework" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/predis/src" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-helper" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/overtrue/easy-sms" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-multi-app" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-worker" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-orm" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/predis/docker" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-filesystem" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/topthink/think-trace" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/lvht/geohash" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/guzzlehttp/guzzle-services" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/qiniu/php-sdk" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/guzzlehttp/uri-template" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/guzzlehttp/guzzle" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/guzzlehttp/promises" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/guzzlehttp/command" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/guzzlehttp/psr7" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/league/mime-type-detection" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/league/flysystem" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/markbaker/matrix" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/markbaker/complex" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/composer" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/qcloud/cos-sdk-v5" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/dashingunique/think-generator" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/simple-cache" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/http-message" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/log" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/container" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/http-client" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/clock" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/setasign/fpdf" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/psr/http-factory" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/setasign/fpdi" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/yiovo/tp6-cache" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/yiovo/tp6-captcha" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/ralouphie/getallheaders" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/myclabs/php-enum" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/phpoffice/phpspreadsheet" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/workerman/gateway-worker" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/symfony/polyfill-mbstring" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/workerman/workerman" />
|
||||
<path value="$PROJECT_DIR$/server-tp6/vendor/picqer/php-barcode-generator" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.0">
|
||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Vendored
+2
-2
@@ -6,6 +6,6 @@ window.publicConfig = {
|
||||
// BASE_API: '../index.php?s=/store'
|
||||
// BASE_API: 'http://139.129.21.253/index.php?s=/store'
|
||||
// BASE_DOMAIN: 'http://139.129.21.253/'
|
||||
BASE_API: 'https://www.hmzkw.com/index.php?s=/store',
|
||||
BASE_DOMAIN: 'https://www.hmzkw.com/'
|
||||
BASE_API: 'http://47.104.73.7/index.php?s=/store',
|
||||
BASE_DOMAIN: 'http:/47.104.73.7/'
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import { axios } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* api接口列表
|
||||
*/
|
||||
const api = {
|
||||
list: '/account/index',
|
||||
detail: '/account/detail',
|
||||
add: '/account/add',
|
||||
edit: '/account/edit',
|
||||
delete: '/account/delete',
|
||||
all: '/account/all'
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表记录
|
||||
*/
|
||||
export function list (params) {
|
||||
return axios({
|
||||
url: api.list,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 全部记录
|
||||
*/
|
||||
export function all (params) {
|
||||
return axios({
|
||||
url: api.all,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户详情(详细信息)
|
||||
*/
|
||||
export function detail (params) {
|
||||
return axios({
|
||||
url: api.detail,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增记录
|
||||
* @param {*} data
|
||||
*/
|
||||
export function add (data) {
|
||||
return axios({
|
||||
url: api.add,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑记录
|
||||
* @param {*} data
|
||||
*/
|
||||
export function edit (data) {
|
||||
return axios({
|
||||
url: api.edit,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
* @param {*} data
|
||||
*/
|
||||
export function deleted (data) {
|
||||
return axios({
|
||||
url: api.delete,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { axios } from '@/utils/request'
|
||||
|
||||
// api接口列表
|
||||
const api = {
|
||||
log: '/company.balance/log'
|
||||
}
|
||||
|
||||
// 列表记录
|
||||
export function log (params) {
|
||||
return axios({
|
||||
url: api.log,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
import { axios } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* api接口列表
|
||||
*/
|
||||
const api = {
|
||||
list: '/company/index',
|
||||
detail: '/company/detail',
|
||||
add: '/company/add',
|
||||
edit: '/company/edit',
|
||||
delete: '/company/delete',
|
||||
all: '/company/all',
|
||||
recharge: '/company/recharge',
|
||||
account: '/company/addAccount',
|
||||
changeState: '/company/changeState',
|
||||
stock: '/company/stock'
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表记录
|
||||
*/
|
||||
export function list (params) {
|
||||
return axios({
|
||||
url: api.list,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 全部记录
|
||||
*/
|
||||
export function all (params) {
|
||||
return axios({
|
||||
url: api.all,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户详情(详细信息)
|
||||
*/
|
||||
export function detail (params) {
|
||||
return axios({
|
||||
url: api.detail,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增记录
|
||||
* @param {*} data
|
||||
*/
|
||||
export function add (data) {
|
||||
return axios({
|
||||
url: api.add,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑记录
|
||||
* @param {*} data
|
||||
*/
|
||||
export function edit (data) {
|
||||
return axios({
|
||||
url: api.edit,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户充值
|
||||
* @param {*} data
|
||||
*/
|
||||
export function recharge (data) {
|
||||
return axios({
|
||||
url: api.recharge,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建账户
|
||||
* @param {*} data
|
||||
*/
|
||||
export function account (data) {
|
||||
return axios({
|
||||
url: api.account,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
* @param {*} data
|
||||
*/
|
||||
export function deleted (data) {
|
||||
return axios({
|
||||
url: api.delete,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
* @param {*} data
|
||||
*/
|
||||
export function changeState (data) {
|
||||
return axios({
|
||||
url: api.changeState,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品库存
|
||||
* @param {*} data
|
||||
*/
|
||||
export function stock (data) {
|
||||
return axios({
|
||||
url: api.stock,
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { axios } from '@/utils/request'
|
||||
|
||||
// api接口列表
|
||||
const api = {
|
||||
order: '/company.recharge/order'
|
||||
}
|
||||
|
||||
// 列表记录
|
||||
export function order (params) {
|
||||
return axios({
|
||||
url: api.order,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export function list (params) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动分油
|
||||
* 重新发放(打回未提交态并重投队列,由企油通 7.7 下发)
|
||||
* @param {*} data
|
||||
*/
|
||||
export function share (data) {
|
||||
@@ -31,7 +31,7 @@ export function share (data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付码
|
||||
* 获取司机免登加油地址(企油通 7.15)
|
||||
* @param {*} data
|
||||
*/
|
||||
export function qrCode (data) {
|
||||
@@ -43,7 +43,7 @@ export function qrCode (data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 分油回调
|
||||
* 重推「发放结果」给下单平台
|
||||
* @param {*} data
|
||||
*/
|
||||
export function oilCallback (data) {
|
||||
@@ -55,7 +55,7 @@ export function oilCallback (data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用回调
|
||||
* 重推「加油核销结果」给下单平台
|
||||
* @param {*} data
|
||||
*/
|
||||
export function useCallback (data) {
|
||||
|
||||
@@ -9,8 +9,7 @@ const api = {
|
||||
recharge: '/user/recharge',
|
||||
grade: '/user/grade',
|
||||
delete: '/user/delete',
|
||||
merchant: '/user/merchant',
|
||||
oil: '/user/oil'
|
||||
merchant: '/user/merchant'
|
||||
}
|
||||
|
||||
// 列表记录
|
||||
@@ -71,14 +70,6 @@ export function recharge (data) {
|
||||
* 用户分油
|
||||
* @param {*} data
|
||||
*/
|
||||
export function oil (data) {
|
||||
return axios({
|
||||
url: api.oil,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改会员等级
|
||||
* @param {*} data
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import Enum from '../enum'
|
||||
|
||||
/**
|
||||
* 枚举类:店铺状态
|
||||
* PayTypeEnum
|
||||
*/
|
||||
export default new Enum([
|
||||
{ key: 'START', name: '启用', value: 10 },
|
||||
{ key: 'STOP', name: '停用', value: 20 }
|
||||
])
|
||||
@@ -1,12 +0,0 @@
|
||||
import Enum from '../../../enum'
|
||||
|
||||
/**
|
||||
* 枚举类:余额变动场景
|
||||
* PayStatusEnum
|
||||
*/
|
||||
export default new Enum([
|
||||
{ key: 'RECHARGE', name: '用户充值', value: 10 },
|
||||
{ key: 'CONSUME', name: '用户消费', value: 20 },
|
||||
{ key: 'ADMIN', name: '管理员操作', value: 30 },
|
||||
{ key: 'REFUND', name: '订单退款', value: 40 }
|
||||
])
|
||||
@@ -1,5 +0,0 @@
|
||||
import CompanyStatusEnum from './CompanyStatus'
|
||||
|
||||
export {
|
||||
CompanyStatusEnum
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import _ from 'lodash'
|
||||
import * as CompanyApi from '@/api/company'
|
||||
|
||||
/**
|
||||
* 公司 model类
|
||||
* CompanyModel
|
||||
*/
|
||||
export default {
|
||||
|
||||
// 当前公司ID
|
||||
companyId: null,
|
||||
|
||||
// 表单数据
|
||||
formData: {
|
||||
// 当前公司记录
|
||||
company: {}
|
||||
},
|
||||
|
||||
// 获取form所需的数据
|
||||
getFromData (companyId = null) {
|
||||
// 记录公司ID (编辑时)
|
||||
this.companyId = companyId
|
||||
return new Promise((resolve, reject) => {
|
||||
Promise.all([
|
||||
// 获取公司详情信息(编辑时)
|
||||
this.getCompanyDetail(companyId)
|
||||
]).then(() => {
|
||||
// 设置默认数据
|
||||
this.setDefaultData()
|
||||
resolve({ formData: this.formData })
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 获取公司详情
|
||||
getCompanyDetail (companyId = null) {
|
||||
if (!companyId) return false
|
||||
return new Promise((resolve, reject) => {
|
||||
CompanyApi.detail({ companyId })
|
||||
.then(result => {
|
||||
this.formData.company = result.data.companyInfo
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 获取表单默认值(用于form.setFieldsValue的数据)
|
||||
getFieldsValue () {
|
||||
// 公司详情信息
|
||||
const companyInfo = this.formData.company
|
||||
|
||||
// 公司基本数据
|
||||
const companyFormData = _.pick(companyInfo, [
|
||||
'name', 'address', 'tin', 'contact_name', 'contact_tel',
|
||||
'idcard', 'url', 'orgNo', 'appKey', 'privateKey', 'publicKey', 'platformPublicKey'
|
||||
])
|
||||
return {
|
||||
...companyFormData
|
||||
}
|
||||
},
|
||||
|
||||
// 设置默认的数据(无法用于form.setFieldsValue的数据)
|
||||
setDefaultData () {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import _ from 'lodash'
|
||||
import * as PartnersApi from '@/api/partners'
|
||||
import * as GoodsApi from '@/api/goods'
|
||||
|
||||
/**
|
||||
* 合作商 model类
|
||||
@@ -14,8 +13,7 @@ export default {
|
||||
// 表单数据
|
||||
formData: {
|
||||
// 当前合作商记录
|
||||
partners: {},
|
||||
goods: []
|
||||
partners: {}
|
||||
},
|
||||
|
||||
// 获取form所需的数据
|
||||
@@ -25,9 +23,7 @@ export default {
|
||||
return new Promise((resolve, reject) => {
|
||||
Promise.all([
|
||||
// 获取合作商详情信息(编辑时)
|
||||
this.getPartnersDetail(partnersId),
|
||||
// 获取所有商品
|
||||
this.getGoodsList()
|
||||
this.getPartnersDetail(partnersId)
|
||||
]).then(() => {
|
||||
// 设置默认数据
|
||||
this.setDefaultData()
|
||||
@@ -65,17 +61,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 获取所有商品
|
||||
getGoodsList () {
|
||||
return new Promise((resolve, reject) => {
|
||||
GoodsApi.oilAll({ oilCardType: 'zsy_ticket' })
|
||||
.then(result => {
|
||||
this.formData.goods = result.data.list
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 设置默认的数据(无法用于form.setFieldsValue的数据)
|
||||
setDefaultData () {
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import _ from 'lodash'
|
||||
import * as UserApi from '@/api/user'
|
||||
import * as CompanyApi from '@/api/company'
|
||||
|
||||
/**
|
||||
* 商户 model类
|
||||
@@ -16,7 +15,6 @@ export default {
|
||||
// 当前商户记录
|
||||
user: {},
|
||||
// 公司列表
|
||||
companyList: [],
|
||||
// 商户列表
|
||||
merchantList: []
|
||||
},
|
||||
@@ -30,9 +28,7 @@ export default {
|
||||
// 获取商户详情信息(编辑时)
|
||||
this.getUserDetail(userId),
|
||||
// 获取商户列表
|
||||
this.getMerchantList(),
|
||||
// 获取分油公司
|
||||
this.getCompanyList()
|
||||
this.getMerchantList()
|
||||
]).then(() => {
|
||||
// 设置默认数据
|
||||
this.setDefaultData()
|
||||
@@ -77,17 +73,6 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取公司列表
|
||||
getCompanyList () {
|
||||
return new Promise((resolve, reject) => {
|
||||
CompanyApi.all()
|
||||
.then(result => {
|
||||
this.formData.companyList = result.data.list
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 设置默认的数据(无法用于form.setFieldsValue的数据)
|
||||
setDefaultData () {
|
||||
|
||||
|
||||
@@ -58,62 +58,6 @@ export const asyncRouterMap = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 分油公司
|
||||
{
|
||||
path: '/company',
|
||||
name: 'company',
|
||||
component: RouteView,
|
||||
redirect: '/company/index',
|
||||
meta: { title: '分油公司', icon: Icons.shop, permission: ['/company'] },
|
||||
children: [
|
||||
{
|
||||
path: '/company/index',
|
||||
component: () => import(/* webpackChunkName: "company" */ '@/views/company/Index'),
|
||||
meta: { title: '公司列表', keepAlive: false, permission: ['/company/index'] },
|
||||
// 访问其他页面时激活该菜单(router-link-active)
|
||||
activePath: ['/company/create', '/company/update']
|
||||
},
|
||||
{
|
||||
path: '/company/create',
|
||||
component: () => import(/* webpackChunkName: "company" */ '@/views/company/Create'),
|
||||
meta: { title: '创建公司', keepAlive: false, permission: ['/company/create'] },
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/company/update',
|
||||
component: () => import(/* webpackChunkName: "company" */ '@/views/company/Update'),
|
||||
meta: { title: '编辑公司', keepAlive: false, permission: ['/company/update'] },
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/company/balance',
|
||||
component: RouteView,
|
||||
redirect: '/company/balance/index',
|
||||
meta: { title: '余额记录', keepAlive: false, permission: ['/company/balance'] },
|
||||
children: [
|
||||
{
|
||||
path: '/company/balance/index',
|
||||
component: () => import(/* webpackChunkName: "content" */ '@/views/company/balance/Index'),
|
||||
meta: { title: '余额明细', keepAlive: false, permission: ['/company/balance/index'] }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/account',
|
||||
component: RouteView,
|
||||
redirect: '/account/index',
|
||||
meta: { title: '分油用户', keepAlive: false, permission: ['/account'] },
|
||||
children: [
|
||||
{
|
||||
path: '/account/index',
|
||||
component: () => import(/* webpackChunkName: "content" */ '@/views/account/Index'),
|
||||
meta: { title: '用户列表', keepAlive: false, permission: ['/account/index'] }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// 实体兑换卡
|
||||
{
|
||||
path: '/card',
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<div class="card-title">{{ $route.meta.title }}</div>
|
||||
<div class="table-operator">
|
||||
<!-- 搜索板块 -->
|
||||
<a-row class="row-item-search">
|
||||
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
|
||||
<a-form-item label="用户名称,电话,身份证号">
|
||||
<a-input v-decorator="['search']" placeholder="请输入用户名称,电话,身份证号" />
|
||||
</a-form-item>
|
||||
<a-form-item label="最后使用时间">
|
||||
<a-range-picker format="YYYY-MM-DD" v-decorator="['last_called_at']" />
|
||||
</a-form-item>
|
||||
<a-form-item class="search-btn">
|
||||
<a-button type="primary" icon="search" html-type="submit">搜索</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-row>
|
||||
</div>
|
||||
<s-table
|
||||
ref="table"
|
||||
rowKey="account_id"
|
||||
:loading="isLoading"
|
||||
:columns="columns"
|
||||
:data="loadData"
|
||||
:pageSize="15"
|
||||
>
|
||||
<!-- 公司 -->
|
||||
<span slot="company" slot-scope="text, item">
|
||||
<p class="twoline-hide" style="width: 100px;">{{ item.company.name }}</p>
|
||||
</span>
|
||||
<!-- 最后使用时间 -->
|
||||
<span slot="last_called_at" slot-scope="text, item">
|
||||
<p class="twoline-hide" style="width: 150px;">{{ item.last_called_at | dateFormat }}</p>
|
||||
</span>
|
||||
</s-table>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as Api from '@/api/account'
|
||||
import { STable } from '@/components/Table'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
STable
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 当前表单元素
|
||||
searchForm: this.$form.createForm(this),
|
||||
// 查询参数
|
||||
queryParam: {},
|
||||
// 正在加载
|
||||
isLoading: false,
|
||||
// 表头
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'account_id'
|
||||
},
|
||||
{
|
||||
title: '公司信息',
|
||||
dataIndex: 'company',
|
||||
scopedSlots: { customRender: 'company' }
|
||||
},
|
||||
{
|
||||
title: '用户编号',
|
||||
dataIndex: 'userNo'
|
||||
},
|
||||
{
|
||||
title: '用户姓名',
|
||||
dataIndex: 'userName'
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
dataIndex: 'mobile'
|
||||
},
|
||||
{
|
||||
title: '用户角色',
|
||||
dataIndex: 'userType',
|
||||
scopedSlots: { customRender: 'userType' }
|
||||
},
|
||||
{
|
||||
title: '用户身份证号',
|
||||
dataIndex: 'userIdCard'
|
||||
},
|
||||
{
|
||||
title: '最后使用时间',
|
||||
dataIndex: 'last_called_at',
|
||||
scopedSlots: { customRender: 'last_called_at' }
|
||||
},
|
||||
{
|
||||
title: '注册时间',
|
||||
dataIndex: 'create_time'
|
||||
}
|
||||
],
|
||||
// 加载数据方法 必须为 Promise 对象
|
||||
loadData: param => {
|
||||
return Api.list({ ...param, ...this.queryParam })
|
||||
.then(response => {
|
||||
return response.data.list
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
* @param Boolean bool 强制刷新到第一页
|
||||
*/
|
||||
handleRefresh (bool = false) {
|
||||
this.$refs.table.refresh(bool)
|
||||
},
|
||||
|
||||
// 确认搜索
|
||||
handleSearch (e) {
|
||||
e.preventDefault()
|
||||
this.searchForm.validateFields((error, values) => {
|
||||
if (!error) {
|
||||
this.queryParam = { ...this.queryParam, ...values }
|
||||
this.handleRefresh(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-card-body {
|
||||
padding: 22px 29px 25px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,184 +0,0 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<div class="card-title">{{ $route.meta.title }}</div>
|
||||
<a-spin :spinning="isLoading">
|
||||
<a-form :form="form" @submit="handleSubmit" :selfUpdate="true">
|
||||
<a-tabs :activeKey="tabKey" :tabBarStyle="{marginBottom: '30px'}" @change="handleTabs">
|
||||
<a-tab-pane :key="0" tab="基本信息"></a-tab-pane>
|
||||
</a-tabs>
|
||||
<div class="tabs-content">
|
||||
<!-- 基本信息 -->
|
||||
<div class="tab-pane" v-show="tabKey == 0">
|
||||
<a-form-item label="公司名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司名称"
|
||||
v-decorator="['name', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="公司地址" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司地址"
|
||||
v-decorator="['address', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="纳税识别号" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入纳税识别号"
|
||||
v-decorator="['tin', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="联系人" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入联系人"
|
||||
v-decorator="['contact_name', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="联系电话" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入联系电话"
|
||||
v-decorator="['contact_tel', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="身份证号" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入身份证号"
|
||||
v-decorator="['idcard', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="请求地址" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入请求地址"
|
||||
v-decorator="['url', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="公司编号(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司编号"
|
||||
v-decorator="['orgNo', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="appKey(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司appKey"
|
||||
v-decorator="['appKey', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="公司私钥(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea class="company-textarea" v-decorator="['privateKey']" placeholder="请输入公司私钥base64编码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="公司公钥(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea class="company-textarea" v-decorator="['publicKey']" placeholder="请输入公司公钥base64编码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="平台公钥(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea class="company-textarea" v-decorator="['platformPublicKey']" placeholder="请输入平台公钥base64编码" />
|
||||
</a-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<a-form-item class="mt-20" :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
|
||||
<a-button type="primary" html-type="submit" :loading="isBtnLoading">提交</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as CompanyApi from '@/api/company'
|
||||
import CompanyModel from '@/common/model/company/Index'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 默认的标签索引
|
||||
tabKey: 0,
|
||||
// 标签布局属性
|
||||
labelCol: { span: 3 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 10 },
|
||||
// loading状态
|
||||
isLoading: false,
|
||||
isBtnLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 表单数据
|
||||
formData: CompanyModel.formData
|
||||
}
|
||||
},
|
||||
// 初始化数据
|
||||
created () {
|
||||
this.isLoading = true
|
||||
// 获取form所需的数据
|
||||
CompanyModel.getFromData()
|
||||
.then(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 手动强制更新页面
|
||||
onForceUpdate (bool = false) {
|
||||
this.$forceUpdate()
|
||||
// bool为true时再执行一次 $forceUpdate, 特殊情况下需执行两次,原因如下:
|
||||
// 第一次执行 $forceUpdate时, 新元素绑定v-decorator无法获取到form.getFieldValue
|
||||
bool && setTimeout(() => {
|
||||
this.$forceUpdate()
|
||||
}, 10)
|
||||
},
|
||||
|
||||
// 切换tab选项卡
|
||||
handleTabs (key) {
|
||||
this.tabKey = key
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
// 表单验证
|
||||
const { form: { validateFields } } = this
|
||||
validateFields((errors, values) => {
|
||||
// 定位到错误的tab选项卡
|
||||
if (errors) {
|
||||
this.onTargetTabError(errors)
|
||||
return false
|
||||
}
|
||||
// 提交到后端api
|
||||
this.onFormSubmit(values)
|
||||
return true
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交到后端api
|
||||
*/
|
||||
onFormSubmit (values) {
|
||||
this.isLoading = true
|
||||
this.isBtnLoading = true
|
||||
CompanyApi.add({ form: values })
|
||||
.then(result => {
|
||||
// 显示提示信息
|
||||
this.$message.success(result.message, 1.5)
|
||||
// 跳转到列表页
|
||||
setTimeout(() => {
|
||||
this.$router.push('./index')
|
||||
}, 1500)
|
||||
})
|
||||
.catch(() => {
|
||||
this.isBtnLoading = false
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import './style.less';
|
||||
</style>
|
||||
@@ -1,341 +0,0 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<div class="card-title">{{ $route.meta.title }}</div>
|
||||
<div class="table-operator">
|
||||
<!-- 搜索板块 -->
|
||||
<a-row class="row-item-search">
|
||||
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
|
||||
<a-form-item label="关键字搜索">
|
||||
<a-input v-decorator="['search']" placeholder="公司编号/公司名称/公司地址/联系人/联系电话/身份证号" />
|
||||
</a-form-item>
|
||||
<a-form-item class="search-btn">
|
||||
<a-button type="primary" icon="search" html-type="submit">搜索</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-row>
|
||||
<!-- 操作板块 -->
|
||||
<div class="row-item-tab clearfix">
|
||||
<a-button
|
||||
v-if="$auth('/company/create')"
|
||||
class="fl-l"
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="handleCreate"
|
||||
>新增</a-button>
|
||||
<div v-if="selectedRowKeys.length" class="button-group">
|
||||
<a-button-group class="ml-10">
|
||||
<a-button v-action:delete icon="delete" @click="handleDelete(selectedRowKeys)">删除</a-button>
|
||||
</a-button-group>
|
||||
<a-button-group class="ml-10">
|
||||
<a-button
|
||||
v-action:status
|
||||
icon="arrow-up"
|
||||
@click="handleUpdateStatus(selectedRowKeys, true)"
|
||||
>启用</a-button>
|
||||
<a-button
|
||||
v-action:status
|
||||
icon="arrow-down"
|
||||
@click="handleUpdateStatus(selectedRowKeys, false)"
|
||||
>停用</a-button>
|
||||
<a-button v-action:delete icon="delete" @click="handleDelete(selectedRowKeys)">删除</a-button>
|
||||
</a-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<s-table
|
||||
ref="table"
|
||||
rowKey="company_id"
|
||||
:loading="isLoading"
|
||||
:columns="columns"
|
||||
:data="loadData"
|
||||
:rowSelection="rowSelection"
|
||||
:pageSize="15"
|
||||
:scroll="{ x: 1450 }"
|
||||
>
|
||||
<!-- 公司地址 -->
|
||||
<span slot="address" slot-scope="text">
|
||||
<p class="twoline-hide" style="width: 400px;">{{ text }}</p>
|
||||
</span>
|
||||
<!-- 公司状态 -->
|
||||
<span slot="status" slot-scope="text, item">
|
||||
<a-tag
|
||||
class="cur-p"
|
||||
:color="text === 10 ? 'green' : 'red'"
|
||||
@click="handleUpdateStatus([item.company_id], text !== 10)"
|
||||
>{{ text === 10 ? '启用' : '停用' }}</a-tag>
|
||||
</span>
|
||||
<!-- 操作项 -->
|
||||
<div class="actions" slot="action" slot-scope="text, item">
|
||||
<a v-action:stock @click="handleStock([item.company_id])">更新库存</a>
|
||||
<a title="公司对接参数" v-action:para @click="handleApiPara(item)">对接参数</a>
|
||||
<a title="公司充值" v-action:recharge @click="handleRecharge(item)">充值</a>
|
||||
<a title="创建用户" v-action:account @click="handleAccount(item)">创建用户</a>
|
||||
<router-link v-if="$auth('/company/update')" :to="{ path: '/company/update', query: { companyId: item.company_id } }">编辑</router-link>
|
||||
<a v-action:delete @click="handleDelete([item.company_id])">删除</a>
|
||||
</div>
|
||||
</s-table>
|
||||
<RechargeForm ref="RechargeForm" @handleSubmit="handleRefresh" />
|
||||
<ApiParaForm ref="ApiParaForm" @handleSubmit="handleRefresh" />
|
||||
<AccountForm ref="AccountForm" @handleSubmit="handleRefresh" />
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as CompanyApi from '@/api/company'
|
||||
import { ContentHeader, STable } from '@/components'
|
||||
import { CompanyStatusEnum } from '@/common/enum/company'
|
||||
import { RechargeForm, ApiParaForm, AccountForm } from './modules'
|
||||
import { assignment, inArray } from '@/utils/util'
|
||||
|
||||
// 表格表头
|
||||
const columns = [
|
||||
{
|
||||
title: '公司ID',
|
||||
width: '70px',
|
||||
dataIndex: 'company_id'
|
||||
},
|
||||
{
|
||||
title: '公司编号',
|
||||
width: '150px',
|
||||
dataIndex: 'orgNo'
|
||||
},
|
||||
{
|
||||
title: '公司名称',
|
||||
width: '150px',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: '公司地址',
|
||||
width: '400px',
|
||||
dataIndex: 'address'
|
||||
},
|
||||
{
|
||||
title: '纳税识别号',
|
||||
width: '200px',
|
||||
dataIndex: 'tin'
|
||||
},
|
||||
{
|
||||
title: '余额',
|
||||
width: '150px',
|
||||
dataIndex: 'balance'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
width: '100px',
|
||||
dataIndex: 'status',
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
/*{
|
||||
title: '联系人',
|
||||
width: '150px',
|
||||
dataIndex: 'contact_name'
|
||||
},
|
||||
{
|
||||
title: '联系电话',
|
||||
width: '150px',
|
||||
dataIndex: 'contact_tel'
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
width: '150px',
|
||||
dataIndex: 'idcard'
|
||||
},*/
|
||||
{
|
||||
title: '可下单数量',
|
||||
width: '100px',
|
||||
dataIndex: 'canOrderNum'
|
||||
},
|
||||
{
|
||||
title: '未使用数量',
|
||||
width: '100px',
|
||||
dataIndex: 'unUseNum'
|
||||
},
|
||||
{
|
||||
title: '已使用数量',
|
||||
width: '100px',
|
||||
dataIndex: 'useNum'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
width: '100px',
|
||||
dataIndex: 'create_time'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: '300px',
|
||||
fixed: 'right',
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
ContentHeader,
|
||||
RechargeForm,
|
||||
ApiParaForm,
|
||||
AccountForm,
|
||||
STable
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 当前表单元素
|
||||
searchForm: this.$form.createForm(this),
|
||||
// 查询参数
|
||||
queryParam: {},
|
||||
// 正在加载
|
||||
isLoading: false,
|
||||
// 表头
|
||||
columns,
|
||||
// 选择的元素
|
||||
selectedRowKeys: [],
|
||||
// 加载数据方法 必须为 Promise 对象
|
||||
loadData: param => {
|
||||
return CompanyApi.list({ ...param, ...this.queryParam })
|
||||
.then(response => {
|
||||
return response.data.list
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
// 批量给当前实例赋值
|
||||
assignment(this, {
|
||||
inArray,
|
||||
CompanyStatusEnum
|
||||
})
|
||||
},
|
||||
created () {
|
||||
},
|
||||
computed: {
|
||||
rowSelection () {
|
||||
return {
|
||||
selectedRowKeys: this.selectedRowKeys,
|
||||
onChange: this.onSelectChange
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* 选中项发生变化时的回调
|
||||
*/
|
||||
onSelectChange (selectedRowKeys) {
|
||||
this.selectedRowKeys = selectedRowKeys
|
||||
},
|
||||
|
||||
// 确认搜索
|
||||
handleSearch (e) {
|
||||
e.preventDefault()
|
||||
this.searchForm.validateFields((error, values) => {
|
||||
if (!error) {
|
||||
this.queryParam = { ...this.queryParam, ...values }
|
||||
this.handleRefresh(true)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 重置搜索表单
|
||||
handleReset () {
|
||||
this.searchForm.resetFields()
|
||||
},
|
||||
|
||||
// 修改商品状态(上下架)
|
||||
handleUpdateStatus (companyIds, state = true) {
|
||||
if (!this.$auth('/company/changeState')) {
|
||||
return false
|
||||
}
|
||||
this.isLoading = true
|
||||
CompanyApi.changeState({ companyIds, state })
|
||||
.then(result => {
|
||||
// 显示成功
|
||||
this.$message.success(result.message, 1.5)
|
||||
this.handleRefresh()
|
||||
})
|
||||
.finally(result => { this.isLoading = false })
|
||||
},
|
||||
|
||||
// 商户充值
|
||||
handleRecharge (item) {
|
||||
this.$refs.RechargeForm.handle(item)
|
||||
},
|
||||
// 商户对接参数
|
||||
handleApiPara (item) {
|
||||
this.$refs.ApiParaForm.handle(item)
|
||||
},
|
||||
// 商户对接参数
|
||||
handleAccount (item) {
|
||||
this.$refs.AccountForm.handle(item)
|
||||
},
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
*/
|
||||
handleDelete (companyIds) {
|
||||
const app = this
|
||||
const modal = this.$confirm({
|
||||
title: '您确定要删除该记录吗?',
|
||||
content: '删除后不可恢复',
|
||||
onOk () {
|
||||
return CompanyApi.deleted(companyIds)
|
||||
.then(result => {
|
||||
app.$message.success(result.message, 1.5)
|
||||
app.handleRefresh()
|
||||
})
|
||||
.finally(result => {
|
||||
modal.destroy()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新库存
|
||||
*/
|
||||
handleStock (companyIds) {
|
||||
const app = this
|
||||
const modal = this.$confirm({
|
||||
title: '执行此操作将更新商品可用库存',
|
||||
content: '',
|
||||
onOk () {
|
||||
return CompanyApi.stock(companyIds)
|
||||
.then(result => {
|
||||
app.$message.success(result.message, 1.5)
|
||||
app.handleRefresh()
|
||||
})
|
||||
.finally(result => {
|
||||
modal.destroy()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 新增记录
|
||||
*/
|
||||
handleCreate () {
|
||||
this.$router.push('/company/create')
|
||||
},
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
* @param Boolean bool 强制刷新到第一页
|
||||
*/
|
||||
handleRefresh (bool = false) {
|
||||
this.selectedRowKeys = []
|
||||
this.$refs.table.refresh(bool)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ant-card-body {
|
||||
padding: 22px 29px 25px;
|
||||
}
|
||||
// 筛选tab
|
||||
.tab-list {
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,210 +0,0 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<div class="card-title">{{ $route.meta.title }}</div>
|
||||
<a-spin :spinning="isLoading">
|
||||
<a-form :form="form" @submit="handleSubmit" :selfUpdate="true">
|
||||
<a-tabs :activeKey="tabKey" :tabBarStyle="{marginBottom: '30px'}" @change="handleTabs">
|
||||
<a-tab-pane :key="0" tab="基本信息"></a-tab-pane>
|
||||
</a-tabs>
|
||||
<div class="tabs-content">
|
||||
<!-- 基本信息 -->
|
||||
<div class="tab-pane" v-show="tabKey == 0">
|
||||
<a-form-item label="公司名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司名称"
|
||||
v-decorator="['name', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="公司地址" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司地址"
|
||||
v-decorator="['address', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="纳税识别号" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入纳税识别号"
|
||||
v-decorator="['tin', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="联系人" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入联系人"
|
||||
v-decorator="['contact_name', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="联系电话" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入联系电话"
|
||||
v-decorator="['contact_tel', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="身份证号" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入身份证号"
|
||||
v-decorator="['idcard', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="请求地址" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入请求地址"
|
||||
v-decorator="['url', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="公司编号(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司编号"
|
||||
v-decorator="['orgNo', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="appKey(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input
|
||||
placeholder="请输入公司appKey"
|
||||
v-decorator="['appKey', {rules: [{required: false}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="公司私钥(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea class="company-textarea" v-decorator="['privateKey']" placeholder="请输入公司私钥base64编码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="公司公钥(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea class="company-textarea" v-decorator="['publicKey']" placeholder="请输入公司公钥base64编码" />
|
||||
</a-form-item>
|
||||
<a-form-item label="平台公钥(平台提供)" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea class="company-textarea" v-decorator="['platformPublicKey']" placeholder="请输入平台公钥base64编码" />
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<a-form-item class="mt-20" :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
|
||||
<a-button type="primary" html-type="submit" :loading="isBtnLoading">提交</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as CompanyApi from '@/api/company'
|
||||
import { InputNumberGroup } from '@/components'
|
||||
import CompanyModel from '@/common/model/company/Index'
|
||||
import { isEmptyObject } from '@/utils/util'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InputNumberGroup
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 默认的标签索引
|
||||
tabKey: 0,
|
||||
// 标签布局属性
|
||||
labelCol: { span: 3 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 10 },
|
||||
// loading状态
|
||||
isLoading: false,
|
||||
isBtnLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 公司ID
|
||||
companyId: null,
|
||||
// 表单数据
|
||||
formData: CompanyModel.formData
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// 初始化数据
|
||||
this.initData()
|
||||
},
|
||||
beforeDestroy () {
|
||||
// 销毁商户详情
|
||||
CompanyModel.formData.company = {}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 初始化数据
|
||||
initData () {
|
||||
// 记录商户ID
|
||||
this.companyId = this.$route.query.companyId
|
||||
// 获取form所需的数据
|
||||
this.isLoading = true
|
||||
CompanyModel.getFromData(this.companyId)
|
||||
.then(() => {
|
||||
// 商户表单数据
|
||||
if (!isEmptyObject(this.form.getFieldsValue())) {
|
||||
this.form.setFieldsValue(CompanyModel.getFieldsValue())
|
||||
}
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
// 手动强制更新页面
|
||||
onForceUpdate (bool = false) {
|
||||
this.$forceUpdate()
|
||||
// bool为true时再执行一次 $forceUpdate, 特殊情况下需执行两次,原因如下:
|
||||
// 第一次执行 $forceUpdate时, 新元素绑定v-decorator无法获取到form.getFieldValue
|
||||
bool && setTimeout(() => {
|
||||
this.$forceUpdate()
|
||||
}, 10)
|
||||
},
|
||||
|
||||
// 切换tab选项卡
|
||||
handleTabs (key) {
|
||||
this.tabKey = key
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
// 表单验证
|
||||
const { form: { validateFields } } = this
|
||||
validateFields((errors, values) => {
|
||||
// 定位到错误的tab选项卡
|
||||
if (errors) {
|
||||
this.onTargetTabError(errors)
|
||||
return false
|
||||
}
|
||||
// 提交到后端api
|
||||
this.onFormSubmit(values)
|
||||
return true
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 定位到错误的tab选项卡
|
||||
*/
|
||||
onTargetTabError (errors) {
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交到后端api
|
||||
*/
|
||||
onFormSubmit (values) {
|
||||
this.isLoading = true
|
||||
this.isBtnLoading = true
|
||||
CompanyApi.edit({ companyId: this.companyId, form: values })
|
||||
.then(result => {
|
||||
// 显示提示信息
|
||||
this.$message.success(result.message, 1.5)
|
||||
// 跳转到列表页
|
||||
setTimeout(() => {
|
||||
this.$router.push('./index')
|
||||
}, 1500)
|
||||
})
|
||||
.catch(() => {
|
||||
this.isBtnLoading = false
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import './style.less';
|
||||
</style>
|
||||
@@ -1,146 +0,0 @@
|
||||
<template>
|
||||
<a-card :bordered="false">
|
||||
<div class="card-title">{{ $route.meta.title }}</div>
|
||||
<div class="table-operator">
|
||||
<!-- 搜索板块 -->
|
||||
<a-row class="row-item-search">
|
||||
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
|
||||
<a-form-item label="公司名称">
|
||||
<a-input v-decorator="['search']" placeholder="请输入公司名称" />
|
||||
</a-form-item>
|
||||
<a-form-item label="余额变动场景">
|
||||
<a-select v-decorator="['scene', { initialValue: 0 }]">
|
||||
<a-select-option :value="0">全部</a-select-option>
|
||||
<a-select-option
|
||||
v-for="(item, index) in SceneEnum.data"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="变动时间">
|
||||
<a-range-picker format="YYYY-MM-DD" v-decorator="['betweenTime']" />
|
||||
</a-form-item>
|
||||
<a-form-item class="search-btn">
|
||||
<a-button type="primary" icon="search" html-type="submit">搜索</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-row>
|
||||
</div>
|
||||
<s-table
|
||||
ref="table"
|
||||
rowKey="log_id"
|
||||
:loading="isLoading"
|
||||
:columns="columns"
|
||||
:data="loadData"
|
||||
:pageSize="15"
|
||||
>
|
||||
<!-- 商户 -->
|
||||
<span slot="company" slot-scope="text, item">
|
||||
<p class="twoline-hide" style="width: 150px;">{{ item.name }}</p>
|
||||
</span>
|
||||
<!-- 余额变动场景 -->
|
||||
<span slot="scene" slot-scope="text">
|
||||
<a-tag>{{ SceneEnum[text].name }}</a-tag>
|
||||
</span>
|
||||
</s-table>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as Api from '@/api/company/balance'
|
||||
import { STable } from '@/components/Table'
|
||||
import SceneEnum from '@/common/enum/company/balance/log/Scene'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
STable
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 枚举类
|
||||
SceneEnum,
|
||||
// 当前表单元素
|
||||
searchForm: this.$form.createForm(this),
|
||||
// 查询参数
|
||||
queryParam: {},
|
||||
// 正在加载
|
||||
isLoading: false,
|
||||
// 表头
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'log_id'
|
||||
},
|
||||
{
|
||||
title: '公司信息',
|
||||
dataIndex: 'company',
|
||||
scopedSlots: { customRender: 'company' }
|
||||
},
|
||||
{
|
||||
title: '余额变动场景',
|
||||
dataIndex: 'scene',
|
||||
scopedSlots: { customRender: 'scene' }
|
||||
},
|
||||
{
|
||||
title: '变动金额',
|
||||
dataIndex: 'money'
|
||||
},
|
||||
{
|
||||
title: '描述/说明',
|
||||
width: '260px',
|
||||
dataIndex: 'describe'
|
||||
},
|
||||
{
|
||||
title: '管理员备注',
|
||||
width: '260px',
|
||||
dataIndex: 'remark'
|
||||
},
|
||||
{
|
||||
title: '变动时间',
|
||||
dataIndex: 'create_time'
|
||||
}
|
||||
],
|
||||
// 加载数据方法 必须为 Promise 对象
|
||||
loadData: param => {
|
||||
return Api.log({ ...param, ...this.queryParam })
|
||||
.then(response => {
|
||||
return response.data.list
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
* @param Boolean bool 强制刷新到第一页
|
||||
*/
|
||||
handleRefresh (bool = false) {
|
||||
this.$refs.table.refresh(bool)
|
||||
},
|
||||
|
||||
// 确认搜索
|
||||
handleSearch (e) {
|
||||
e.preventDefault()
|
||||
this.searchForm.validateFields((error, values) => {
|
||||
if (!error) {
|
||||
this.queryParam = { ...this.queryParam, ...values }
|
||||
this.handleRefresh(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-card-body {
|
||||
padding: 22px 29px 25px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,123 +0,0 @@
|
||||
<template>
|
||||
<a-modal
|
||||
class="noborder"
|
||||
:title="title"
|
||||
:width="520"
|
||||
:visible="visible"
|
||||
:confirmLoading="confirmLoading"
|
||||
:maskClosable="false"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form :form="form">
|
||||
<template>
|
||||
<a-form-item class="mb-5" label="公司ID" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.company_id }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="公司名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.name }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="创建用户数" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input-number
|
||||
:min="1"
|
||||
v-decorator="[`users`, { initialValue: '', rules: [{ required: true, message: '请输入用户数' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import pick from 'lodash.pick'
|
||||
import * as Api from '@/api/company'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '创建公司用户',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 13 },
|
||||
// modal(对话框)是否可见
|
||||
visible: false,
|
||||
// modal(对话框)确定按钮 loading
|
||||
confirmLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 当前记录
|
||||
record: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 显示对话框
|
||||
handle (record) {
|
||||
// 显示窗口
|
||||
this.visible = true
|
||||
// 当前记录
|
||||
this.record = record
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
// 表单验证
|
||||
const { form: { validateFields } } = this
|
||||
validateFields((errors, values) => {
|
||||
// 提交到后端api
|
||||
!errors && this.onFormSubmit(values)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭对话框事件
|
||||
*/
|
||||
handleCancel () {
|
||||
this.visible = false
|
||||
this.form.resetFields()
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交到后端api
|
||||
*/
|
||||
onFormSubmit (values) {
|
||||
const { record } = this
|
||||
this.confirmLoading = true
|
||||
values.company_id = record.company_id
|
||||
Api.account({ companyId: record.company_id, form: values })
|
||||
.then((result) => {
|
||||
// 显示成功
|
||||
this.$message.success(result.message, 1.5)
|
||||
// 关闭对话框事件
|
||||
this.handleCancel()
|
||||
// 通知父端组件提交完成了
|
||||
this.$emit('handleSubmit', values)
|
||||
})
|
||||
.finally(() => {
|
||||
this.confirmLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ant-modal-body {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<a-modal
|
||||
class="noborder"
|
||||
:title="title"
|
||||
:width="900"
|
||||
:visible="visible"
|
||||
:confirmLoading="confirmLoading"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form :form="form">
|
||||
<a-tabs :activeKey="activeKey" @change="onChangeTabs">
|
||||
<a-tab-pane :key="RECHARGE_TYPE_BALANCE" tab="公司对接参数">
|
||||
<template v-if="activeKey === RECHARGE_TYPE_BALANCE">
|
||||
<a-form-item class="mb-5" label="请求地址" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.url }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="公司编号" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.orgNo }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="公司appKey" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.appKey }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="公司私钥" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.privateKey }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="公司公钥" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.publicKey }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="平台公司公钥" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.platformPublicKey }}</span>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import pick from 'lodash.pick'
|
||||
|
||||
// 充值类型枚举: 余额
|
||||
const RECHARGE_TYPE_BALANCE = 'balance'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '公司对接参数',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 13 },
|
||||
// modal(对话框)是否可见
|
||||
visible: false,
|
||||
// modal(对话框)确定按钮 loading
|
||||
confirmLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 当前tab索引
|
||||
activeKey: RECHARGE_TYPE_BALANCE,
|
||||
// 充值类型
|
||||
RECHARGE_TYPE_BALANCE,
|
||||
// 当前记录
|
||||
record: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 显示对话框
|
||||
handle (record) {
|
||||
// 显示窗口
|
||||
this.visible = true
|
||||
// 当前记录
|
||||
this.record = record
|
||||
},
|
||||
|
||||
// 切换tabs事件
|
||||
onChangeTabs (activeKey) {
|
||||
this.activeKey = activeKey
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭对话框事件
|
||||
*/
|
||||
handleCancel () {
|
||||
this.visible = false
|
||||
this.form.resetFields()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ant-modal-body {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,190 +0,0 @@
|
||||
<template>
|
||||
<a-modal
|
||||
class="noborder"
|
||||
:title="title"
|
||||
:width="520"
|
||||
:visible="visible"
|
||||
:confirmLoading="confirmLoading"
|
||||
:maskClosable="false"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form :form="form">
|
||||
<a-tabs :activeKey="activeKey" @change="onChangeTabs">
|
||||
<a-tab-pane :key="RECHARGE_TYPE_BALANCE" tab="充值余额">
|
||||
<template v-if="activeKey === RECHARGE_TYPE_BALANCE">
|
||||
<a-form-item class="mb-5" label="公司ID" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.company_id }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="当前余额" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span class="c-p">{{ record.balance }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="充值方式" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-radio-group
|
||||
v-decorator="[`${RECHARGE_TYPE_BALANCE}.mode`, { initialValue: 'inc', rules: [{ required: true }] }]"
|
||||
>
|
||||
<a-radio value="inc">增加</a-radio>
|
||||
<a-radio value="dec">减少</a-radio>
|
||||
<a-radio value="final">最终金额</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="变更金额" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input-number
|
||||
:min="0.01"
|
||||
v-decorator="[`${RECHARGE_TYPE_BALANCE}.money`, { initialValue: '', rules: [{ required: true, message: '请输入变更的金额' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="管理员备注" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea
|
||||
placeholder="请输入管理员备注"
|
||||
:rows="3"
|
||||
v-decorator="[`${RECHARGE_TYPE_BALANCE}.remark`, { rules: [{ required: true, message: '请输入管理员备注' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
<!--<a-tab-pane :key="RECHARGE_TYPE_POINTS" tab="充值积分">
|
||||
<template v-if="activeKey === RECHARGE_TYPE_POINTS">
|
||||
<a-form-item class="mb-5" label="商户ID" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.company_id }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="当前积分" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span class="c-p">{{ record.points }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item label="充值方式" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-radio-group
|
||||
v-decorator="[`${RECHARGE_TYPE_POINTS}.mode`, { initialValue: 'inc', rules: [{ required: true }] }]"
|
||||
>
|
||||
<a-radio value="inc">增加</a-radio>
|
||||
<a-radio value="dec">减少</a-radio>
|
||||
<a-radio value="final">最终积分</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="变更数量" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input-number
|
||||
:min="0.01"
|
||||
v-decorator="[`${RECHARGE_TYPE_POINTS}.value`, { initialValue: '', rules: [{ required: true, message: '请输入变更的金数量' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="管理员备注" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea
|
||||
placeholder="请输入管理员备注"
|
||||
:rows="3"
|
||||
v-decorator="[`${RECHARGE_TYPE_POINTS}.remark`, { rules: [{ required: true, message: '请输入管理员备注' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>-->
|
||||
</a-tabs>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import pick from 'lodash.pick'
|
||||
import * as Api from '@/api/company'
|
||||
|
||||
// 充值类型枚举: 余额
|
||||
const RECHARGE_TYPE_BALANCE = 'balance'
|
||||
|
||||
// 充值类型枚举: 积分
|
||||
const RECHARGE_TYPE_POINTS = 'points'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '公司充值',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 13 },
|
||||
// modal(对话框)是否可见
|
||||
visible: false,
|
||||
// modal(对话框)确定按钮 loading
|
||||
confirmLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 当前tab索引
|
||||
activeKey: RECHARGE_TYPE_BALANCE,
|
||||
// 充值类型
|
||||
RECHARGE_TYPE_BALANCE,
|
||||
RECHARGE_TYPE_POINTS,
|
||||
// 当前记录
|
||||
record: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 显示对话框
|
||||
handle (record) {
|
||||
// 显示窗口
|
||||
this.visible = true
|
||||
// 当前记录
|
||||
this.record = record
|
||||
},
|
||||
|
||||
// 切换tabs事件
|
||||
onChangeTabs (activeKey) {
|
||||
this.activeKey = activeKey
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
// 表单验证
|
||||
const { form: { validateFields } } = this
|
||||
validateFields((errors, values) => {
|
||||
// 提交到后端api
|
||||
!errors && this.onFormSubmit(values)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭对话框事件
|
||||
*/
|
||||
handleCancel () {
|
||||
this.visible = false
|
||||
this.form.resetFields()
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交到后端api
|
||||
*/
|
||||
onFormSubmit (values) {
|
||||
const { record, activeKey } = this
|
||||
this.confirmLoading = true
|
||||
Api.recharge({ companyId: record.company_id, target: activeKey, form: values })
|
||||
.then((result) => {
|
||||
// 显示成功
|
||||
this.$message.success(result.message, 1.5)
|
||||
// 关闭对话框事件
|
||||
this.handleCancel()
|
||||
// 通知父端组件提交完成了
|
||||
this.$emit('handleSubmit', values)
|
||||
})
|
||||
.finally(() => {
|
||||
this.confirmLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ant-modal-body {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +0,0 @@
|
||||
import RechargeForm from './RechargeForm'
|
||||
import ApiParaForm from './ApiParaForm'
|
||||
import AccountForm from './AccountForm'
|
||||
|
||||
export {
|
||||
RechargeForm,
|
||||
ApiParaForm,
|
||||
AccountForm
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
.tabs-content {
|
||||
.tab-pane {
|
||||
animation: fadenum 0.6s ease;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/.ant-form-item-control {
|
||||
padding-left: 10px;
|
||||
|
||||
.ant-form-item-control {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 18px;
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-number-group {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.company-textarea{
|
||||
height: 80px;
|
||||
}
|
||||
@@ -39,7 +39,6 @@
|
||||
v-decorator="['callback', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<MultiGoods ref="MultiGoods" :goodsList="formData.goods" @change="handleGoodsChange" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -54,12 +53,8 @@
|
||||
<script>
|
||||
import * as PartnersApi from '@/api/partners'
|
||||
import PartnersModel from '@/common/model/partners/Index'
|
||||
import MultiGoods from './modules/MultiGoods'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiGoods
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 默认的标签索引
|
||||
@@ -74,8 +69,7 @@ export default {
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 表单数据
|
||||
formData: PartnersModel.formData,
|
||||
goodsList: []
|
||||
formData: PartnersModel.formData
|
||||
}
|
||||
},
|
||||
// 初始化数据
|
||||
@@ -117,8 +111,6 @@ export default {
|
||||
this.onTargetTabError(errors)
|
||||
return false
|
||||
}
|
||||
// 整理商品数据
|
||||
values.goodsList = this.goodsList
|
||||
// 提交到后端api
|
||||
this.onFormSubmit(values)
|
||||
return true
|
||||
@@ -146,11 +138,6 @@ export default {
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleGoodsChange (val) {
|
||||
// console.log('最新商品列表:', val)
|
||||
this.goodsList = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
v-decorator="['callback', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<MultiGoods ref="MultiGoods" :goodsList="formData.goods" :defaultGoodsList="formData.partners.goodsList" @change="handleGoodsChange" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -55,13 +54,11 @@
|
||||
import * as PartnersApi from '@/api/partners'
|
||||
import { InputNumberGroup } from '@/components'
|
||||
import PartnersModel from '@/common/model/partners/Index'
|
||||
import MultiGoods from './modules/MultiGoods'
|
||||
import { isEmptyObject } from '@/utils/util'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InputNumberGroup,
|
||||
MultiGoods
|
||||
InputNumberGroup
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -79,8 +76,7 @@ export default {
|
||||
// 合作商ID
|
||||
partnersId: null,
|
||||
// 表单数据
|
||||
formData: PartnersModel.formData,
|
||||
goodsList: []
|
||||
formData: PartnersModel.formData
|
||||
}
|
||||
},
|
||||
created () {
|
||||
@@ -137,8 +133,6 @@ export default {
|
||||
this.onTargetTabError(errors)
|
||||
return false
|
||||
}
|
||||
// 整理商品数据
|
||||
values.goodsList = this.goodsList
|
||||
// 提交到后端api
|
||||
this.onFormSubmit(values)
|
||||
return true
|
||||
@@ -172,10 +166,6 @@ export default {
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
handleGoodsChange (val) {
|
||||
this.goodsList = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-item
|
||||
label="对接商品"
|
||||
:labelCol="labelCol"
|
||||
:wrapperCol="wrapperCol"
|
||||
>
|
||||
<!-- 添加按钮 -->
|
||||
<div class="sku-batch">
|
||||
<a-button @click="handleAddGoods">添加商品</a-button>
|
||||
</div>
|
||||
|
||||
<!-- 商品列表 -->
|
||||
<a-table
|
||||
class="sku-list"
|
||||
:columns="columns"
|
||||
:dataSource="multiGoodsData"
|
||||
:scroll="{ x: true }"
|
||||
:pagination="false"
|
||||
bordered
|
||||
rowKey="row_id"
|
||||
>
|
||||
<!-- 选择商品 -->
|
||||
<template slot="goods_id" slot-scope="text, item">
|
||||
<a-select
|
||||
v-model="item.goods_id"
|
||||
placeholder="请选择商品"
|
||||
style="width: 100%"
|
||||
@change="emitChange"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(sub_item, index) in goodsList"
|
||||
:key="index"
|
||||
:value="sub_item.goods_id"
|
||||
>
|
||||
{{ sub_item.goods_name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
|
||||
<!-- 分配数量 -->
|
||||
<template slot="allot_num" slot-scope="text, item">
|
||||
<a-input-number
|
||||
v-model="item.allot_num"
|
||||
size="small"
|
||||
:precision="0"
|
||||
@change="emitChange"
|
||||
/>
|
||||
</template>
|
||||
<!-- 库存数量 -->
|
||||
<template slot="stock_num" slot-scope="text, item">
|
||||
{{ item.stock_num }}
|
||||
</template>
|
||||
<!-- 删除操作 -->
|
||||
<template slot="action" slot-scope="text, item">
|
||||
<a @click="handleDelete(item)">删除</a>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PropTypes from 'ant-design-vue/es/_util/vue-types'
|
||||
|
||||
// 表格表头
|
||||
const columns = [
|
||||
{
|
||||
title: '商品',
|
||||
dataIndex: 'goods_id',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'goods_id' }
|
||||
},
|
||||
{
|
||||
title: '分配数量',
|
||||
dataIndex: 'allot_num',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'allot_num' }
|
||||
},
|
||||
{
|
||||
title: '库存数量',
|
||||
dataIndex: 'stock_num',
|
||||
width: 120,
|
||||
scopedSlots: { customRender: 'stock_num' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: '150px',
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
props: {
|
||||
goodsList: PropTypes.any,
|
||||
defaultGoodsList: PropTypes.array.def([]),
|
||||
isGoodsLocked: PropTypes.bool.def(false)
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
labelCol: { span: 3 },
|
||||
wrapperCol: { span: 21 },
|
||||
multiGoodsData: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultGoodsList (val) {
|
||||
if (val.length) {
|
||||
this.getData()
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.multiGoodsData = this.defaultGoodsList.map((item, index) => ({
|
||||
...item,
|
||||
row_id: item.row_id || Date.now() + index
|
||||
}))
|
||||
this.emitChange()
|
||||
},
|
||||
handleAddGoods () {
|
||||
this.multiGoodsData.push({
|
||||
goods_id: null,
|
||||
allot_num: 1,
|
||||
stock_num: 0,
|
||||
row_id: Date.now()
|
||||
})
|
||||
this.emitChange()
|
||||
},
|
||||
handleDelete (record) {
|
||||
this.multiGoodsData = this.multiGoodsData.filter(item => item !== record)
|
||||
this.emitChange()
|
||||
},
|
||||
emitChange () {
|
||||
this.$emit('change', this.multiGoodsData)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// 商品多规格
|
||||
.spec-group {
|
||||
width: 895px;
|
||||
margin-bottom: 15px;
|
||||
line-height: normal;
|
||||
|
||||
.ant-input {
|
||||
height: 28px;
|
||||
padding: 4px 11px;
|
||||
font-size: @font-size-base;
|
||||
line-height: 1.5;
|
||||
|
||||
&::placeholder {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-help {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.spec-group-item {
|
||||
background: #f4f5f9;
|
||||
padding: 7px 12px;
|
||||
line-height: 28px;
|
||||
|
||||
.group-item-input {
|
||||
float: left;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.group-item-delete {
|
||||
font-size: 12px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.spec-value {
|
||||
background: #fbfbfb;
|
||||
padding: 8px 35px;
|
||||
|
||||
.spec-value-add,
|
||||
.spec-value-item {
|
||||
float: left;
|
||||
margin-bottom: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.spec-value-add {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
|
||||
a {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.spec-value-item {
|
||||
position: relative;
|
||||
margin-right: 20px;
|
||||
|
||||
.value-item-input {
|
||||
width: 186px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.icon-close {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-close {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #7d7d7d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加规格按钮
|
||||
.spec-group-add-btn {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
// 批量设置sku
|
||||
.sku-batch {
|
||||
line-height: 40px;
|
||||
margin-bottom: 12px;
|
||||
.title {
|
||||
line-height: 28px;
|
||||
margin-right: 15px;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
/deep/.ant-input,
|
||||
/deep/.ant-input-number {
|
||||
width: 120px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
/deep/.ant-input {
|
||||
width: 140px;
|
||||
}
|
||||
}
|
||||
|
||||
// sku列表
|
||||
.sku-list {
|
||||
width: 895px;
|
||||
/deep/.ant-table-thead > tr > th,
|
||||
/deep/.ant-table-tbody > tr > td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
/deep/.ant-table-tbody > tr > td {
|
||||
padding: 12px 18px;
|
||||
}
|
||||
|
||||
/deep/.ant-input-sm,
|
||||
/deep/.ant-input-number-sm {
|
||||
height: 28px;
|
||||
}
|
||||
/deep/.ant-input-number-sm input {
|
||||
height: 26px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,7 @@
|
||||
import RechargeForm from './RechargeForm'
|
||||
import ApiParaForm from './ApiParaForm'
|
||||
import MultiGoods from '../../partners/modules/MultiGoods'
|
||||
|
||||
export {
|
||||
RechargeForm,
|
||||
ApiParaForm,
|
||||
MultiGoods
|
||||
ApiParaForm
|
||||
}
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
<!-- 搜索板块 -->
|
||||
<a-row class="row-item-search">
|
||||
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
|
||||
<a-form-item label="用户电话">
|
||||
<a-input v-decorator="['search']" placeholder="请输入用户电话" />
|
||||
<a-form-item label="司机手机号">
|
||||
<a-input v-decorator="['search']" placeholder="请输入司机手机号" />
|
||||
</a-form-item>
|
||||
<a-form-item label="商品编码">
|
||||
<a-input v-decorator="['goods_no']" placeholder="商品编码" />
|
||||
<a-form-item label="司机姓名">
|
||||
<a-input v-decorator="['driver_name']" placeholder="请输入司机姓名" />
|
||||
</a-form-item>
|
||||
<a-form-item label="分油状态">
|
||||
<a-form-item label="单号">
|
||||
<a-input v-decorator="['orderNo']" placeholder="油卡编号/销售单号/批次号/运单号" />
|
||||
</a-form-item>
|
||||
<a-form-item label="发放状态">
|
||||
<a-select v-decorator="['oil_status', { initialValue: -1 }]">
|
||||
<a-select-option :value="-1">全部</a-select-option>
|
||||
<a-select-option
|
||||
@@ -21,7 +24,15 @@
|
||||
>{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="使用状态">
|
||||
<a-form-item label="企油通发放态">
|
||||
<a-select v-decorator="['oil_status_zsy', { initialValue: -1 }]">
|
||||
<a-select-option :value="-1">全部</a-select-option>
|
||||
<a-select-option :value="0">未提交</a-select-option>
|
||||
<a-select-option :value="2">发放成功</a-select-option>
|
||||
<a-select-option :value="3">发放失败</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="加油核销">
|
||||
<a-select v-decorator="['use_status', { initialValue: -1 }]">
|
||||
<a-select-option :value="-1">全部</a-select-option>
|
||||
<a-select-option
|
||||
@@ -55,7 +66,7 @@
|
||||
</a-row>
|
||||
<!-- 操作板块 -->
|
||||
<div class="row-item-tab clearfix flex-box">
|
||||
<span class="form-total">油卡金额:¥{{ total_money }}</span>
|
||||
<span class="form-total">发放总金额:¥{{ total_money }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<s-table
|
||||
@@ -66,52 +77,62 @@
|
||||
:data="loadData"
|
||||
:pageSize="15"
|
||||
>
|
||||
<span slot="goods" slot-scope="text">
|
||||
<GoodsItem
|
||||
:data="{
|
||||
image: text.images[0].file.preview_url,
|
||||
imageAlt: '商品图片',
|
||||
title: text.goods_name,
|
||||
goods_no: text.goods_no,
|
||||
goodsProps: text.goods_props
|
||||
}"
|
||||
/>
|
||||
</span>
|
||||
<span slot="partners" slot-scope="text">
|
||||
<p>{{ text.name }}</p>
|
||||
</span>
|
||||
<div slot="driver" slot-scope="item">
|
||||
<p class="mtb-2">{{ item.driver_name || '-' }}</p>
|
||||
<p class="mtb-2 f-13">{{ item.mobile }}</p>
|
||||
</div>
|
||||
<div slot="qyt" slot-scope="item">
|
||||
<p class="mtb-2 f-13">批次:{{ item.batch_no || '-' }}</p>
|
||||
<p class="mtb-2 f-13">运单:{{ item.waybill_no || '-' }}</p>
|
||||
</div>
|
||||
<div slot="consume" slot-scope="item">
|
||||
<template v-if="item.use_status === 1">
|
||||
<p class="mtb-2 f-13">{{ item.station_name || '-' }}</p>
|
||||
<p class="mtb-2 f-13">{{ item.oil_name }} {{ item.litter }}L</p>
|
||||
<p class="mtb-2 f-13">实付:¥{{ (item.pay_fee / 100).toFixed(2) }}</p>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</div>
|
||||
<div slot="status" slot-scope="item">
|
||||
<p class="mtb-2">
|
||||
<span class="f-13">分油状态:</span>
|
||||
<span class="f-13">发放状态:</span>
|
||||
<a-tag
|
||||
:color="item.oil_status == OilStatusEnum.OIL.value ? 'green' : ''"
|
||||
>{{ OilStatusEnum[item.oil_status].name }}</a-tag>
|
||||
</p>
|
||||
<p class="mtb-2">
|
||||
<span class="f-13">使用状态:</span>
|
||||
<span class="f-13">加油核销:</span>
|
||||
<a-tag
|
||||
:color="item.use_status == UseStatusEnum.USE.value ? 'green' : ''"
|
||||
>{{ UseStatusEnum[item.use_status].name }}</a-tag>
|
||||
</p>
|
||||
<p class="mtb-2">
|
||||
<span class="f-13">企油通:</span>
|
||||
<a-tag :color="qytColor(item.oil_status_zsy)">{{ qytText(item.oil_status_zsy) }}</a-tag>
|
||||
</p>
|
||||
<p v-if="item.oil_text" class="mtb-2 f-13 order-remark">{{ item.oil_text }}</p>
|
||||
</div>
|
||||
<div class="actions" slot="action" slot-scope="item">
|
||||
<!--有付款权限,订单状态为进行中,已支付,并且未使用-->
|
||||
<a
|
||||
v-if="(inArray(item.oil_status_zsy, [3])) && item.oil_status === 0 && item.oilCardType === 'zsy_ticket'"
|
||||
@click="handleShare(item)"
|
||||
>手动分油</a>
|
||||
>重新发放</a>
|
||||
<a
|
||||
v-if="(inArray(item.oil_status_zsy, [2])) && item.oil_status === 1 && item.use_status === 0 && item.oilCardType === 'zsy_ticket'"
|
||||
@click="handlePay(item)"
|
||||
>付款码</a>
|
||||
>加油链接</a>
|
||||
<a
|
||||
v-if="(inArray(item.oil_status_zsy, [2])) && item.oil_status === 1 && item.oilCardType === 'zsy_ticket'"
|
||||
@click="handleOil(item)"
|
||||
>分油结果回调</a>
|
||||
>重推发放结果</a>
|
||||
<a
|
||||
v-if="(inArray(item.oil_status_zsy, [2])) && item.oil_status === 1 && item.use_status === 1 && item.oilCardType === 'zsy_ticket'"
|
||||
@click="handleUse(item)"
|
||||
>使用结果回调</a>
|
||||
>重推加油结果</a>
|
||||
</div>
|
||||
</s-table>
|
||||
<ShareForm ref="ShareForm" @handleSubmit="handleRefresh" />
|
||||
@@ -123,7 +144,7 @@
|
||||
|
||||
<script>
|
||||
import * as Api from '@/api/partners/order'
|
||||
import { STable, GoodsItem } from '@/components/Table'
|
||||
import { STable } from '@/components/Table'
|
||||
import {
|
||||
OilStatusEnum, UseStatusEnum
|
||||
} from '@/common/enum/order'
|
||||
@@ -136,7 +157,6 @@ export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
STable,
|
||||
GoodsItem,
|
||||
ShareForm,
|
||||
PayForm,
|
||||
OilForm,
|
||||
@@ -162,9 +182,8 @@ export default {
|
||||
scopedSlots: { customRender: 'oilCardNo' }
|
||||
},
|
||||
{
|
||||
title: '分油记录编号',
|
||||
dataIndex: 'shareNo',
|
||||
scopedSlots: { customRender: 'shareNo' }
|
||||
title: '企油通单号',
|
||||
scopedSlots: { customRender: 'qyt' }
|
||||
},
|
||||
{
|
||||
title: '对接公司内部销售单号',
|
||||
@@ -172,23 +191,21 @@ export default {
|
||||
scopedSlots: { customRender: 'partners_order_no' }
|
||||
},
|
||||
{
|
||||
title: '油卡数量',
|
||||
title: '数量',
|
||||
dataIndex: 'total_num',
|
||||
scopedSlots: { customRender: 'total_num' }
|
||||
},
|
||||
{
|
||||
title: '油卡金额',
|
||||
title: '发放金额',
|
||||
dataIndex: 'total_price'
|
||||
},
|
||||
{
|
||||
title: '商品信息',
|
||||
dataIndex: 'goods',
|
||||
scopedSlots: { customRender: 'goods' }
|
||||
title: '司机',
|
||||
scopedSlots: { customRender: 'driver' }
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
dataIndex: 'mobile',
|
||||
scopedSlots: { customRender: 'mobile' }
|
||||
title: '加油信息',
|
||||
scopedSlots: { customRender: 'consume' }
|
||||
},
|
||||
{
|
||||
title: '合作商',
|
||||
@@ -256,7 +273,16 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// 手动分油
|
||||
// 企油通发放态文案
|
||||
qytText (v) {
|
||||
return { 0: '未提交', 1: '处理中', 2: '发放成功', 3: '发放失败' }[v] || '未知'
|
||||
},
|
||||
// 企油通发放态颜色
|
||||
qytColor (v) {
|
||||
return { 2: 'green', 3: 'red' }[v] || ''
|
||||
},
|
||||
|
||||
// 重新发放
|
||||
handleShare (record) {
|
||||
this.$refs.ShareForm.show(record)
|
||||
},
|
||||
|
||||
@@ -37,7 +37,7 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '手动分油',
|
||||
title: '重推发放结果',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="title"
|
||||
:width="560"
|
||||
:width="520"
|
||||
:visible="visible"
|
||||
:isLoading="isLoading"
|
||||
:confirmLoading="isLoading"
|
||||
:maskClosable="false"
|
||||
@ok="handleCancel"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="isLoading">
|
||||
<a-form :form="form">
|
||||
<iframe :src="qrCodeValue" width="200px" height="200px"></iframe>
|
||||
</a-form>
|
||||
<div v-if="qrCodeValue" class="qyt-h5">
|
||||
<div class="qyt-h5__tip">司机扫码即可进入企油通加油页(免登),也可直接把下方链接发给司机。</div>
|
||||
<div class="qyt-h5__qr">
|
||||
<vue-qr :text="qrCodeValue" :size="200" :margin="6" />
|
||||
</div>
|
||||
<a-input-search
|
||||
class="qyt-h5__url"
|
||||
:value="qrCodeValue"
|
||||
readonly
|
||||
enter-button="复制"
|
||||
@search="handleCopy"
|
||||
/>
|
||||
</div>
|
||||
<a-empty v-else description="正在获取加油链接…" />
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
@@ -28,24 +38,16 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '支付码',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 13 },
|
||||
title: '加油链接',
|
||||
// modal(对话框)是否可见
|
||||
visible: false,
|
||||
// modal(对话框)确定按钮 loading
|
||||
// 加载中
|
||||
isLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 当前记录
|
||||
record: {},
|
||||
// 企油通 H5 免登加油地址
|
||||
qrCodeValue: ''
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -53,47 +55,64 @@ export default {
|
||||
* 显示对话框
|
||||
*/
|
||||
show (record) {
|
||||
// 显示窗口
|
||||
this.visible = true
|
||||
// 当前记录
|
||||
this.record = record
|
||||
this.qrCodeValue = ''
|
||||
this.getQrCode()
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
// 表单验证
|
||||
const { form: { validateFields } } = this
|
||||
validateFields((errors, values) => {
|
||||
// 提交到后端api
|
||||
!errors && this.onFormSubmit(values)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭对话框事件
|
||||
*/
|
||||
handleCancel () {
|
||||
this.visible = false
|
||||
this.form.resetFields()
|
||||
this.qrCodeValue = ''
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取支付二维码
|
||||
* 复制链接
|
||||
*/
|
||||
handleCopy () {
|
||||
const input = document.createElement('input')
|
||||
input.value = this.qrCodeValue
|
||||
document.body.appendChild(input)
|
||||
input.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(input)
|
||||
this.$message.success('链接已复制', 1.5)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取企油通 H5 免登加油地址(7.15)
|
||||
*/
|
||||
getQrCode () {
|
||||
this.isLoading = true
|
||||
Api.qrCode({ orderId: this.record.order_id })
|
||||
.then((result) => {
|
||||
// 显示成功
|
||||
.then(result => {
|
||||
this.qrCodeValue = result.data.qrCode
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.qyt-h5 {
|
||||
text-align: center;
|
||||
&__tip {
|
||||
color: #969799;
|
||||
font-size: 13px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
&__qr {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
&__url {
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -37,7 +37,7 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '手动分油',
|
||||
title: '重新发放',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
|
||||
@@ -37,7 +37,7 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '手动分油',
|
||||
title: '重推加油结果',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
|
||||
@@ -9,19 +9,6 @@
|
||||
<div class="tabs-content">
|
||||
<!-- 基本信息 -->
|
||||
<div class="tab-pane" v-show="tabKey == 0">
|
||||
<a-form-item label="分油公司" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select
|
||||
style="width: 300px"
|
||||
v-decorator="['company_id', {rules: [{required: true, message: '请选择分油公司'}]}]"
|
||||
placeholder="请选择商户"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(item, index) in formData.companyList"
|
||||
:key="index"
|
||||
:value="item.company_id"
|
||||
>{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="商户" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select
|
||||
style="width: 300px"
|
||||
|
||||
@@ -75,12 +75,10 @@
|
||||
<a title="会员充值" v-action:recharge @click="handleRecharge(item)">充值</a>
|
||||
<a title="会员等级" v-action:grade @click="handleGrade(item)">等级</a>
|
||||
<a v-action:delete @click="handleDelete(item)">删除</a>
|
||||
<!-- <a title="用户分油" v-action:oil @click="handleOil(item)">分油</a>-->
|
||||
</span>
|
||||
</s-table>
|
||||
<GradeForm ref="GradeForm" :gradeList="gradeList" @handleSubmit="handleRefresh" />
|
||||
<RechargeForm ref="RechargeForm" @handleSubmit="handleRefresh" />
|
||||
<OilForm ref="OilForm" @handleSubmit="handleRefresh" />
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
@@ -88,7 +86,7 @@
|
||||
import * as Api from '@/api/user'
|
||||
import * as GradeApi from '@/api/user/grade'
|
||||
import { STable } from '@/components'
|
||||
import { GradeForm, RechargeForm, OilForm } from './modules'
|
||||
import { GradeForm, RechargeForm } from './modules'
|
||||
import PlatformIcon from '@/components/PlatformIcon'
|
||||
|
||||
export default {
|
||||
@@ -97,7 +95,6 @@ export default {
|
||||
STable,
|
||||
GradeForm,
|
||||
RechargeForm,
|
||||
OilForm,
|
||||
PlatformIcon
|
||||
},
|
||||
data () {
|
||||
@@ -216,11 +213,6 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// 用户分油
|
||||
handleOil (item) {
|
||||
this.$refs.OilForm.handle(item)
|
||||
},
|
||||
|
||||
/**
|
||||
* 刷新列表
|
||||
* @param Boolean bool 强制刷新到第一页
|
||||
|
||||
@@ -9,19 +9,6 @@
|
||||
<div class="tabs-content">
|
||||
<!-- 基本信息 -->
|
||||
<div class="tab-pane" v-show="tabKey == 0">
|
||||
<a-form-item label="分油公司" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select
|
||||
style="width: 300px"
|
||||
v-decorator="['company_id', {rules: [{required: true, message: '请选择分油公司'}]}]"
|
||||
placeholder="请选择商户"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(item, index) in formData.companyList"
|
||||
:key="index"
|
||||
:value="item.company_id"
|
||||
>{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="商户" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select
|
||||
style="width: 300px"
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
<template>
|
||||
<a-modal
|
||||
class="noborder"
|
||||
:title="title"
|
||||
:width="520"
|
||||
:visible="visible"
|
||||
:confirmLoading="confirmLoading"
|
||||
:maskClosable="false"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form :form="form">
|
||||
<a-tabs :activeKey="activeKey" @change="onChangeTabs">
|
||||
<a-tab-pane :key="OIL_TYPE" tab="用户分油">
|
||||
<template v-if="activeKey === OIL_TYPE">
|
||||
<a-form-item class="mb-5" label="用户昵称" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.nick_name ? record.nick_name : '无' }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="手机号" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<span>{{ record.mobile }}</span>
|
||||
</a-form-item>
|
||||
<a-form-item class="mb-5" label="卡券类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select @change="typeChange" v-decorator="[`oilCardType`, { rules: [{required: true, message: '请选择卡券类型'}], initialValue: 'zsy_ticket' }]">
|
||||
<a-select-option
|
||||
v-for="(item, index) in OilCardTypeEnum.data"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="所属省份" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select
|
||||
style="width: 300px"
|
||||
@change="handleChange"
|
||||
v-decorator="['province', {rules: [{required: true, message: '请选择所属省份'}]}]"
|
||||
placeholder="请选择所属省份"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(item, index) in province"
|
||||
:key="index"
|
||||
:value="item"
|
||||
>{{ item }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="油券" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-select
|
||||
style="width: 300px"
|
||||
v-decorator="['goods_id', {rules: []}]"
|
||||
placeholder="请选择油券"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="(item, index) in goods"
|
||||
:key="index"
|
||||
:value="item.goods_id"
|
||||
>{{ item.goods_name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="分油金额" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-input-number
|
||||
placeholder="卡券类型为油卡时填写"
|
||||
:min="0.01"
|
||||
v-decorator="[`amount`, { initialValue: '', rules: [] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="管理员备注" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-textarea
|
||||
placeholder="请输入管理员备注"
|
||||
:rows="3"
|
||||
v-decorator="[`buyer_remark`, { rules: [{ required: true, message: '请输入管理员备注' }] }]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import pick from 'lodash.pick'
|
||||
import * as Api from '@/api/user'
|
||||
import * as GoodsApi from '@/api/goods'
|
||||
|
||||
import {
|
||||
OilCardTypeEnum
|
||||
} from '@/common/enum/order'
|
||||
import { assignment, inArray } from '@/utils/util'
|
||||
|
||||
// 充值类型枚举: 余额
|
||||
const OIL_TYPE = 'oil'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 对话框标题
|
||||
title: '用户分油',
|
||||
// 标签布局属性
|
||||
labelCol: { span: 7 },
|
||||
// 输入框布局属性
|
||||
wrapperCol: { span: 13 },
|
||||
// modal(对话框)是否可见
|
||||
visible: false,
|
||||
// modal(对话框)确定按钮 loading
|
||||
confirmLoading: false,
|
||||
// 当前表单元素
|
||||
form: this.$form.createForm(this),
|
||||
// 当前tab索引
|
||||
activeKey: OIL_TYPE,
|
||||
// 类型
|
||||
OIL_TYPE,
|
||||
// 当前记录
|
||||
record: {},
|
||||
oilCardType: 'zsy_ticket',
|
||||
pro: '',
|
||||
province: [],
|
||||
goods: []
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
// 批量给当前实例赋值
|
||||
assignment(this, {
|
||||
inArray,
|
||||
OilCardTypeEnum
|
||||
})
|
||||
},
|
||||
created () {
|
||||
this.getProvinceList()
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 显示对话框
|
||||
handle (record) {
|
||||
// 显示窗口
|
||||
this.visible = true
|
||||
// 当前记录
|
||||
this.record = record
|
||||
},
|
||||
|
||||
// 切换tabs事件
|
||||
onChangeTabs (activeKey) {
|
||||
this.activeKey = activeKey
|
||||
},
|
||||
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
// 表单验证
|
||||
const { form: { validateFields } } = this
|
||||
validateFields((errors, values) => {
|
||||
// 提交到后端api
|
||||
!errors && this.onFormSubmit(values)
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭对话框事件
|
||||
*/
|
||||
handleCancel () {
|
||||
this.visible = false
|
||||
this.form.resetFields()
|
||||
},
|
||||
|
||||
/**
|
||||
* 提交到后端api
|
||||
*/
|
||||
onFormSubmit (values) {
|
||||
const { record, activeKey } = this
|
||||
this.confirmLoading = true
|
||||
Api.oil({ userId: record.user_id, target: activeKey, form: values })
|
||||
.then((result) => {
|
||||
// 显示成功
|
||||
this.$message.success(result.message, 1.5)
|
||||
// 关闭对话框事件
|
||||
this.handleCancel()
|
||||
// 通知父端组件提交完成了
|
||||
this.$emit('handleSubmit', values)
|
||||
})
|
||||
.finally(() => {
|
||||
this.confirmLoading = false
|
||||
})
|
||||
},
|
||||
typeChange (value, option) {
|
||||
this.oilCardType = value
|
||||
this.getGoodsList(this.pro, value)
|
||||
},
|
||||
handleChange (value, option) {
|
||||
this.pro = value
|
||||
this.getGoodsList(value, this.oilCardType)
|
||||
},
|
||||
// 获取商品
|
||||
getGoodsList (province, oilCardType) {
|
||||
return new Promise((resolve, reject) => {
|
||||
GoodsApi.all({ province, oilCardType })
|
||||
.then(result => {
|
||||
this.goods = result.data.list
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取省份
|
||||
getProvinceList () {
|
||||
return new Promise((resolve, reject) => {
|
||||
GoodsApi.province()
|
||||
.then(result => {
|
||||
this.province = result.data.list
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.ant-modal-body {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,4 @@
|
||||
import GradeForm from './GradeForm'
|
||||
import RechargeForm from './RechargeForm'
|
||||
import OilForm from './OilForm'
|
||||
|
||||
export { GradeForm, RechargeForm, OilForm }
|
||||
export { GradeForm, RechargeForm }
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
APP_DEBUG = false
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = oil
USERNAME = user
PASSWORD = qQ19961012
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
[CACHE]
DRIVER = file
[REDIS]
HOSTNAME = 127.0.0.1
HOSTPORT = 6379
PASSWORD =
SELECT = 0
[LANG]
default_lang = zh-cn
|
||||
APP_DEBUG = false
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = oil
USERNAME = oil
PASSWORD = AxSZEJDp5nePyfMa
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
[CACHE]
DRIVER = file
[REDIS]
HOSTNAME = 127.0.0.1
HOSTPORT = 6379
PASSWORD =
SELECT = 0
[LANG]
default_lang = zh-cn
; ===== 企油通对接配置(值不要加引号;RSA 密钥压成一行 base64,去掉 BEGIN/END 与换行)=====
[QYT]
; 接口域名,不含结尾斜杠,向企油通对接人索取(测试/正式不同)
BASE_URL = http://dev.pbpayapi.worknoya.work
; 平台分配的 appId(业务接口用)
APP_ID = 37257338026e7a377165454689773882
; 我方 RSA 私钥(一行 base64,无头尾无换行)
PRIVATE_KEY = MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpi86NYP5sVj2FcLvSk3o6mmWAgEW4TiuMtzDqld1QjaKAVaEbbGN93ZvSaafawPeBMI5qi04NvFHnPlGuQiGxJ5ddzaE4P5/xAsd2NnUFY30o71n3Tq30jYQdblTa7xr9nAhZiBrd2CtKWfvnoU/RxsJORUhiJhKtTVjNQ6N8UICDyUVzlhIqKtishMLYDSIhRnONtrQuKnXDPAoaTxbxEHLHXbic7WPwtOUNln/7oKuLdGJyKn2ikFv1YBNzwVpaLRsu+zF617qE5HWVf5GtEs/IuD+p1t4p6Dnm0Bq1fChkqz3pQejiyuNzhZt3zJZWCz3aPOxKLXBhfm+V29yZAgMBAAECggEABRJmGOucYNBJodrH+5omz2b7/1aW/1bzTY/TWkkmaDj8cftdyOy6ozLEbQx1FYGtRcOWlxBYwudtyc2e8ugOivakvA0hNAYPOk37eolRgdpCjb1vQwsrAARVve2lgzEg7RJEW61LJHTJgr1jYD/+m8dm26GN80WxTFbif6100Ayp++qxP7/EAwsD+Nl9wNo1itSHIiwzt4ohCWgxoSgVwkoUdMVM3qERzBXzjQAzK/A8DuJDyNayu74YVBrxXGRbzeeOippu7d2dY6bHwyDah7ki5IW9MRmMH/d24sayb+kYYKXI9d+G9jqXlL9ZASb4/OPQ2s7WPftDQhIvpXJdwQKBgQDUmkdl+viy13PtmV00AfzDaOeOTOknzfW7xjylnYR63pI8dnMLTN+RIXYgWMbehrLjMwxhWjekOPKA9HZ2g1wI7sxYsHWBiq6StYOcS7RlGayyvFstbbUR3X5Ff7y/3+BmYzrzZKepwJ8bCLCoMaRPw4HiGVdNm0qOfmQAeuopMQKBgQDMJ5MWc9jAbvs1hb4JZ6oTPY1SMfA7QTas3EHq8CFCgvFJEtu1F2QD4w+L2G0m0zgVHDuFKR88mFIs+yGzfEhNy05ro2oAExW7MuwwEeQHWcq1m+r7iQMEchMCJbXEZLf9lUxNb3NKVG/W3gMDAkJfh+uFln/DAf/GOeFXttqP6QKBgBvI8e3VB+2vlLoHohOq8tLDAggp6wrFswjQVpq6ZFb+gZQfUte2Oz2nZt3BXHQ2nGhvAn4yoTT4MFFEIbtJXZzZQKGSpjjA3CHWURX7Gt9fpJ9TWIMuZEyqatdAY3WcF6Kp80ld7T+VKfYJg7Tnj/bQsUfQUgWVdv/6aq1ZYwLxAoGAVo80+yEVNsoXcuMI5x3v64Z+g+oujEEjOHmO7VjxES1JtozrYMXRHyDHt6iE5yBJOBInXldIKj3/IZk8+cfpNCrOTi8UQ4HUBfIaWGtNfpxgqU25fPrjr5/aVV+9yM5XgIortu1ZOZvBa53oMv9jOvP7NUHRW9JeKyLhW3ppAvkCgYEAlOC6viG8DSarMSMRL4I5vm4tpO0lwuU0bGeAEy+fTme+Ww3Hkg2Bgz/e3+jfkYbwAkkR24XO4qJJeNF11Uq4ghA/1dCRrfGkB0XK7bNrsXsgyZeaU8Ku1vLG/6LVNPgSuoZTYyQAcSaQP+Ipze3Sz49nUD6Jsdjt2zlaeMCCQVs=
; 企油通平台公钥(一行 base64,用于验签其响应与回调)
PLATFORM_PUBLIC_KEY = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqYvOjWD+bFY9hXC70pN6OpplgIBFuE4rjLcw6pXdUI2igFWhG2xjfd2b0mmn2sD3gTCOaotODbxR5z5RrkIhsSeXXc2hOD+f8QLHdjZ1BWN9KO9Z906t9I2EHW5U2u8a/ZwIWYga3dgrSln756FP0cbCTkVIYiYSrU1YzUOjfFCAg8lFc5YSKirYrITC2A0iIUZzjba0Lip1wzwKGk8W8RByx124nO1j8LTlDZZ/+6Cri3Ricip9opBb9WATc8FaWi0bLvsxete6hOR1lX+RrRLPyLg/qdbeKeg55tAatXwoZKs96UHo4srjc4Wbd8yWVgs92jzsSi1wYX5vldvcmQIDAQAB
; 我方统一社会信用代码 / 营业执照编码
BUSINESS_LICENSE = 91450103MAE2729EXJ (1-1)
; 机构号:支付宝企业码通道 7.7 必填,由企油通分配
INSTITUTION_ID =
; 全平台唯一编号前缀(batch_no/waybill_no/waybill_no_code),正式 HM、测试建议 HMTEST
NO_PREFIX = HM
; 7.15 H5 免登落地页地址(测试:http://dev.paytaskpage.worknoya.vip/#/)
H5_BASE_URL = https://paytaskpage.worknoya.vip/#/
; 7.15 H5 免登用的 appId(可能与业务 appId 不同,需线下确认)
H5_APP_ID = 37257338026e7a377165454689773882
; 我方 7.10 消费回调地址(仅作记录,实际需在企油通后台配置)
CONSUME_NOTIFY_URL = http://47.104.73.7/qytconsume.php
; 业务接口签名字段拼接方式,待对接人确认后可改
SIGN_MODE = ksort_md5_sha1rsa
; 是否记录详细请求/响应日志到 runtime/storelog
LOG = true
|
||||
@@ -32,9 +32,6 @@ class Controller extends BaseController
|
||||
{
|
||||
// 当前商城ID
|
||||
protected $storeId;
|
||||
protected $latitude;
|
||||
protected $longitude;
|
||||
protected $province;
|
||||
|
||||
/**
|
||||
* API基类初始化
|
||||
@@ -44,12 +41,6 @@ class Controller extends BaseController
|
||||
{
|
||||
// 当前商城id
|
||||
$this->storeId = $this->getStoreId();
|
||||
$this->latitude = input('get.latitude');
|
||||
$this->longitude = input('get.longitude');
|
||||
$res = $this->httpCurl('https://apis.map.qq.com/ws/geocoder/v1/',['location'=>$this->latitude.','.$this->longitude,'key'=>'ETFBZ-F4XCW-YOQRI-RWBQM-BAZIQ-2VFS5']);
|
||||
if(isset($res['status']) && $res['status'] == 0){
|
||||
$this->province = $res['result']['address_component']['province'];
|
||||
}
|
||||
// 验证当前商城状态
|
||||
$this->checkStore();
|
||||
// 验证当前客户端状态
|
||||
|
||||
@@ -15,13 +15,9 @@ namespace app\api\controller;
|
||||
use app\api\controller\Controller;
|
||||
use app\api\model\partners\Order as OrderModel;
|
||||
use app\common\model\Partners as PartnersModel;
|
||||
use app\common\model\PartnersGoods as PartnersGoodsModel;
|
||||
use app\common\model\Goods as GoodsModel;
|
||||
use app\api\model\GoodsSku as GoodsSkuModel;
|
||||
use app\common\crypto\RsaUtil;
|
||||
use app\common\service\goods\source\Factory as StockFactory;
|
||||
use app\common\service\IdingjuOil;
|
||||
use app\store\model\Company as CompanyModel;
|
||||
use app\common\service\PartnersBalance;
|
||||
use app\common\service\QytOil;
|
||||
use app\store\model\order\QrCode as QrCodeModel;
|
||||
use cores\exception\BaseException;
|
||||
use think\facade\Request;
|
||||
@@ -83,10 +79,12 @@ class OilCard extends Controller
|
||||
// 业务处理
|
||||
$data = $result['data'];
|
||||
$orgNo = $data['orgNo'] ?? '';
|
||||
$goodsNo = $data['goodsNo'] ?? '';
|
||||
$amount = $data['amount'] ?? '';
|
||||
$mobile = $data['mobile'] ?? '';
|
||||
$saleOrderNo = $data['saleOrderNo'] ?? '';
|
||||
$oilCardType = $data['oilCardType'] ?? '';
|
||||
// 企油通:司机姓名(下单平台必传,用于运单油费下发)
|
||||
$driverName = trim((string)($data['name'] ?? ''));
|
||||
// 请求参数orgNo与请求头appKey不存在对应关系
|
||||
if($partners['orgNo'] != $orgNo){
|
||||
return $this->oilRenderError('12','0014');
|
||||
@@ -94,78 +92,80 @@ class OilCard extends Controller
|
||||
if(!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
|
||||
return $this->oilRenderError('12','0013', '', '手机号格式不正确');
|
||||
}
|
||||
// 销售平台订单号重复
|
||||
$order = OrderModel::detail(['partners_id' => $partners['partners_id'], 'partners_order_no' => $saleOrderNo]);
|
||||
if($order){
|
||||
return $this->oilRenderError('12','2023');
|
||||
if($driverName === ''){
|
||||
return $this->oilRenderError('12','0001', '', '缺少必填请求参数 name(司机姓名)');
|
||||
}
|
||||
// 未找到卡券对应的信息
|
||||
$goods = GoodsModel::detail(['goods_no' => $goodsNo, 'oilCardType' => $oilCardType]);
|
||||
if(!$goods){
|
||||
return $this->oilRenderError('12','2047');
|
||||
// 金额:由下单平台直接传入(单位:元,最多两位小数)
|
||||
if($amount === '' || !preg_match('/^\d{1,8}(\.\d{1,2})?$/', (string)$amount) || (float)$amount <= 0){
|
||||
return $this->oilRenderError('12','0013', '', 'amount 金额格式不正确(单位:元,最多两位小数且大于0)');
|
||||
}
|
||||
// 判断商品库存
|
||||
$detail = GoodsSkuModel::detail($goods['goods_id'], '0');
|
||||
if (1 > $detail['stock_num']) {
|
||||
return $this->oilRenderError('12','0013', '', "很抱歉,商品 [{$goods['goods_name']}] 平台库存不足");
|
||||
$amount = round((float)$amount, 2);
|
||||
// 销售平台订单号幂等:已存在则返回原订单结果(发放失败态除外)
|
||||
$exist = OrderModel::detail(['partners_id' => $partners['partners_id'], 'partners_order_no' => $saleOrderNo]);
|
||||
if($exist){
|
||||
if((int)$exist['oil_status_zsy'] === 3){
|
||||
return $this->oilRenderError('12','2023','','该销售订单号已提交且发放失败,请使用新订单号');
|
||||
}
|
||||
|
||||
$partnersGoods = PartnersGoodsModel::detail($partners['partners_id'], $goods['goods_id']);
|
||||
if(!$partnersGoods || $partnersGoods['stock_num'] <= 0){
|
||||
return $this->oilRenderError('01','2010');
|
||||
return $this->oilRenderSuccess([
|
||||
'oilCardNo' => $exist['oilCardNo'],
|
||||
'amount' => $exist['total_price'],
|
||||
]);
|
||||
}
|
||||
// 额度管控:先原子扣减合作商余额(余额不足直接拒单,防并发超扣)
|
||||
$balanceLogId = PartnersBalance::deduct((int)$partners['partners_id'], (float)$amount, $saleOrderNo, 0, (int)$this->storeId);
|
||||
if ($balanceLogId === false) {
|
||||
return $this->oilRenderError('01','2028', '', '合作商余额不足,请先充值');
|
||||
}
|
||||
$OrderModel = new OrderModel();
|
||||
$oilCardNo = 'OIL' . self::createOrderNo();
|
||||
if($OrderModel->saveOrder([
|
||||
'province' => $goods['province'],
|
||||
try {
|
||||
$created = $OrderModel->saveOrder([
|
||||
'mobile' => $mobile,
|
||||
'driver_name' => $driverName,
|
||||
'oilCardType' => $oilCardType,
|
||||
'oilCardNo' => $oilCardNo,
|
||||
'partners_order_no' => $saleOrderNo,
|
||||
'partners_id' => $partners['partners_id'],
|
||||
'goods_id' => $goods['goods_id'],
|
||||
'goods_name' => $goods['goods_name'],
|
||||
'goods_no' => $goods['goods_no'],
|
||||
'goods_price' => $goods['goods_price_min'],
|
||||
'goods_price' => $amount,
|
||||
'total_num' => 1,
|
||||
'total_price' => $goods['goods_price_min'],
|
||||
'total_pay_price' => $goods['goods_price_min'],
|
||||
'total_price' => $amount,
|
||||
'total_pay_price' => $amount,
|
||||
'store_id' => $this->storeId,
|
||||
])){
|
||||
// 更新商品库存 (针对下单减库存的商品)
|
||||
$this->updateGoodsStockNum([
|
||||
[
|
||||
'deduct_stock_type' => 10,
|
||||
'goods_id' => $goods['goods_id'],
|
||||
'goods_sku_id' => $detail['id'],
|
||||
'total_num' => 1,
|
||||
]
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// 建单失败 -> 回补刚扣减的余额
|
||||
PartnersBalance::refund((int)$partners['partners_id'], (float)$amount, $saleOrderNo, 0, (int)$this->storeId);
|
||||
// 并发下 (partners_id, partners_order_no) 唯一键冲突 -> 幂等返回已存在订单
|
||||
if (strpos($e->getMessage(), 'Duplicate') !== false) {
|
||||
$again = OrderModel::detail(['partners_id' => $partners['partners_id'], 'partners_order_no' => $saleOrderNo]);
|
||||
if ($again) {
|
||||
return $this->oilRenderSuccess(['oilCardNo' => $again['oilCardNo'], 'amount' => $again['total_price']]);
|
||||
}
|
||||
}
|
||||
$this->saveLog('share saveOrder 异常:' . $e->getMessage());
|
||||
return $this->oilRenderError('99', '9999');
|
||||
}
|
||||
if($created){
|
||||
// 回填流水的订单ID(建单前尚不知 order_id)
|
||||
PartnersBalance::bindOrder($balanceLogId, (int)$OrderModel->order_id);
|
||||
// 存入队列处理
|
||||
$queueService = new QueueService();
|
||||
$queueService->push('partners_queue', json_encode(['order_id'=>$OrderModel->order_id],320));
|
||||
|
||||
return $this->oilRenderSuccess([
|
||||
'oilCardNo' => $oilCardNo,
|
||||
'amount' => $goods['goods_price_min'],
|
||||
'amount' => $amount,
|
||||
]);
|
||||
}
|
||||
// 未建单成功 -> 回补余额
|
||||
PartnersBalance::refund((int)$partners['partners_id'], (float)$amount, $saleOrderNo, 0, (int)$this->storeId);
|
||||
return $this->oilRenderError('99', '9999');
|
||||
} else {
|
||||
// 错误处理
|
||||
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品库存 (针对下单减库存的商品)
|
||||
* @param $order
|
||||
* @return void
|
||||
*/
|
||||
private function updateGoodsStockNum($goodsList): void
|
||||
{
|
||||
StockFactory::getFactory(10)->updateGoodsStock($goodsList);
|
||||
}
|
||||
|
||||
public static function createOrderNo(): string
|
||||
{
|
||||
// 获取当前时间戳到毫秒(13位)
|
||||
@@ -177,36 +177,6 @@ class OilCard extends Controller
|
||||
return (string)($time . $rand); // 拼接成纯数字字符串
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $goodsNo
|
||||
* @return string
|
||||
*/
|
||||
public function getCompany($goodsNo): string
|
||||
{
|
||||
switch ($goodsNo) {
|
||||
case 'djgdface100':
|
||||
case 'djgdface200':
|
||||
case 'djgdface300':
|
||||
return 'umQZhIHKofyA';
|
||||
case 'jmgxyyface100':
|
||||
case 'jmgxyyface200':
|
||||
case 'jmgxyyface300':
|
||||
|
||||
case 'jmgzface100':
|
||||
case 'jmgzface200':
|
||||
case 'jmgzface300':
|
||||
|
||||
case 'jmfjface100':
|
||||
case 'jmfjface200':
|
||||
case 'jmfjface300':
|
||||
return 'HpWqXIgYvTBg';
|
||||
case 'face003':
|
||||
return 'NKJBgaaRNdiL'; // 测试参数
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款二维码申请
|
||||
* @return Json
|
||||
@@ -266,105 +236,22 @@ class OilCard extends Controller
|
||||
if(!$order) {
|
||||
return $this->oilRenderError('12','0013', '', '未找到对应订单');
|
||||
}
|
||||
$company = CompanyModel::detail(['orgNo' => $this->getCompany($order['goods_no'])]);
|
||||
if (!$company) {
|
||||
return $this->oilRenderError('12','0013', '', '没有可用参数:【' . $order['goods_no'] . '】');
|
||||
// 企油通:生成司机免登加油 H5 地址(7.15)。出参 qrCode 结构不变,值由二维码链接改为 H5 URL。
|
||||
$h5Url = (new QytOil())->h5Url($order['mobile']);
|
||||
if(!$h5Url){
|
||||
return $this->oilRenderError('12','0013', '', '生成加油链接失败');
|
||||
}
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->payQrCodeRequest(['order_no'=>$oilCardNo], $company);
|
||||
|
||||
if(isset($res['code']) && $res['code'] == '1' && isset($res['data']['useQrCodeUrl'])){
|
||||
// 插入支付码记录
|
||||
// 插入申请记录(留痕)
|
||||
$QrCodeModel = new QrCodeModel();
|
||||
$QrCodeModel->add([
|
||||
'oilCardNo'=>$order['oilCardNo'],
|
||||
'qrCode'=>$res['data']['useQrCodeUrl'],
|
||||
'qrCode'=>$h5Url,
|
||||
'amount'=>$order['goods_price'],
|
||||
'order_id'=>$order['order_id'],
|
||||
'user_id'=>0,
|
||||
'store_id'=>$order['store_id'],
|
||||
]);
|
||||
return $this->oilRenderSuccess([
|
||||
'qrCode'=>$res['data']['useQrCodeUrl']
|
||||
]);
|
||||
}else{
|
||||
return $this->oilRenderError('12','0013', '', $res['message'] ?? '');
|
||||
}
|
||||
} else {
|
||||
// 错误处理
|
||||
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 油券库存查询
|
||||
* @return Json
|
||||
* @throws BaseException
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function stock()
|
||||
{
|
||||
// 获取所有 HTTP 请求头
|
||||
$headers = Request::header();
|
||||
// 获取 JSON 格式的请求体
|
||||
$jsonData = Request::instance()->getContent();
|
||||
$data = json_decode($jsonData, true);
|
||||
$appKey = $headers['appkey'] ?? '';
|
||||
$requestId = $headers['requestid'] ?? '';
|
||||
$method = $headers['method'] ?? '';
|
||||
// 请求头METHOD参数不正确
|
||||
if($method != 'syb.oil.oilCard.stockList'){
|
||||
return $this->oilRenderError('12', '0005');
|
||||
}
|
||||
try {
|
||||
Db::name('request_log')->insert([
|
||||
'request_id' => $requestId,
|
||||
'app_key' => $appKey,
|
||||
'create_time' => time()
|
||||
]);
|
||||
} catch (\think\Exception $e) {
|
||||
// 判断是否唯一索引冲突
|
||||
if (strpos($e->getMessage(), 'Duplicate entry') !== false) {
|
||||
return $this->oilRenderError('12', '0012'); // 请求流水号重复
|
||||
}
|
||||
// 其他数据库异常
|
||||
return $this->oilRenderError('99', '9999'); // 未知错误
|
||||
}
|
||||
$partners = PartnersModel::detail(['appKey' => $appKey]);
|
||||
if(!$partners){
|
||||
return $this->oilRenderError('02','0004');
|
||||
}
|
||||
$crypto = new RsaUtil($partners);
|
||||
$result = $crypto->processResponse(['header'=>$headers,'encryptData'=>$data]);
|
||||
if ($result['code'] === '00') {
|
||||
// 业务处理
|
||||
$data = $result['data'];
|
||||
$orgNo = $data['orgNo'] ?? '';
|
||||
$goodsNo = $data['goodsNo'] ?? '';
|
||||
|
||||
// 请求参数orgNo与请求头appKey不存在对应关系
|
||||
if($partners['orgNo'] != $orgNo){
|
||||
return $this->oilRenderError('12','0014');
|
||||
}
|
||||
// 未找到卡券对应的信息
|
||||
$goods = GoodsModel::detail(['goods_no' => $goodsNo]);
|
||||
if(!$goods){
|
||||
return $this->oilRenderError('12','2047');
|
||||
}
|
||||
$partnersGoods = PartnersGoodsModel::detail($partners['partners_id'], $goods['goods_id']);
|
||||
if(!$partnersGoods){
|
||||
return $this->oilRenderError('01','2010');
|
||||
}
|
||||
$orderModel = new OrderModel();
|
||||
$sucNum = $orderModel->getCount(['partners_id' => $partners['partners_id'], 'goods_id' => $goods['goods_id']], 'all');
|
||||
$useNum = $orderModel->getCount(['partners_id' => $partners['partners_id'], 'goods_id' => $goods['goods_id']], 'used');
|
||||
return $this->oilRenderSuccess([
|
||||
'goodsNo'=>$goods['goods_no'], // 商品编号
|
||||
'canOrderNum'=>$partnersGoods['stock_num'], // 剩余可下单数量
|
||||
'unUseNum'=>floatval($sucNum) - floatval($useNum), // 未使用商品数量
|
||||
'useNum'=>$useNum, // 已使用商品数量
|
||||
]);
|
||||
return $this->oilRenderSuccess(['qrCode'=>$h5Url]);
|
||||
} else {
|
||||
// 错误处理
|
||||
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
|
||||
@@ -478,7 +365,6 @@ class OilCard extends Controller
|
||||
'shareNo' => $item['shareNo'],
|
||||
'mobile' => $item['mobile'],
|
||||
'oilCardNo' => $item['oilCardNo'],
|
||||
'productName' => $item['goods_name'],
|
||||
'num' => $item['total_num'],
|
||||
'amount' => $item['total_price'],
|
||||
'createTime' => $item['create_time'],
|
||||
@@ -561,13 +447,10 @@ class OilCard extends Controller
|
||||
$detail = OrderModel::detail(['oilCardNo' => $data['oilCardNo']]);
|
||||
// 组装返回格式
|
||||
$result = [
|
||||
'province' => $detail['province'],
|
||||
'mobile' => $detail['mobile'],
|
||||
'oilCardNo' => $detail['oilCardNo'],
|
||||
'shareNo' => $detail['shareNo'],
|
||||
'saleOrderNo' => $detail['partners_order_no'],
|
||||
'goods_name' => $detail['goods_name'],
|
||||
'goods_no' => $detail['goods_no'],
|
||||
'total_price' => $detail['total_price'],
|
||||
'oil_status_zsy' => $detail['oil_status_zsy'],
|
||||
'oil_status' => $detail['oil_status'],
|
||||
|
||||
@@ -309,36 +309,9 @@ class Order extends Controller
|
||||
*/
|
||||
public function qrCode(): Json
|
||||
{
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
$postData = $this->request->param();
|
||||
$postData['order_goods_id'] = $this->request->param('orderGoodsId');
|
||||
|
||||
$orderGoods = OrderGoodsModel::detail($postData['order_goods_id']);
|
||||
if($orderGoods['use_status'] != 0){
|
||||
return $this->renderError('油券已核销');
|
||||
}else {
|
||||
$company = CompanyModel::detail($orderGoods['company_id']);
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->payQrCodeRequest(['order_no'=>$orderGoods['oilCardNo']], $company);
|
||||
if($res['code'] == '1' && isset($res['data']['useQrCodeUrl'])){
|
||||
// 插入支付码记录
|
||||
$QrCodeModel = new QrCodeModel();
|
||||
$QrCodeModel->add([
|
||||
'oilCardNo'=>$orderGoods['oilCardNo'],
|
||||
'qrCode'=>$res['data']['useQrCodeUrl'],
|
||||
'amount'=>$orderGoods['goods_price'],
|
||||
'order_id'=>$orderGoods['order_id'],
|
||||
'user_id'=>$orderGoods['user_id'],
|
||||
'store_id'=>$orderGoods['store_id'],
|
||||
]);
|
||||
$res = [
|
||||
'qrCode'=>$res['data']['useQrCodeUrl']
|
||||
];
|
||||
return $this->renderSuccess($res, '提交成功');
|
||||
}else{
|
||||
return $this->renderError('平台创建用户失败【'.($res['errMessage'] ?? $res['message']).'】');
|
||||
}
|
||||
}
|
||||
// 企油通改造:小程序油品发放/核销链路已停用(上游定聚已下线)。
|
||||
// 保留接口避免小程序端报错,统一返回提示;如需恢复请改走 QytOil。
|
||||
return $this->renderError('该功能已停用');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,47 +321,9 @@ class Order extends Controller
|
||||
*/
|
||||
public function qrCodeImg(): Json
|
||||
{
|
||||
// $res = [
|
||||
// 'base64'=> 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAIAAAAP3aGbAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGwElEQVR4nO3cwY4bRxAFQdPY//9l+roQ4IULVoGVmoizwO0ZUok+vdf7/f4LoODvTx8A4L8SLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CAjK/tP/B6vbb/xKO83+/Rv99+/9PzTE3Pf+39PM3278ENC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsICM9T2sqe09nWuu7VVNz3Pt/NuunWfbtb0wNywgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMs7tYU1d2+up7yVdO//0+62ff9u19zPlhgVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhARn4Pi5/V96SunYfPcsMCMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIMMe1h9uuid1bT/r2nn4LDcsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjLye1j2j36va/tWdX6fv5cbFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZ5/awnraXtG36Pqf7Tdc+f9u18zyNGxaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGa/pPhF8t72HBd+5YQEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQ8fXpA/xf23tM08/fdu382+e59vnbrp3/2nncsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIWN/DuranM3Vtj+navtX25197n9d+n0/jhgVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAxuvavs+1faLt/ampa9/X1LX3OWVv67PcsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIWN/Detoe0PbzPu19TtXfz/ZeWP335oYFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQMbXpw/wq2t7QNuu7Q1t87w/u7ZPd40bFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZ63tY9T2jqWvPe21f7Nr7mdret7q2n3Xt+3LDAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCDjtb13s73H9DTX9ommru1zXTvP1LX/X9vP64YFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQMbXpw/wq/re09T2nlF972nq2j7U097/NjcsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjLO7WFNXds/eto+0dT0/Vzbk5qeZ/v3sH2ea8/rhgVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhARn4Pi5/V97nqe1LX1J/XDQvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADHtYf7hr+0fT80xNz3/teZ92/ik3LCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsIAMwQIy8ntY2/s7ddP3c23/aOra+et7Vde+XzcsIEOwgAzBAjIEC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjLO7WFN933gu2v7Tdf2uaaund8NC8gQLCBDsIAMwQIyBAvIECwgQ7CADMECMgQLyBAsIEOwgAzBAjIEC8gQLCBDsICM17X9HYB/44YFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWECGYAEZggVkCBaQIVhAhmABGYIFZAgWkCFYQIZgARmCBWQIFpAhWEDGP+OBJg1/1F6rAAAAAElFTkSuQmCC'
|
||||
//// 'base64'=> ''
|
||||
// ];
|
||||
// return $this->renderSuccess($res, '提交成功');
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
$postData = $this->request->param();
|
||||
$postData['order_goods_id'] = $this->request->param('orderGoodsId');
|
||||
|
||||
$orderGoods = OrderGoodsModel::detail($postData['order_goods_id']);
|
||||
if($orderGoods['use_status'] != 0){
|
||||
return $this->renderError('油券已核销');
|
||||
}else {
|
||||
/*$res = [
|
||||
'base64'=> $this->getBase64($orderGoods['qrCode'])
|
||||
];
|
||||
return $this->renderSuccess($res, '提交成功');*/
|
||||
$company = CompanyModel::detail($orderGoods['company_id']);
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->payQrCodeRequest(['order_no'=>$orderGoods['oilCardNo']], $company);
|
||||
//$res = $IdingjuOil->payQrCodeRequest(['oilCardNo'=>$orderGoods['oilCardNo'],'shareNo'=>$orderGoods['shareNo'],'mobile'=>$orderGoods['mobile'],'oilCardType'=>$orderGoods['oilCardType']], $company);
|
||||
//if($res['code'] == '00' && isset($res['data']['qrCode'])){
|
||||
if($res['code'] == '1' && isset($res['data']['useQrCodeUrl'])){
|
||||
// 插入支付码记录
|
||||
$QrCodeModel = new QrCodeModel();
|
||||
$QrCodeModel->add([
|
||||
'oilCardNo'=>$orderGoods['oilCardNo'],
|
||||
'qrCode'=>$res['data']['useQrCodeUrl'],
|
||||
'amount'=>$orderGoods['goods_price'],
|
||||
'order_id'=>$orderGoods['order_id'],
|
||||
'user_id'=>$orderGoods['user_id'],
|
||||
'store_id'=>$orderGoods['store_id'],
|
||||
]);
|
||||
$res = [
|
||||
'base64'=> $this->getBase64($res['data']['useQrCodeUrl'])
|
||||
];
|
||||
return $this->renderSuccess($res, '提交成功');
|
||||
}else{
|
||||
return $this->renderError('平台创建用户失败【'.($res['errMessage'] ?? $res['message']).'】');
|
||||
}
|
||||
}
|
||||
// 企油通改造:小程序油品发放/核销链路已停用(上游定聚已下线)。
|
||||
// 保留接口避免小程序端报错,统一返回提示;如需恢复请改走 QytOil。
|
||||
return $this->renderError('该功能已停用');
|
||||
}
|
||||
|
||||
public function getBase64($url){
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 企油通 · 回调接收
|
||||
// +----------------------------------------------------------------------
|
||||
// | 入口:public/qytconsume.php -> /qytNotify/consume
|
||||
// | 对应企油通 7.10「运单加油明细推送(异步)」,我方须返回 {"code":"100","msg":"Success"}
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\common\crypto\Qyt as QytCrypto;
|
||||
use app\common\service\QueueService;
|
||||
use app\common\service\QytOil;
|
||||
use think\facade\Request;
|
||||
|
||||
class QytNotify extends Controller
|
||||
{
|
||||
/**
|
||||
* 7.10 运单加油明细推送
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function consume()
|
||||
{
|
||||
$raw = Request::instance()->getContent();
|
||||
(new QytOil())->saveLog('7.10 消费回调原文:' . $raw);
|
||||
|
||||
$body = json_decode($raw, true);
|
||||
|
||||
// 兼容:外层信封 {appId,timestamp,sign,params(JSON字符串)} 或 直接推 body
|
||||
$params = $body;
|
||||
if (is_array($body) && isset($body['params'])) {
|
||||
$params = is_string($body['params']) ? json_decode($body['params'], true) : $body['params'];
|
||||
}
|
||||
|
||||
// TODO 验签(规则待对接人确认)
|
||||
// if (is_array($body) && !empty($body['sign'])) {
|
||||
// $crypto = new QytCrypto();
|
||||
// if (!$crypto->verify($params, $body['sign'])) {
|
||||
// return json(['code' => '99', 'msg' => '验签失败']);
|
||||
// }
|
||||
// }
|
||||
|
||||
// 无明细也回 100,避免企油通重复推送
|
||||
if (is_array($params) && !empty($params['order_list'])) {
|
||||
(new QueueService())->push('callback_queue', json_encode([
|
||||
'header' => ['method' => 'qyt_consume'],
|
||||
'res' => $params,
|
||||
], 320));
|
||||
} else {
|
||||
(new QytOil())->saveLog('7.10 消费回调无 order_list,已忽略');
|
||||
}
|
||||
|
||||
return json(['code' => '100', 'msg' => 'Success']);
|
||||
}
|
||||
}
|
||||
@@ -32,47 +32,9 @@ class Station extends Controller
|
||||
*/
|
||||
public function list(): Json
|
||||
{
|
||||
$SybOil = new SybOil();
|
||||
$company = CompanyModel::detail('2');
|
||||
$param = $this->request->param();
|
||||
$province = Db::name('area')->where(array(
|
||||
['name', '=', $param['province']],
|
||||
['level', '=', 1],
|
||||
))->find();
|
||||
$city = Db::name('area')->where(array(
|
||||
['name', '=', $param['city']],
|
||||
['pid', '=', $province['code']],
|
||||
['level', '=', 2],
|
||||
))->find();
|
||||
$goods = Db::name('goods')->where(array(
|
||||
['oilCardType', '=', 'zsy_ticket'],
|
||||
['province', '=', $param['province']],
|
||||
['status', '=', 10],
|
||||
))->order('stock_total', 'desc')
|
||||
->find();
|
||||
// 企油通改造:本功能依赖已下线的上游(智慧油客/定聚),现已停用。
|
||||
// 企油通无油站查询能力,返回空列表,避免小程序端报错。
|
||||
$list = [];
|
||||
if($goods) {
|
||||
// 对接平台接口
|
||||
$res = $SybOil->baseGasStationList(['goodsNo' => $goods['goods_no'], 'longitude' => $param['longitude'], 'latitude' => $param['latitude'], 'province' => $province['code'], 'city' => $city['code']], $company);
|
||||
if (isset($res['data']['zsyResp']['count']) && $res['data']['zsyResp']['count'] > 0) {
|
||||
$lists = $res['data']['zsyResp']['lists'];
|
||||
foreach ($lists as $k => $array) {
|
||||
$list[] = [
|
||||
'id' => $k + 1,
|
||||
'name' => $array['name'],
|
||||
'brand' => $array['brand'] == 1 ? '中国石油' : '中国BP',
|
||||
'latitude' => $array['lat'],
|
||||
'longitude' => $array['lng'],
|
||||
'address' => '',
|
||||
'distance' => $array['nearBy'],
|
||||
'width' => 30,
|
||||
'height' => 30,
|
||||
'iconPath' => '/static/marker.png',
|
||||
'stationCode' => $array['stationCode'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->renderSuccess(compact('list'));
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\api\model;
|
||||
|
||||
use app\common\model\PartnersGoods as PartnersGoodsModel;
|
||||
use app\common\library\helper;
|
||||
use cores\exception\BaseException;
|
||||
|
||||
/**
|
||||
* 用户优惠券模型
|
||||
* Class PartnersGoods
|
||||
* @package app\api\model
|
||||
*/
|
||||
class PartnersGoods extends PartnersGoodsModel
|
||||
{
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@ declare (strict_types=1);
|
||||
namespace app\api\model\partners;
|
||||
|
||||
use app\common\model\partners\Order as OrderModel;
|
||||
use app\api\model\PartnersGoods as PartnersGoodsModel;
|
||||
use app\common\library\helper;
|
||||
use cores\exception\BaseException;
|
||||
|
||||
@@ -32,14 +31,8 @@ class Order extends OrderModel
|
||||
*/
|
||||
public function saveOrder(array $data)
|
||||
{
|
||||
// 事务处理
|
||||
$this->transaction(function () use ($data) {
|
||||
// 写入订单记录
|
||||
// 企油通改造:下单改为按金额(amount)直传,不再挂商品与合作商商品库存
|
||||
$this->save($data);
|
||||
// 修改合作商商品库存
|
||||
PartnersGoodsModel::setIncUseNum(['partners_id' => $data['partners_id'], 'goods_id' => $data['goods_id']], 1);
|
||||
PartnersGoodsModel::setDecStockNum(['partners_id' => $data['partners_id'], 'goods_id' => $data['goods_id']], 1);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +255,11 @@ class PaySuccess extends BaseService
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
foreach ($order->goods as $goods) {
|
||||
/* @var GoodsModel $goods */
|
||||
// 企油通改造:小程序油品发放链路已停用,支付成功后不再触发上游分油(保留优惠券发放)。
|
||||
// 如需恢复小程序侧发放,改走 QytOil 并补齐司机三要素来源。
|
||||
if ($goods['oilCardType'] == 'zsy_ticket') {
|
||||
continue;
|
||||
}
|
||||
if($goods['oilCardType'] == 'zsy_ticket') {
|
||||
$data['amount'] = $goods['total_price']; // 金额
|
||||
$company = CompanyModel::detail(['orgNo' => $this->getCompany($goods['goods_no'])]);
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 企油通 · 签名 / 验签 / 请求信封
|
||||
// +----------------------------------------------------------------------
|
||||
// | 第二阶段 A-1 骨架。标 【TODO 待对接人确认】 处需按企油通实际规则微调。
|
||||
// |
|
||||
// | 三种签名场景(见《企油通接口对接文档.md》§2.1 / §2.4):
|
||||
// | 1. 业务信封:外层 { appId, timestamp, sign, params(JSON字符串) }
|
||||
// | 2. 7.15 H5 免登地址:ksort → http_build_query → urldecode → 大写MD5 → SHA1withRSA → base64
|
||||
// | 3. 7.16 / 7.17:必须真实 RSA 验签调用(本质同 1,但企油通侧强校验)
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\common\crypto;
|
||||
|
||||
class Qyt
|
||||
{
|
||||
/** @var string 我方私钥资源 */
|
||||
protected $privateKey;
|
||||
|
||||
/** @var string|false 企油通平台公钥资源 */
|
||||
protected $platformPublicKey;
|
||||
|
||||
/** @var array config('qyt') */
|
||||
protected $conf;
|
||||
|
||||
public function __construct(array $conf = null)
|
||||
{
|
||||
$this->conf = $conf ?: (array) config('qyt');
|
||||
$this->privateKey = $this->loadPrivateKey($this->conf['private_key'] ?? '');
|
||||
$this->platformPublicKey = $this->loadPublicKey($this->conf['platform_public_key'] ?? '');
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 1. 业务信封
|
||||
// ================================================================
|
||||
|
||||
/**
|
||||
* 构建业务请求信封
|
||||
* @param array $bizParams 业务参数(会被 json_encode 成字符串放进 params)
|
||||
* @return array{appId:string,timestamp:int,sign:string,params:string}
|
||||
*/
|
||||
public function envelope(array $bizParams): array
|
||||
{
|
||||
$appId = (string) ($this->conf['app_id'] ?? '');
|
||||
$timestamp = time();
|
||||
// ⚠️ params 必须是 JSON 字符串(转义),不是对象
|
||||
$paramsJson = json_encode($bizParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$sign = $this->bizSign([
|
||||
'appId' => $appId,
|
||||
'timestamp' => $timestamp,
|
||||
'params' => $paramsJson,
|
||||
]);
|
||||
|
||||
return [
|
||||
'appId' => $appId,
|
||||
'timestamp' => $timestamp,
|
||||
'sign' => $sign,
|
||||
'params' => $paramsJson,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务信封签名
|
||||
* 【TODO 待对接人确认】业务接口的具体拼签字段与顺序,文档 §2.4 只给了 7.15 的算法,
|
||||
* 业务接口写的是「密钥、公私钥与具体拼签字段请向对接人员索取」。
|
||||
* 当前默认实现:对参与字段 ksort 后 http_build_query → urldecode → 大写MD5 → SHA1withRSA → base64
|
||||
* (与 7.15 同族算法,落地时按实际规则替换本方法即可,调用方无需改动)
|
||||
*
|
||||
* @param array $fields 参与签名的字段(appId / timestamp / params)
|
||||
*/
|
||||
public function bizSign(array $fields): string
|
||||
{
|
||||
$mode = $this->conf['sign_mode'] ?? 'ksort_md5_sha1rsa';
|
||||
switch ($mode) {
|
||||
// 预留:'raw_concat_sha256rsa' 等其它模式
|
||||
case 'ksort_md5_sha1rsa':
|
||||
default:
|
||||
return $this->md5Sha1RsaSign($fields);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 2. 7.15 H5 免登地址
|
||||
// ================================================================
|
||||
|
||||
/**
|
||||
* 生成司机免登加油 H5 跳转地址(7.15)
|
||||
* @param string $mobile 司机手机号
|
||||
* @param string $creditcode 企业营业执照号;传空则不带(不参与签名)
|
||||
* @return string 完整可跳转 URL
|
||||
*/
|
||||
public function h5Url(string $mobile, string $creditcode = ''): string
|
||||
{
|
||||
$base = rtrim((string) ($this->conf['h5_base_url'] ?? ''), '/');
|
||||
$appId = (string) ($this->conf['h5_app_id'] ?: $this->conf['app_id']);
|
||||
$timestamp = date('YmdHis');
|
||||
|
||||
$params = [
|
||||
'appId' => $appId,
|
||||
'mobile' => $mobile,
|
||||
'timestamp' => $timestamp,
|
||||
];
|
||||
if ($creditcode !== '') {
|
||||
$params['creditcode'] = $creditcode; // 传了必须一并入签
|
||||
}
|
||||
|
||||
$params['sign'] = $this->md5Sha1RsaSign($params);
|
||||
|
||||
// 文档示例形如 https://paytaskpage.worknoya.vip/#/?appId=..&mobile=..×tamp=..&sign=..#/
|
||||
return $base . '/?' . http_build_query($params) . '#/';
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 3. 验签(企油通响应 / 回调)
|
||||
// ================================================================
|
||||
|
||||
/**
|
||||
* 验签企油通返回 / 回调报文
|
||||
* @param array $data 业务数据(通用响应里的 data,或回调 params)
|
||||
* @param string $sign 报文里的 sign
|
||||
* 【TODO 待对接人确认】验签串的构造(对 data 的 json 形态 / 是否含外层字段)
|
||||
*/
|
||||
public function verify($data, string $sign): bool
|
||||
{
|
||||
if ($sign === '' || $this->platformPublicKey === false) {
|
||||
return false;
|
||||
}
|
||||
$payload = is_string($data) ? $data : json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$ok = openssl_verify($payload, base64_decode($sign), $this->platformPublicKey, OPENSSL_ALGO_SHA256);
|
||||
return $ok === 1;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 内部:算法与密钥
|
||||
// ================================================================
|
||||
|
||||
/**
|
||||
* 同族签名算法:ksort → http_build_query → urldecode → 大写MD5 → SHA1withRSA → base64
|
||||
*/
|
||||
protected function md5Sha1RsaSign(array $params): string
|
||||
{
|
||||
ksort($params);
|
||||
$raw = urldecode(http_build_query($params));
|
||||
$md5Upper = strtoupper(md5($raw));
|
||||
$signature = '';
|
||||
openssl_sign($md5Upper, $signature, $this->privateKey, OPENSSL_ALGO_SHA1);
|
||||
return base64_encode($signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 载入私钥:支持 PEM 全文 / 去头尾的单行 base64
|
||||
* @return \OpenSSLAsymmetricKey|resource|string
|
||||
*/
|
||||
protected function loadPrivateKey(string $key)
|
||||
{
|
||||
if ($key === '') {
|
||||
return '';
|
||||
}
|
||||
if (strpos($key, '-----BEGIN') === false) {
|
||||
$key = "-----BEGIN PRIVATE KEY-----\n" . chunk_split(trim($key), 64, "\n") . "-----END PRIVATE KEY-----\n";
|
||||
}
|
||||
$res = openssl_pkey_get_private($key);
|
||||
return $res === false ? '' : $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 载入公钥:支持 PEM 全文 / 去头尾的单行 base64
|
||||
* @return \OpenSSLAsymmetricKey|resource|false
|
||||
*/
|
||||
protected function loadPublicKey(string $key)
|
||||
{
|
||||
if ($key === '') {
|
||||
return false;
|
||||
}
|
||||
if (strpos($key, '-----BEGIN') === false) {
|
||||
$key = "-----BEGIN PUBLIC KEY-----\n" . chunk_split(trim($key), 64, "\n") . "-----END PUBLIC KEY-----\n";
|
||||
}
|
||||
return openssl_pkey_get_public($key);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use cores\BaseModel;
|
||||
use app\common\library\helper;
|
||||
|
||||
/**
|
||||
* 合作商关联商品券模型
|
||||
* Class PartnersGoods
|
||||
* @package app\common\model
|
||||
*/
|
||||
class PartnersGoods extends BaseModel
|
||||
{
|
||||
// 定义表名
|
||||
protected $name = 'partners_goods';
|
||||
|
||||
// 定义主键
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 关联模型:商品
|
||||
* @return \think\model\relation\HasOne
|
||||
*/
|
||||
public function goods(): \think\model\relation\HasOne
|
||||
{
|
||||
return $this->hasOne('Goods', 'id', 'goods_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品信息详情
|
||||
* @param int $partnersId
|
||||
* @param int $goodsId
|
||||
* @return array|null|static
|
||||
*/
|
||||
public static function detail(int $partnersId, int $goodsId)
|
||||
{
|
||||
return static::get(['partners_id' => $partnersId, 'goods_id' => $goodsId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取合作商商品列表
|
||||
* @param int $partnersId 合作商ID
|
||||
* @return \think\Collection
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public static function getGoodsList(int $partnersId): \think\Collection
|
||||
{
|
||||
return (new static)->where('partners_id', '=', $partnersId)->order(['id' => 'asc'])->select();
|
||||
}
|
||||
|
||||
/**
|
||||
* 累计合作商使用数量
|
||||
* @param int|array $where
|
||||
* @param int $num
|
||||
* @return mixed
|
||||
*/
|
||||
public static function setIncUseNum($where, int $num)
|
||||
{
|
||||
return (new static)->setInc($where, 'use_num', $num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 减少合作商库存数量
|
||||
* @param int|array $where
|
||||
* @param int $num
|
||||
* @return mixed
|
||||
*/
|
||||
public static function setDecStockNum($where, int $num)
|
||||
{
|
||||
return (new static)->setDec($where, 'stock_num', $num);
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\common\model\partners;
|
||||
|
||||
use cores\BaseModel;
|
||||
|
||||
/**
|
||||
* 合作商库存变动记录
|
||||
* Class StockLog
|
||||
* @package app\common\model\partners
|
||||
*/
|
||||
class StockLog extends BaseModel
|
||||
{
|
||||
// 定义表名
|
||||
protected $name = 'partners_stock_log';
|
||||
|
||||
// 定义主键
|
||||
protected $pk = 'id';
|
||||
|
||||
protected $updateTime = false;
|
||||
|
||||
/**
|
||||
* 关联合作商记录表
|
||||
* @return \think\model\relation\BelongsTo
|
||||
*/
|
||||
public function partners()
|
||||
{
|
||||
$module = self::getCalledModule();
|
||||
return $this->belongsTo("app\\{$module}\\model\\Partners");
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增记录
|
||||
* @param array $data
|
||||
*/
|
||||
public static function add(array $data)
|
||||
{
|
||||
$model = new static;
|
||||
$model->save(array_merge([
|
||||
'store_id' => $model::$storeId
|
||||
], $data));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 合作商(下单平台)余额管控
|
||||
// +----------------------------------------------------------------------
|
||||
// | 企油通改造后,下单按金额直传,不再有商品/库存额度概念,
|
||||
// | 改由 yoshop_partners.balance 承担下单额度管控:
|
||||
// | 下单时原子扣减(余额不足直接拒单),发放失败/撤单时原路回补。
|
||||
// | 扣减用 UPDATE ... WHERE balance >= amount,天然防并发超扣。
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\enum\partners\balanceLog\Scene as SceneEnum;
|
||||
use think\facade\Db;
|
||||
|
||||
class PartnersBalance
|
||||
{
|
||||
/**
|
||||
* 原子扣减合作商余额(余额不足返回 false,不做任何变更)
|
||||
* @param int $partnersId 合作商ID
|
||||
* @param float $amount 扣减金额(元)
|
||||
* @param string $orderNo 业务单号(写入流水描述)
|
||||
* @param int $orderId 关联订单ID
|
||||
* @param int $storeId 商城ID
|
||||
* @return int|false 成功返回流水ID(供建单后回填 order_id),余额不足返回 false
|
||||
*/
|
||||
public static function deduct(int $partnersId, float $amount, string $orderNo, int $orderId = 0, int $storeId = 0)
|
||||
{
|
||||
if ($amount <= 0) {
|
||||
return false;
|
||||
}
|
||||
$affected = Db::name('partners')
|
||||
->where('partners_id', '=', $partnersId)
|
||||
->where('balance', '>=', $amount)
|
||||
->update(['balance' => Db::raw('`balance` - ' . self::money($amount))]);
|
||||
if (!$affected) {
|
||||
return false;
|
||||
}
|
||||
return self::log(SceneEnum::CONSUME, $partnersId, -$amount, $orderNo, $orderId, $storeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回填流水的关联订单ID
|
||||
*/
|
||||
public static function bindOrder($logId, int $orderId): void
|
||||
{
|
||||
if ($logId && $orderId) {
|
||||
Db::name('partners_balance_log')->where('log_id', '=', (int)$logId)->update(['order_id' => $orderId]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 回补合作商余额(发放失败 / 撤单)
|
||||
*/
|
||||
public static function refund(int $partnersId, float $amount, string $orderNo, int $orderId = 0, int $storeId = 0): void
|
||||
{
|
||||
if ($amount <= 0) {
|
||||
return;
|
||||
}
|
||||
Db::name('partners')
|
||||
->where('partners_id', '=', $partnersId)
|
||||
->update(['balance' => Db::raw('`balance` + ' . self::money($amount))]);
|
||||
self::log(SceneEnum::REFUND, $partnersId, $amount, $orderNo, $orderId, $storeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前余额
|
||||
*/
|
||||
public static function balance(int $partnersId): float
|
||||
{
|
||||
return (float) Db::name('partners')->where('partners_id', '=', $partnersId)->value('balance');
|
||||
}
|
||||
|
||||
/**
|
||||
* 写余额变动流水(失败不影响主流程),返回流水ID
|
||||
* @return int
|
||||
*/
|
||||
protected static function log(int $scene, int $partnersId, float $money, string $orderNo, int $orderId, int $storeId): int
|
||||
{
|
||||
try {
|
||||
return (int) Db::name('partners_balance_log')->insertGetId([
|
||||
'partners_id' => $partnersId,
|
||||
'scene' => $scene,
|
||||
'money' => round($money, 2),
|
||||
'describe' => vsprintf(SceneEnum::data()[$scene]['describe'], [$orderNo]),
|
||||
'remark' => '',
|
||||
'order_id' => $orderId,
|
||||
'store_id' => $storeId,
|
||||
'create_time' => time(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
log_record(['name' => '合作商余额流水写入失败', 'partners_id' => $partnersId, 'msg' => $e->getMessage()]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额安全格式化(仅允许数字与小数点,防拼接注入)
|
||||
*/
|
||||
protected static function money(float $amount): string
|
||||
{
|
||||
return number_format(round($amount, 2), 2, '.', '');
|
||||
}
|
||||
}
|
||||
@@ -44,19 +44,21 @@ class QueueService
|
||||
|
||||
/**
|
||||
* 检查延迟队列,将到期任务迁移到普通队列
|
||||
* 并发安全:先 zrem,只有「移除成功(返回>0)」的进程才把任务放进就绪队列,
|
||||
* 避免多个消费者同时迁移导致同一任务被投递多次。
|
||||
* @param string $queueName
|
||||
*/
|
||||
public function migrateDelayedToReady($queueName)
|
||||
{
|
||||
$now = time();
|
||||
// 获取到期任务
|
||||
$tasks = $this->redis->zrangebyscore($queueName . ':delayed', 0, $now);
|
||||
if (!empty($tasks)) {
|
||||
if (empty($tasks)) {
|
||||
return;
|
||||
}
|
||||
foreach ($tasks as $task) {
|
||||
// 放回普通队列
|
||||
// 先抢占式移除,再入队
|
||||
if ($this->redis->zrem($queueName . ':delayed', $task) > 0) {
|
||||
$this->push($queueName, $task);
|
||||
// 从延迟队列中移除
|
||||
$this->redis->zrem($queueName . ':delayed', $task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 企油通 · 上游接口客户端(支付宝企业码通道)
|
||||
// +----------------------------------------------------------------------
|
||||
// | 本次实际对接仅 3 个接口:
|
||||
// | 7.7 运单油费下发 createAndSendQuota —— 本类 createAndSendQuota()
|
||||
// | 7.15 H5 跳转地址 (本地签名生成 URL) —— 本类 h5Url()
|
||||
// | 7.10 运单加油明细推送(异步回调) —— app\api\controller\QytNotify
|
||||
// | 通道固定为支付宝企业码(passageway=1),司机手机号 + 姓名必填。
|
||||
// | 金额:对外「元」入参,7.7 内部换算为「分」。
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\crypto\Qyt as QytCrypto;
|
||||
|
||||
class QytOil extends BaseService
|
||||
{
|
||||
// 支付宝企业码通道
|
||||
const PASSAGEWAY_ALIPAY = 1;
|
||||
|
||||
/** @var array config('qyt') */
|
||||
protected $conf;
|
||||
|
||||
/** @var QytCrypto */
|
||||
protected $crypto;
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
$this->conf = (array) config('qyt');
|
||||
$this->crypto = new QytCrypto($this->conf);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 7.7 运单油费下发(一张订单 = 1 batch / 1 waybill / 1 employee)
|
||||
// ================================================================
|
||||
|
||||
/**
|
||||
* @param array $data ['batch_no','waybill_no','waybill_no_code','mobile','name','amount'(元)]
|
||||
* @return array 归一化 ['code'=>'00'|其它, 'data'=>[], 'message'=>'', 'dup_batch'=>bool]
|
||||
*/
|
||||
public function createAndSendQuota(array $data): array
|
||||
{
|
||||
$params = [
|
||||
'batch_no' => $data['batch_no'],
|
||||
'business_license' => $this->conf['business_license'],
|
||||
'passageway' => (string) self::PASSAGEWAY_ALIPAY,
|
||||
'institution_id' => $this->conf['institution_id'],
|
||||
'waybill_list' => [[
|
||||
'waybill_no' => $data['waybill_no'],
|
||||
'employee_list' => [[
|
||||
'mobile' => $data['mobile'],
|
||||
'name' => $data['name'],
|
||||
'quota_amount' => self::yuanToFen($data['amount']), // 分
|
||||
'voucher_name' => $this->conf['voucher_name'],
|
||||
'effective_start' => '', // 空=当日生效
|
||||
'effective_end' => '', // 空=长期有效
|
||||
'waybill_no_code' => $data['waybill_no_code'],
|
||||
]],
|
||||
]],
|
||||
];
|
||||
|
||||
return $this->post('/enterprise/api/zhyk/createAndSendQuota', $params);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 7.15 H5 免登加油地址(本地签名生成 URL,不发起接口请求)
|
||||
// ================================================================
|
||||
|
||||
public function h5Url(string $mobile): string
|
||||
{
|
||||
$creditcode = !empty($this->conf['h5_with_creditcode']) ? (string) $this->conf['business_license'] : '';
|
||||
return $this->crypto->h5Url($mobile, $creditcode);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 内部:统一请求
|
||||
// ================================================================
|
||||
|
||||
/**
|
||||
* @return array ['code' => '00'成功 | 其它, 'data' => array, 'message' => string, 'dup_batch' => bool, 'raw' => array]
|
||||
*/
|
||||
protected function post(string $path, array $bizParams): array
|
||||
{
|
||||
$url = rtrim((string) $this->conf['base_url'], '/') . $path;
|
||||
$body = $this->crypto->envelope($bizParams);
|
||||
|
||||
$this->saveLog("[请求] {$path} " . json_encode(['url' => $url, 'params' => $bizParams], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$resp = $this->curlPost($url, json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
$this->saveLog("[响应] {$path} " . $resp);
|
||||
|
||||
$json = json_decode($resp, true);
|
||||
if (!is_array($json)) {
|
||||
return ['code' => 'ERR', 'data' => [], 'message' => '响应解析失败', 'dup_batch' => false, 'raw' => ['body' => $resp]];
|
||||
}
|
||||
|
||||
// 通用响应结构:{ status: ok|error, data, message, serialNo, sign }
|
||||
$ok = ($json['status'] ?? '') === 'ok';
|
||||
// 【TODO 待对接人确认】是否所有响应都带 sign、验签串如何构造
|
||||
// if ($ok && !empty($json['sign'])) { $ok = $this->crypto->verify($json['data'] ?? [], $json['sign']); }
|
||||
|
||||
$message = (string) ($json['message'] ?? '');
|
||||
// 幂等:batch_no 已存在 —— 视为「已受理」,供 7.7 重试判定
|
||||
$dupBatch = false;
|
||||
if (!$ok && $message !== '') {
|
||||
foreach ((array) (config('qyt.dup_batch_hints') ?: ['已存在', '重复', 'duplicate', 'exist']) as $hint) {
|
||||
if (mb_stripos($message, $hint) !== false) {
|
||||
$dupBatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'code' => $ok ? '00' : 'ERR',
|
||||
'data' => $json['data'] ?? [],
|
||||
'message' => $message,
|
||||
'dup_batch' => $dupBatch,
|
||||
'raw' => $json,
|
||||
];
|
||||
}
|
||||
|
||||
protected function curlPost(string $url, string $jsonBody): string
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $jsonBody,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => (int) ($this->conf['timeout'] ?? 15),
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_SSL_VERIFYHOST => false,
|
||||
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Charset: UTF-8'],
|
||||
]);
|
||||
$resp = curl_exec($ch);
|
||||
if ($resp === false) {
|
||||
$err = curl_error($ch);
|
||||
curl_close($ch);
|
||||
return json_encode(['status' => 'error', 'message' => 'cURL: ' . $err], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
curl_close($ch);
|
||||
return (string) $resp;
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 工具
|
||||
// ================================================================
|
||||
|
||||
/** 元 → 分 */
|
||||
public static function yuanToFen($yuan): int
|
||||
{
|
||||
return (int) bcmul((string) $yuan, '100', 0);
|
||||
}
|
||||
|
||||
/** 分 → 元(字符串,保留 2 位) */
|
||||
public static function fenToYuan($fen): string
|
||||
{
|
||||
return bcdiv((string) (int) $fen, '100', 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成企油通全平台唯一编号(加企业前缀),确定性派生 -> 重试保持一致
|
||||
* @param string $type B=batch / W=waybill / C=waybill_no_code
|
||||
* @param string $seed 订单号 / order_id 等业务种子
|
||||
*/
|
||||
public static function genNo(string $type, string $seed): string
|
||||
{
|
||||
$prefix = (string) (config('qyt.no_prefix') ?: 'HM');
|
||||
return $prefix . $type . $seed;
|
||||
}
|
||||
|
||||
/** 记录日志到 runtime/storelog */
|
||||
public function saveLog($data): void
|
||||
{
|
||||
if (empty($this->conf['log'])) {
|
||||
return;
|
||||
}
|
||||
$dir = runtime_path('storelog/') . date('Ym') . '/' . date('Ymd');
|
||||
is_dir($dir) || @mkdir($dir, 0777, true);
|
||||
@file_put_contents(
|
||||
$dir . '/qyt_' . date('YmdH') . '.txt',
|
||||
date('Y-m-d H:i:s ') . (is_string($data) ? $data : json_encode($data, JSON_UNESCAPED_UNICODE)) . "\r\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -330,6 +330,70 @@ class CallbackQueue extends Command
|
||||
// $SybOil->saveLogStore('重新加入队列:【'.$message.'】');
|
||||
}
|
||||
break;
|
||||
case "qyt_consume":
|
||||
// 企油通 7.10 运单加油明细推送(一次可能多条;企油通可能重推 -> 全流程幂等)
|
||||
foreach ((array)($res['order_list'] ?? []) as $c) {
|
||||
$code = $c['waybill_no_code'] ?? '';
|
||||
$order = Db::name('partners_order')->where('waybill_no_code', $code)->find();
|
||||
if (!$order) {
|
||||
$SybOil->saveLogStore('企油通消费回调未匹配订单:' . json_encode($c, 320));
|
||||
continue;
|
||||
}
|
||||
$payTime = !empty($c['pay_time']) ? (strtotime($c['pay_time']) ?: time()) : time();
|
||||
// 落消费流水(uk_consume 去重:重复回调直接忽略)
|
||||
try {
|
||||
Db::name('qyt_consume')->insert([
|
||||
'order_id' => $order['order_id'],
|
||||
'waybill_no' => $c['waybill_no'] ?? '',
|
||||
'waybill_no_code' => $code,
|
||||
'order_code' => $c['order_code'] ?? '',
|
||||
'station_code' => $c['station_code'] ?? '',
|
||||
'station_name' => $c['station_name'] ?? '',
|
||||
'oil_name' => $c['oil_name'] ?? '',
|
||||
'litter' => $c['litter'] ?? '',
|
||||
'oil_price' => (int)($c['oil_price'] ?? 0),
|
||||
'actual_oil_price' => (int)($c['actual_oil_price'] ?? 0),
|
||||
'pay_fee' => (int)($c['pay_fee'] ?? 0),
|
||||
'consume_amount' => (int)($c['consume_amount'] ?? 0),
|
||||
'pay_time' => $payTime,
|
||||
'raw' => json_encode($c, 320),
|
||||
'store_id' => $order['store_id'],
|
||||
'create_time' => time(),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
if (strpos($e->getMessage(), 'Duplicate') === false) {
|
||||
throw $e;
|
||||
}
|
||||
$SybOil->saveLogStore('企油通消费回调重复,忽略流水:' . $code . '/' . ($c['order_code'] ?? ''));
|
||||
}
|
||||
// 条件跃迁 use_status 0 -> 1(要求已发放),仅胜出者通知下单平台
|
||||
$affected = Db::name('partners_order')->where('order_id', $order['order_id'])
|
||||
->where('use_status', 0)
|
||||
->where('oil_status', 1)
|
||||
->update([
|
||||
'use_status' => 1,
|
||||
'use_time' => time(),
|
||||
'use_text' => '加油',
|
||||
'qyt_order_code' => $c['order_code'] ?? '',
|
||||
'shareNo' => $c['order_code'] ?: $order['shareNo'],
|
||||
'station_name' => $c['station_name'] ?? '',
|
||||
'oil_name' => $c['oil_name'] ?? '',
|
||||
'litter' => $c['litter'] ?? '',
|
||||
'pay_fee' => (int)($c['pay_fee'] ?? 0),
|
||||
'consume_time' => $payTime,
|
||||
'update_time' => time(),
|
||||
]);
|
||||
if ($affected) {
|
||||
$queueService = new QueueService();
|
||||
$queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $order['order_id'],
|
||||
'optType' => 'add_oil',
|
||||
'retry_count' => 0,
|
||||
], 320));
|
||||
$SybOil->saveLogStore('企油通消费回调处理成功:' . json_encode($c, 320));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$SybOil->saveLogStore('队列数据处理异常,未知:【'.$message.'】');
|
||||
}
|
||||
|
||||
@@ -1,36 +1,54 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 下单平台订单 -> 企油通「运单油费下发」(7.7)
|
||||
// +----------------------------------------------------------------------
|
||||
// | OilCard::share 创建 yoshop_partners_order 后 push 'partners_queue',本命令消费:
|
||||
// | 1. 每个 order_id 用 RedisLock 串行化,锁内重读订单状态
|
||||
// | 2. 生成企油通全平台唯一编号(确定性派生,可安全重试)
|
||||
// | 3. 调 7.7 createAndSendQuota;支付宝企业码通道下「受理成功即完成发放」
|
||||
// | 4. 发放成功 -> oil_status=1 / oil_status_zsy=2,投 notify_queue 回调下单平台
|
||||
// |
|
||||
// | 并发/原子性:
|
||||
// | · oil_status_zsy 只在 7.7 结果确定后离开 0;空闲时 reconcile() 补投丢失的队列消息
|
||||
// | · 状态跃迁为条件 UPDATE(... WHERE oil_status_zsy=0),affected=1 才回调,天然幂等
|
||||
// | · batch_no 确定性派生 -> 崩溃重试用同一值,依赖企油通按 batch_no 幂等去重
|
||||
// | 启动:php think partners:queue(可多进程;RedisLock 保证同一订单串行)
|
||||
// +----------------------------------------------------------------------
|
||||
namespace app\console\command;
|
||||
|
||||
use app\common\service\IdingjuOil;
|
||||
use app\common\lock\RedisLock;
|
||||
use app\common\model\partners\Order as OrderModel;
|
||||
use app\common\service\PartnersBalance;
|
||||
use app\common\service\QueueService;
|
||||
use app\store\model\Company as CompanyModel;
|
||||
use app\common\service\QytOil;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use app\common\model\partners\Order as OrderModel;
|
||||
use think\facade\Db;
|
||||
|
||||
class PartnersQueue extends Command
|
||||
{
|
||||
/** @var QueueService */
|
||||
protected $queueService;
|
||||
|
||||
/** @var int 上次兜底巡检时间 */
|
||||
protected $lastReconcile = 0;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('partners:queue')
|
||||
->setDescription('Process messages from the Redis queue');
|
||||
->setDescription('下单平台订单 -> 企油通运单油费下发(7.7)');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$this->queueService = new QueueService();
|
||||
|
||||
while (true) {
|
||||
$message = $this->queueService->pop('partners_queue');
|
||||
if ($message) {
|
||||
// 处理消息
|
||||
$this->processMessage($message);
|
||||
} else {
|
||||
// 暂停一段时间再检查队列
|
||||
$this->reconcile();
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
@@ -38,103 +56,157 @@ class PartnersQueue extends Command
|
||||
|
||||
protected function processMessage($message)
|
||||
{
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
$IdingjuOil->saveLogStore('partners_queue队列数据处理:【'.$message.'】');
|
||||
// 拿到队列数据处理
|
||||
$data = json_decode($message, true);
|
||||
// 检查解码是否成功
|
||||
if ($data === false) {
|
||||
$IdingjuOil->saveLogStore('partners_queue队列数据解码失败:' . json_last_error_msg());
|
||||
$qyt = new QytOil();
|
||||
$data = is_array($message) ? $message : json_decode($message, true);
|
||||
$orderId = $data['order_id'] ?? null;
|
||||
if (!$orderId) {
|
||||
$qyt->saveLog('partners_queue 消息缺少 order_id:' . json_encode($message, 320));
|
||||
return;
|
||||
}
|
||||
$order = OrderModel::detail($data['order_id']);
|
||||
if (!$order) {
|
||||
$IdingjuOil->saveLogStore('未找到对应订单:【' . $data['order_id'] . '】');
|
||||
|
||||
// 每个订单串行处理;锁 60s 自动过期,崩溃不会死锁
|
||||
$lock = new RedisLock('qyt:send:' . $orderId, 60);
|
||||
if (!$lock->acquireLock()) {
|
||||
$qyt->saveLog("partners_queue 订单处理中,跳过 order={$orderId}");
|
||||
return;
|
||||
}
|
||||
// 此处可以根据业务逻辑处理接收到的数据
|
||||
|
||||
try {
|
||||
if($order['order_status'] == 10 && $order['oil_status'] == 0 && $order['oilCardType'] == 'zsy_ticket'){
|
||||
$data['amount'] = $order['total_price']; // 金额
|
||||
$company = CompanyModel::detail(['orgNo' => $this->getCompany($order['goods_no'])]);
|
||||
if (!$company) {
|
||||
$IdingjuOil->saveLogStore('没有可用参数:【' . $order['goods_no'] . '】');
|
||||
$order = OrderModel::detail($orderId);
|
||||
if (!$order) {
|
||||
$qyt->saveLog('partners_queue 未找到订单:' . $orderId);
|
||||
return;
|
||||
}
|
||||
if ($order['order_status'] != 10 || $order['oil_status'] != 0 || (int) $order['oil_status_zsy'] !== 0) {
|
||||
$qyt->saveLog("partners_queue 订单状态不满足下发条件 order={$orderId}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->oilOilCardShare([
|
||||
'goodsNo'=>$order['goods_no'],
|
||||
'amount'=>$data['amount'],
|
||||
'userNo'=>'',
|
||||
'mobile'=>$order['mobile'],
|
||||
'saleOrderNo'=>$order['oilCardNo'],
|
||||
'oilCardType'=>$order['oilCardType'],
|
||||
'notify_url'=>config('app.base_url') . 'partnersoil.php',
|
||||
'use_notify_url'=>config('app.base_url') . 'partnersoiluse.php'
|
||||
], $company);
|
||||
|
||||
if ($res['code'] != 1) {
|
||||
$IdingjuOil->saveLogStore(($res['errMessage'] ?? $res['message']));
|
||||
// 1. 确定性派生编号(含企业前缀),重试时保持一致
|
||||
$seed = $order['partners_order_no'] ?: (string) $order['order_id'];
|
||||
$batchNo = QytOil::genNo('B', $seed);
|
||||
$waybillNo = QytOil::genNo('W', $seed);
|
||||
$waybillNoCode = QytOil::genNo('C', $seed);
|
||||
$name = trim((string) $order['driver_name']);
|
||||
if ($name === '' || $order['mobile'] === '') {
|
||||
$failed = Db::name('partners_order')->where('order_id', $orderId)->where('oil_status_zsy', 0)
|
||||
->update(['oil_status_zsy' => 3, 'oil_text' => '缺司机姓名/手机号,无法发放', 'update_time' => time()]);
|
||||
$failed && $this->refundBalance($order);
|
||||
return;
|
||||
}
|
||||
$item['shareNo'] = $res['data']['trade_no'] ?? '';
|
||||
$item['qrCode'] = $res['data']['useUrl'] ?? '';
|
||||
$item['oil_status_zsy'] = $res['data']['state'] ?? 0;
|
||||
$item['oil_time'] = time();
|
||||
$item['oil_status'] = $item['oil_status_zsy'] == 2 ? 1 : 0; // 已发券 为1
|
||||
$resUpdate = $order->save($item);
|
||||
if (!$resUpdate) {
|
||||
$IdingjuOil->saveLogStore("订单更新失败,order_id: {$data['order_id']}");
|
||||
|
||||
// 2. 先落编号(状态不动,仍为 0)
|
||||
Db::name('partners_order')->where('order_id', $orderId)->update([
|
||||
'batch_no' => $batchNo,
|
||||
'waybill_no' => $waybillNo,
|
||||
'waybill_no_code' => $waybillNoCode,
|
||||
'oil_text' => '发放中',
|
||||
'update_time' => time(),
|
||||
]);
|
||||
|
||||
// 3. 7.7 运单油费下发
|
||||
$res = $qyt->createAndSendQuota([
|
||||
'batch_no' => $batchNo,
|
||||
'waybill_no' => $waybillNo,
|
||||
'waybill_no_code' => $waybillNoCode,
|
||||
'mobile' => $order['mobile'],
|
||||
'name' => $name,
|
||||
'amount' => $order['total_price'],
|
||||
]);
|
||||
|
||||
// 失败(且非 batch 已存在)
|
||||
if ($res['code'] !== '00' && empty($res['dup_batch'])) {
|
||||
$failed = Db::name('partners_order')->where('order_id', $orderId)->where('oil_status_zsy', 0)->update([
|
||||
'oil_status_zsy' => 3,
|
||||
'oil_text' => '下发失败:' . $res['message'],
|
||||
'update_time' => time(),
|
||||
]);
|
||||
$failed && $this->refundBalance($order);
|
||||
$qyt->saveLog("7.7 下发失败 order={$orderId}:" . $res['message']);
|
||||
return;
|
||||
}
|
||||
if($item['oil_status_zsy'] == 2) {
|
||||
// 存入队列处理
|
||||
$queueService = new QueueService();
|
||||
$queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $order['order_id'],
|
||||
// data.status: 1 成功 / 2 失败(dup_batch 视为已受理成功)
|
||||
$status = empty($res['dup_batch']) ? (string) ($res['data']['status'] ?? '1') : '1';
|
||||
if ($status === '2') {
|
||||
$failed = Db::name('partners_order')->where('order_id', $orderId)->where('oil_status_zsy', 0)->update([
|
||||
'oil_status_zsy' => 3,
|
||||
'oil_text' => $res['data']['msg'] ?? '下发失败',
|
||||
'update_time' => time(),
|
||||
]);
|
||||
$failed && $this->refundBalance($order);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 受理成功 = 发放成功(支付宝企业码通道);条件跃迁 0 -> 2,胜出者回调下单平台
|
||||
$affected = Db::name('partners_order')->where('order_id', $orderId)->where('oil_status_zsy', 0)->update([
|
||||
'oil_status' => 1,
|
||||
'oil_status_zsy' => 2,
|
||||
'oil_time' => time(),
|
||||
'shareNo' => $waybillNoCode,
|
||||
'oil_text' => $res['data']['msg'] ?? '发放成功',
|
||||
'update_time' => time(),
|
||||
]);
|
||||
if ($affected) {
|
||||
$this->queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $orderId,
|
||||
'type' => 'add',
|
||||
'optType' => 'share_oil',
|
||||
'retry_count' => 0,
|
||||
], 320));
|
||||
$qyt->saveLog("7.7 发放成功 order={$orderId} batch_no={$batchNo}"
|
||||
. (empty($res['dup_batch']) ? '' : '(batch 已存在,按已发放处理)'));
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$IdingjuOil->saveLogStore(
|
||||
'partners_queue队列处理异常:' . $e->getMessage() .
|
||||
' 在文件:' . $e->getFile() .
|
||||
' 第:' . $e->getLine() .
|
||||
' 行。堆栈跟踪:' . $e->getTraceAsString()
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
// 不改状态(仍为 0),交由 reconcile 兜底重投
|
||||
$qyt->saveLog('partners_queue 异常 order=' . $orderId . ':' . $e->getMessage()
|
||||
. ' @ ' . $e->getFile() . ':' . $e->getLine());
|
||||
} finally {
|
||||
$lock->releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $goodsNo
|
||||
* @return string
|
||||
* 发放失败 -> 回补合作商余额(仅在状态跃迁胜出时调用,天然幂等)
|
||||
*/
|
||||
public function getCompany($goodsNo): string
|
||||
protected function refundBalance($order)
|
||||
{
|
||||
switch ($goodsNo) {
|
||||
case 'djgdface100':
|
||||
case 'djgdface200':
|
||||
case 'djgdface300':
|
||||
return 'umQZhIHKofyA';
|
||||
case 'jmgxyyface100':
|
||||
case 'jmgxyyface200':
|
||||
case 'jmgxyyface300':
|
||||
PartnersBalance::refund(
|
||||
(int) $order['partners_id'],
|
||||
(float) $order['total_price'],
|
||||
(string) $order['partners_order_no'],
|
||||
(int) $order['order_id'],
|
||||
(int) $order['store_id']
|
||||
);
|
||||
(new QytOil())->saveLog("发放失败已回补合作商余额 order={$order['order_id']} amount={$order['total_price']}");
|
||||
}
|
||||
|
||||
case 'jmgzface100':
|
||||
case 'jmgzface200':
|
||||
case 'jmgzface300':
|
||||
|
||||
case 'jmfjface100':
|
||||
case 'jmfjface200':
|
||||
case 'jmfjface300':
|
||||
return 'HpWqXIgYvTBg';
|
||||
case 'face003':
|
||||
return 'NKJBgaaRNdiL'; // 测试参数
|
||||
default:
|
||||
return '';
|
||||
/**
|
||||
* 兜底巡检(限频 60s):补投丢失的 partners_queue 消息。
|
||||
* 因下发为条件跃迁,重复投递安全。
|
||||
*/
|
||||
protected function reconcile()
|
||||
{
|
||||
if (time() - $this->lastReconcile < 60) {
|
||||
return;
|
||||
}
|
||||
$this->lastReconcile = time();
|
||||
$now = time();
|
||||
try {
|
||||
$ids = Db::name('partners_order')
|
||||
->where('order_status', 10)
|
||||
->where('oil_status_zsy', 0)
|
||||
->where('oilCardType', 'zsy_ticket')
|
||||
->where('create_time', '<', $now - 120)
|
||||
->where('create_time', '>', $now - 86400)
|
||||
->limit(200)->column('order_id');
|
||||
foreach ($ids as $oid) {
|
||||
$this->queueService->push('partners_queue', json_encode(['order_id' => $oid], 320));
|
||||
}
|
||||
if ($ids) {
|
||||
(new QytOil())->saveLog('partners_queue reconcile 补投 ' . count($ids) . ' 单');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
(new QytOil())->saveLog('partners_queue reconcile 异常:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,48 +224,8 @@ class Company extends Controller
|
||||
*/
|
||||
public function stock(): Json
|
||||
{
|
||||
$arr = $this->postData();
|
||||
// 商品详情
|
||||
foreach ((array)$arr as $company_id) {
|
||||
$company = CompanyModel::detail($company_id);
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
$goodsNo = $this->getGoodsNo($company['orgNo']);
|
||||
$goodsList = GoodsModel::getAll([['goods_no','in',$goodsNo]]);
|
||||
$canOrderNum = $unUseNum = $useNum = 0;
|
||||
foreach ($goodsList as $array){
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->stockList(['goodsNo' => $array['goods_no']], $company);
|
||||
// 更新记录
|
||||
if ($res['code'] == '1') {
|
||||
/*$res['data']['canOrderNum'] = $res['data']['canOrderNum']?:0;
|
||||
$res['data']['unUseNum'] = $res['data']['unUseNum']?:0;
|
||||
$res['data']['useNum'] = $res['data']['useNum']?:0;
|
||||
$canOrderNum += $res['data']['canOrderNum'];
|
||||
$unUseNum += $res['data']['unUseNum'];
|
||||
$useNum += $res['data']['useNum'];
|
||||
Db::name('goods')
|
||||
->where('goods_id', $array['goods_id'])
|
||||
->update(['stock_total' => $res['data']['canOrderNum'], 'unUseNum' => $res['data']['unUseNum'], 'useNum' => $res['data']['useNum']]);
|
||||
|
||||
Db::name('goods_sku')
|
||||
->where('goods_id', $array['goods_id'])
|
||||
->update(['stock_num' => $res['data']['canOrderNum'], 'unUseNum' => $res['data']['unUseNum'], 'useNum' => $res['data']['useNum']]);
|
||||
*/
|
||||
$res['data']['quantity'] = $res['data']['quantity']?:0;
|
||||
$canOrderNum += $res['data']['quantity'];
|
||||
Db::name('goods')
|
||||
->where('goods_id', $array['goods_id'])
|
||||
->update(['stock_total' => $res['data']['quantity']]);
|
||||
|
||||
Db::name('goods_sku')
|
||||
->where('goods_id', $array['goods_id'])
|
||||
->update(['stock_num' => $res['data']['quantity']]);
|
||||
}
|
||||
}
|
||||
$company->save(['canOrderNum'=>$canOrderNum,'unUseNum'=>$unUseNum,'useNum'=>$useNum]);
|
||||
|
||||
}
|
||||
return $this->renderSuccess($arr);
|
||||
// 企油通改造:本功能依赖已下线的上游(智慧油客/定聚),现已停用。
|
||||
return $this->renderError('上游库存同步已停用(企油通无油券库存概念)');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -183,17 +183,8 @@ class Goods extends Controller
|
||||
*/
|
||||
public function onReloadStock(int $goodsId): Json
|
||||
{
|
||||
// 商品详情
|
||||
$model = GoodsModel::detail($goodsId);
|
||||
$company = CompanyModel::detail(['status'=>10]);
|
||||
$SybOil = new SybOil();
|
||||
// 对接平台接口
|
||||
$res = $SybOil->stockList(['goodsNo' => $model['goods_no']], $company);
|
||||
// 更新记录
|
||||
if ($res['code'] == '00') {
|
||||
return $this->renderSuccess($res['data']);
|
||||
}
|
||||
return $this->renderError($model->getError() ?: $res['errMessage']);
|
||||
// 企油通改造:上游库存同步已停用(企油通无油券库存概念,库存改为平台内部维护)。
|
||||
return $this->renderError('上游库存同步已停用,请直接在「合作商」中维护可下单额度');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -153,47 +153,8 @@ class Order extends Controller
|
||||
*/
|
||||
public function cancelShare(): Json
|
||||
{
|
||||
$postData = $this->postForm();
|
||||
$postData['order_goods_id'] = $this->request->param('orderGoodsId');
|
||||
$order_goods_id = $postData['order_goods_id'];
|
||||
$password = $postData['password'];
|
||||
//验证密码
|
||||
$user = UserModel::detail($this->store['user']['store_user_id']);
|
||||
if(!password_verify($password, $user['password'])){
|
||||
return $this->renderError('登录密码错误');
|
||||
}
|
||||
$model = OrderGoodsModel::detail($order_goods_id);
|
||||
if ($model['oil_status'] != 1) {
|
||||
return $this->renderError('该订单状态不是已分油状态');
|
||||
}
|
||||
if ($model['use_status'] != 0) {
|
||||
return $this->renderError('油卡已核销,无法撤销');
|
||||
}
|
||||
$order = OrderModel::detail($model['order_id']);
|
||||
$company = CompanyModel::detail($model['company_id']);
|
||||
// 对接平台接口,撤销分油
|
||||
$res = $this->oilOilCardCancelShare(['shareNo'=>$model['shareNo'],'amount'=>$model['goods_price'],'saleOrderNo'=>$order['order_no'],'type'=>'recovery','oilCardType'=>$model['oilCardType']], $company);
|
||||
if($res['code'] == '00'){
|
||||
if ($model->cancelShare($postData)) {
|
||||
// 更新商户余额(增加)
|
||||
MerchantModel::setIncBalance((int)$model['merchant_id'], (float)$model['goods_price']);
|
||||
BalanceLogModel::add(SceneEnum::REFUND, [
|
||||
'merchant_id' => (int)$model['merchant_id'],
|
||||
'money' => (float)$model['goods_price'],
|
||||
], ['saleOrderNo' => $order['order_no']]);
|
||||
// 更新公司余额(增加)
|
||||
CompanyModel::setIncBalance((int)$model['company_id'], (float)$model['goods_price']);
|
||||
CompanyBalanceLogModel::add(SceneEnum::REFUND, [
|
||||
'company_id' => (int)$model['company_id'],
|
||||
'money' => (float)$model['goods_price'],
|
||||
], ['saleOrderNo' => $order['order_no']]);
|
||||
return $this->renderSuccess('操作成功');
|
||||
}
|
||||
return $this->renderError($model->getError() ?: '操作失败');
|
||||
}else{
|
||||
return $this->renderError('平台撤销分油失败【'.($res['errMessage'] ?? $res['message']).'】');
|
||||
}
|
||||
|
||||
// 企油通改造:本功能依赖已下线的上游(智慧油客/定聚),现已停用。
|
||||
return $this->renderError('小程序油品链路已停用');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,36 +164,8 @@ class Order extends Controller
|
||||
*/
|
||||
public function qrCode(): Json
|
||||
{
|
||||
$postData = $this->postForm();
|
||||
$postData['order_goods_id'] = $this->request->param('orderGoodsId');
|
||||
|
||||
$orderGoods = OrderGoodsModel::detail($postData['order_goods_id']);
|
||||
if($orderGoods['use_status'] != 0){
|
||||
return $this->renderError('油券已核销');
|
||||
}else {
|
||||
$company = CompanyModel::detail($orderGoods['company_id']);
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->payQrCodeRequest(['order_no'=>$orderGoods['oilCardNo']], $company);
|
||||
if($res['code'] == '1' && isset($res['data']['useQrCodeUrl'])){
|
||||
// 插入支付码记录
|
||||
$QrCodeModel = new QrCodeModel();
|
||||
$QrCodeModel->add([
|
||||
'oilCardNo'=>$orderGoods['oilCardNo'],
|
||||
'qrCode'=>$res['data']['useQrCodeUrl'],
|
||||
'amount'=>$orderGoods['goods_price'],
|
||||
'order_id'=>$orderGoods['order_id'],
|
||||
'user_id'=>$orderGoods['user_id'],
|
||||
'store_id'=>$orderGoods['store_id'],
|
||||
]);
|
||||
$res = [
|
||||
'qrCode'=>$res['data']['useQrCodeUrl']
|
||||
];
|
||||
return $this->renderSuccess($res, '提交成功');
|
||||
}else{
|
||||
return $this->renderError($res['errMessage'] ?? $res['message']);
|
||||
}
|
||||
}
|
||||
// 企油通改造:本功能依赖已下线的上游(智慧油客/定聚),现已停用。
|
||||
return $this->renderError('小程序油品链路已停用');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,60 +250,7 @@ class Order extends Controller
|
||||
*/
|
||||
public function share(): Json
|
||||
{
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
$postData = $this->request->param();
|
||||
$postData['order_goods_id'] = $this->request->param('orderGoodsId');
|
||||
|
||||
$goods = OrderGoodsModel::detail($postData['order_goods_id']);
|
||||
|
||||
if($goods['oil_status'] != 0){
|
||||
return $this->renderError('已分油');
|
||||
}else {
|
||||
if($goods['oilCardType']) {
|
||||
$data['amount'] = $goods['total_price']; // 金额
|
||||
$company = CompanyModel::detail(['orgNo' => $this->getCompany($goods['goods_no'])]);
|
||||
if (!$company) {
|
||||
return $this->renderError('已分油');
|
||||
}
|
||||
try {
|
||||
// 查找一个未被调用的用户
|
||||
$account = $this->processUserOrders($company['company_id']);
|
||||
} catch (\Throwable $e) {
|
||||
return $this->renderError($e->getMessage());
|
||||
}
|
||||
|
||||
// 查询公司余额
|
||||
/*if ($data['amount'] > $company['balance']) {
|
||||
$this->error = '公司余额不足';
|
||||
return false;
|
||||
}*/
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->oilOilCardShare([
|
||||
'goodsNo'=>$goods['goods_no'],
|
||||
'amount'=>$data['amount'],
|
||||
'userNo'=>$account['userNo'],
|
||||
'mobile'=>$account['mobile'],
|
||||
'saleOrderNo'=>$goods['oilCardNo'],
|
||||
'oilCardType'=>$goods['oilCardType']
|
||||
], $company);
|
||||
//$res = json_decode('{"code":"00","message":"请求成功","errCode":null,"errMessage":null,"data":{"oilCardNo":null,"amount":100,"balance":null,"shareNo":"CDV2408021928160001"}}', true);
|
||||
if ($res['code'] != 1) {
|
||||
return $this->renderError($res['errMessage'] ?? $res['message']);
|
||||
}
|
||||
$IdingjuOil->saveLogStore("分油接口结果".json_encode($res,320));
|
||||
$item['account_id'] = $account['account_id'];
|
||||
$item['userNo'] = $account['userNo'];
|
||||
$item['mobile'] = $account['mobile'];
|
||||
$item['company_id'] = $company['company_id'];
|
||||
$item['shareNo'] = $res['data']['trade_no'] ?? '';
|
||||
$item['qrCode'] = $res['data']['useUrl'] ?? '';
|
||||
$item['oil_status_zsy'] = $res['data']['state'] ?? 0;
|
||||
$item['oil_time'] = time();
|
||||
$item['oil_status'] = $item['oil_status_zsy'] == 2 ? 1 : 0; // 已发券 为1
|
||||
$r = $goods->save($item);
|
||||
$IdingjuOil->saveLogStore("保存分油结果".json_encode($r,320));
|
||||
return $this->renderSuccess('分油成功');
|
||||
}
|
||||
}
|
||||
// 企油通改造:本功能依赖已下线的上游(智慧油客/定聚),现已停用。
|
||||
return $this->renderError('小程序油品链路已停用');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace app\store\controller;
|
||||
|
||||
use app\store\controller\Controller;
|
||||
use app\store\model\Partners as PartnersModel;
|
||||
use app\store\model\PartnersGoods as PartnersGoodsModel;
|
||||
use app\store\model\partners\Order as OrderModel;
|
||||
use app\store\model\store\User;
|
||||
use think\response\Json;
|
||||
@@ -94,13 +93,6 @@ class Partners extends Controller
|
||||
public function detail(int $partnersId): Json
|
||||
{
|
||||
$partnersInfo = PartnersModel::detail($partnersId);
|
||||
// 商品列表
|
||||
$partnersInfo['goodsList'] = PartnersGoodsModel::getGoodsList($partnersInfo['partners_id']);
|
||||
// 给每个元素加上 allot_num
|
||||
foreach ($partnersInfo['goodsList'] as &$item) {
|
||||
$item['allot_num'] = 0; // 默认值,可以改成其他逻辑
|
||||
}
|
||||
unset($item); // 解除引用,避免后续误操作
|
||||
return $this->renderSuccess(compact('partnersInfo'));
|
||||
}
|
||||
|
||||
|
||||
@@ -64,40 +64,8 @@ class User extends Controller
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$model = new UserModel;
|
||||
$data = $this->postForm();
|
||||
if (empty($data['company_id'])) {
|
||||
return $this->renderError('请填写分油公司');
|
||||
}
|
||||
if (empty($data['merchant_id'])) {
|
||||
return $this->renderError('请填写商户');
|
||||
}
|
||||
if (empty($data['userType'])) {
|
||||
return $this->renderError('请填写用户角色');
|
||||
}
|
||||
if (empty($data['userName'])) {
|
||||
return $this->renderError('请填写用户姓名');
|
||||
}
|
||||
if (empty($data['mobile'])) {
|
||||
return $this->renderError('请填写用户手机号');
|
||||
}
|
||||
if (empty($data['userIdCard'])) {
|
||||
return $this->renderError('请填写用户身份证号');
|
||||
}
|
||||
|
||||
$company = CompanyModel::detail($data['company_id']);
|
||||
// 对接平台接口
|
||||
$res = $this->userOptAdd(['mobile'=>$data['mobile'],'userName'=>$data['userName'],'userIdCard'=>$data['userIdCard'],'userType'=>$data['userType']], $company);
|
||||
if($res['code'] == '00' && isset($res['data']['userNo'])){
|
||||
$data['userNo'] = $res['data']['userNo'];
|
||||
}else{
|
||||
return $this->renderError('平台创建用户失败【'.($res['errMessage'] ?? $res['message']).'】');
|
||||
}
|
||||
// 新增记录
|
||||
if ($model->add($data,$this->store['user'])) {
|
||||
return $this->renderSuccess('添加成功');
|
||||
}
|
||||
return $this->renderError($model->getError() ?: '添加失败');
|
||||
// 企油通改造:分油用户池已停用(司机信息改由下单平台随单传入),不再向上游注册用户。
|
||||
return $this->renderError('分油用户池已停用');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,80 +169,8 @@ class User extends Controller
|
||||
*/
|
||||
public function oil(int $userId, string $target)
|
||||
{
|
||||
$data = $this->postForm();
|
||||
$user = UserModel::detail($userId);
|
||||
$data['amount'] = $data['amount']??0;
|
||||
$data['goodsNo'] = $data['goodsNo']??'';
|
||||
// 用户详情
|
||||
$model = new OrderModel();
|
||||
if (empty($data['oilCardType'])) {
|
||||
return $this->renderError('请填写卡券类型');
|
||||
}
|
||||
if ($data['oilCardType'] == 'card' && empty($data['amount'])) {
|
||||
return $this->renderError('请填写分油金额');
|
||||
}
|
||||
if ($data['oilCardType'] != 'card' && empty($data['goods_id'])) {
|
||||
return $this->renderError('请选择油券');
|
||||
}
|
||||
if($data['goods_id']) {
|
||||
$goods = GoodsModel::detail($data['goods_id']);
|
||||
$data['goodsNo'] = $goods['goods_no'];
|
||||
$data['amount'] = $goods['goods_price_max']; // 金额
|
||||
}
|
||||
// 查询用户余额
|
||||
if($data['amount'] > $user['balance']){
|
||||
return $this->renderError('用户余额不足');
|
||||
}
|
||||
$saleOrderNo = OrderService::createOrderNo();
|
||||
try {
|
||||
// 查找一个未被调用的用户
|
||||
$account = $this->processUserOrders();
|
||||
} catch (Exception $e) {
|
||||
return $this->renderError($e->getMessage());
|
||||
}
|
||||
$company = CompanyModel::detail($account['company_id']);
|
||||
// 查询公司余额
|
||||
if($data['amount'] > $company['balance']){
|
||||
return $this->renderError('公司余额不足');
|
||||
}
|
||||
$SybOil = new SybOil();
|
||||
// 对接平台接口
|
||||
$res = $SybOil->oilOilCardShare(['goodsNo'=>$data['goodsNo'],'amount'=>$data['amount'],'userNo'=>$account['userNo'],'mobile'=>$account['mobile'],'saleOrderNo'=>$saleOrderNo,'oilCardType'=>$data['oilCardType']], $company);
|
||||
//$res = json_decode('{"code":"00","message":"请求成功","errCode":null,"errMessage":null,"data":{"oilCardNo":null,"amount":100,"balance":null,"shareNo":"CDV2407271355570001"}}',true);
|
||||
if($res['code'] == '00'){
|
||||
$data['saleOrderNo'] = $saleOrderNo;
|
||||
$data['oilCardNo'] = $data['oilCardType'] == 'zsy_ticket' ? $res['data']['shareNo'] : $res['data']['oilCardNo'];
|
||||
$data['amount'] = $res['data']['amount'];
|
||||
$data['shareNo'] = $res['data']['shareNo'] ?? '';
|
||||
$data['company_id'] = $account['company_id'];
|
||||
$data['account_id'] = $account['account_id'];
|
||||
$data['userNo'] = $account['userNo'];
|
||||
$data['mobile'] = $account['mobile'];
|
||||
}else{
|
||||
return $this->renderError('平台分油失败【'.($res['errMessage'] ?? $res['message']).'】');
|
||||
}
|
||||
$data['user_id'] = $user['user_id'];
|
||||
$data['store_id'] = $user['store_id'];
|
||||
$data['payType'] = 10;
|
||||
if ($model->addOil($data)) {
|
||||
// 更新用户余额
|
||||
UserModel::setDecBalance((int)$user['user_id'], (float)$data['amount']);
|
||||
BalanceLogModel::add(SceneEnum::CONSUME, [
|
||||
'user_id' => (int)$user['user_id'],
|
||||
'money' => -(float)$data['amount'],
|
||||
], ['saleOrderNo' => $saleOrderNo]);
|
||||
// 累积用户总消费金额
|
||||
UserModel::setIncPayMoney($user['user_id'], (float)$data['amount']);
|
||||
|
||||
// 更新公司余额
|
||||
CompanyModel::setDecBalance((int)$user['company_id'], (float)$data['amount']);
|
||||
CompanyBalanceLogModel::add(SceneEnum::CONSUME, [
|
||||
'company_id' => (int)$user['company_id'],
|
||||
'money' => -(float)$data['amount'],
|
||||
], ['saleOrderNo' => $saleOrderNo]);
|
||||
return $this->renderSuccess('操作成功');
|
||||
}
|
||||
return $this->renderError($model->getError() ?: '操作失败');
|
||||
// 企油通改造:后台给小程序用户手动分油依赖已下线的上游(智慧油客)+ 分油用户池,现已停用。
|
||||
return $this->renderError('小程序油品链路已停用');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// | 后台 · 下单平台(合作商)订单管理
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// | 企油通改造后:
|
||||
// | list() 订单列表(含企油通批次号/运单号/发放态/加油明细)
|
||||
// | detail() 订单详情 + 加油消费流水
|
||||
// | share() 重新发放:把订单打回未提交态并重投 partners_queue,由 7.7 下发
|
||||
// | qrCode() 获取司机免登加油地址(7.15),出参 qrCode 为 H5 URL
|
||||
// | oilCallback() / useCallback() 重推「发放/加油」结果给下单平台
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\store\controller\partners;
|
||||
|
||||
use app\store\controller\Controller;
|
||||
use app\store\model\partners\Order as OrderModel;
|
||||
use app\store\model\Company as CompanyModel;
|
||||
use app\common\service\IdingjuOil;
|
||||
use app\store\model\order\QrCode as QrCodeModel;
|
||||
use app\common\service\PartnersBalance;
|
||||
use app\common\service\QueueService;
|
||||
use app\common\service\QytOil;
|
||||
use app\store\controller\Controller;
|
||||
use app\store\model\order\QrCode as QrCodeModel;
|
||||
use app\store\model\partners\Order as OrderModel;
|
||||
use think\facade\Db;
|
||||
use think\response\Json;
|
||||
|
||||
/**
|
||||
* 余额明细
|
||||
* Class Order
|
||||
* @package app\store\controller\user
|
||||
*/
|
||||
class Order extends Controller
|
||||
{
|
||||
/**
|
||||
* 订单明细
|
||||
* 订单列表
|
||||
* @return mixed
|
||||
*/
|
||||
public function list()
|
||||
@@ -39,207 +36,148 @@ class Order extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付二维码
|
||||
* 订单详情(含企油通加油消费流水)
|
||||
* @return Json
|
||||
*/
|
||||
public function detail(): Json
|
||||
{
|
||||
$orderId = (int) $this->request->param('orderId');
|
||||
$order = OrderModel::detail($orderId);
|
||||
if (!$order) {
|
||||
return $this->renderError('订单不存在');
|
||||
}
|
||||
$consume = Db::name('qyt_consume')
|
||||
->where('order_id', $orderId)
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
return $this->renderSuccess(['order' => $order, 'consume' => $consume]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取司机免登加油地址(企油通 7.15)
|
||||
* @return Json
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function qrCode(): Json
|
||||
{
|
||||
$postData = $this->postForm();
|
||||
$postData['order_id'] = $this->request->param('orderId');
|
||||
|
||||
$order = OrderModel::detail($postData['order_id']);
|
||||
if($order['use_status'] != 0){
|
||||
return $this->renderError('油券已核销');
|
||||
}else {
|
||||
$company = CompanyModel::detail(['orgNo' => $this->getCompany($order['goods_no'])]);
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->payQrCodeRequest(['order_no'=>$order['oilCardNo']], $company);
|
||||
if($res['code'] == '1' && isset($res['data']['useQrCodeUrl'])){
|
||||
// 插入支付码记录
|
||||
$QrCodeModel = new QrCodeModel();
|
||||
$QrCodeModel->add([
|
||||
'oilCardNo'=>$order['oilCardNo'],
|
||||
'qrCode'=>$res['data']['useQrCodeUrl'],
|
||||
'amount'=>$order['goods_price'],
|
||||
'order_id'=>$order['order_id'],
|
||||
'user_id'=>0,
|
||||
'store_id'=>$order['store_id'],
|
||||
$orderId = (int) $this->request->param('orderId');
|
||||
$order = OrderModel::detail($orderId);
|
||||
if (!$order) {
|
||||
return $this->renderError('订单不存在');
|
||||
}
|
||||
if ($order['use_status'] != 0) {
|
||||
return $this->renderError('该单已加油核销');
|
||||
}
|
||||
if ($order['oil_status'] != 1) {
|
||||
return $this->renderError('该单尚未发放成功,无法获取加油地址');
|
||||
}
|
||||
$h5Url = (new QytOil())->h5Url((string) $order['mobile']);
|
||||
if (!$h5Url) {
|
||||
return $this->renderError('生成加油地址失败,请检查企油通配置');
|
||||
}
|
||||
// 留痕
|
||||
(new QrCodeModel())->add([
|
||||
'oilCardNo' => $order['oilCardNo'],
|
||||
'qrCode' => $h5Url,
|
||||
'amount' => $order['goods_price'],
|
||||
'order_id' => $order['order_id'],
|
||||
'user_id' => 0,
|
||||
'store_id' => $order['store_id'],
|
||||
]);
|
||||
$res = [
|
||||
'qrCode'=>$res['data']['useQrCodeUrl']
|
||||
];
|
||||
return $this->renderSuccess($res, '提交成功');
|
||||
}else{
|
||||
return $this->renderError($res['errMessage'] ?? $res['message']);
|
||||
}
|
||||
}
|
||||
return $this->renderSuccess(['qrCode' => $h5Url], '获取成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $goodsNo
|
||||
* @return string
|
||||
*/
|
||||
public function getCompany($goodsNo): string
|
||||
{
|
||||
switch ($goodsNo) {
|
||||
case 'djgdface100':
|
||||
case 'djgdface200':
|
||||
case 'djgdface300':
|
||||
return 'umQZhIHKofyA';
|
||||
case 'jmgxyyface100':
|
||||
case 'jmgxyyface200':
|
||||
case 'jmgxyyface300':
|
||||
|
||||
case 'jmgzface100':
|
||||
case 'jmgzface200':
|
||||
case 'jmgzface300':
|
||||
|
||||
case 'jmfjface100':
|
||||
case 'jmfjface200':
|
||||
case 'jmfjface300':
|
||||
return 'HpWqXIgYvTBg';
|
||||
case 'face003':
|
||||
return 'NKJBgaaRNdiL'; // 测试参数
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动分油
|
||||
* 重新发放(把订单打回未提交态并重投队列,由 partners:queue 调用企油通 7.7)
|
||||
* @return Json
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function share(): Json
|
||||
{
|
||||
$IdingjuOil = new IdingjuOil();
|
||||
$postData = $this->request->param();
|
||||
$postData['order_id'] = $this->request->param('orderId');
|
||||
|
||||
$order = OrderModel::detail($postData['order_id']);
|
||||
if($order['oil_status'] != 0){
|
||||
return $this->renderError('已分油');
|
||||
}else {
|
||||
if($order['oilCardType']) {
|
||||
$data['amount'] = $order['total_price']; // 金额
|
||||
$company = CompanyModel::detail(['orgNo' => $this->getCompany($order['goods_no'])]);
|
||||
if (!$company) {
|
||||
return $this->renderError('已分油');
|
||||
$orderId = (int) $this->request->param('orderId');
|
||||
$order = OrderModel::detail($orderId);
|
||||
if (!$order) {
|
||||
return $this->renderError('订单不存在');
|
||||
}
|
||||
|
||||
// 对接平台接口
|
||||
$res = $IdingjuOil->oilOilCardShare([
|
||||
'goodsNo'=>$order['goods_no'],
|
||||
'amount'=>$data['amount'],
|
||||
'userNo'=>0,
|
||||
'mobile'=>$order['mobile'],
|
||||
'saleOrderNo'=>$order['oilCardNo'],
|
||||
'oilCardType'=>$order['oilCardType']
|
||||
], $company);
|
||||
if ($res['code'] != 1) {
|
||||
return $this->renderError($res['errMessage'] ?? $res['message']);
|
||||
if ($order['oil_status'] == 1) {
|
||||
return $this->renderError('该单已发放成功,无需重发');
|
||||
}
|
||||
$IdingjuOil->saveLogStore("分油接口结果".json_encode($res,320));
|
||||
// $item['company_id'] = $company['company_id'];
|
||||
$item['shareNo'] = $res['data']['trade_no'] ?? '';
|
||||
$item['qrCode'] = $res['data']['useUrl'] ?? '';
|
||||
$item['oil_status_zsy'] = $res['data']['state'] ?? 0;
|
||||
$item['oil_time'] = time();
|
||||
$item['oil_status'] = $item['oil_status_zsy'] == 2 ? 1 : 0; // 已发券 为1
|
||||
$r = $order->save($item);
|
||||
$IdingjuOil->saveLogStore("保存分油结果".json_encode($r,320));
|
||||
return $this->renderSuccess('分油成功');
|
||||
if ($order['use_status'] != 0) {
|
||||
return $this->renderError('该单已加油核销,不可重发');
|
||||
}
|
||||
// 发放失败时余额已回补,重发需重新扣减合作商余额
|
||||
$logId = PartnersBalance::deduct(
|
||||
(int) $order['partners_id'],
|
||||
(float) $order['total_price'],
|
||||
(string) $order['partners_order_no'],
|
||||
$orderId,
|
||||
(int) $order['store_id']
|
||||
);
|
||||
if ($logId === false) {
|
||||
return $this->renderError('合作商余额不足,请先充值后再重发');
|
||||
}
|
||||
// 仅允许从「发放失败(3)」重置为「未提交(0)」,避免与正在处理的单冲突
|
||||
$reset = Db::name('partners_order')->where('order_id', $orderId)
|
||||
->where('oil_status', 0)
|
||||
->where('oil_status_zsy', 3)
|
||||
->update(['oil_status_zsy' => 0, 'oil_text' => '后台重新发放', 'update_time' => time()]);
|
||||
if (!$reset) {
|
||||
// 状态已被其它进程改变 -> 回补刚扣的余额
|
||||
PartnersBalance::refund(
|
||||
(int) $order['partners_id'],
|
||||
(float) $order['total_price'],
|
||||
(string) $order['partners_order_no'],
|
||||
$orderId,
|
||||
(int) $order['store_id']
|
||||
);
|
||||
return $this->renderError('当前状态不允许重发(仅「发放失败」的订单可重发)');
|
||||
}
|
||||
(new QueueService())->push('partners_queue', json_encode(['order_id' => $orderId], 320));
|
||||
return $this->renderSuccess('已提交重新发放,请稍后刷新查看结果');
|
||||
}
|
||||
|
||||
/**
|
||||
* 分油回调
|
||||
* 重推「发放结果」给下单平台
|
||||
* @return Json
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function oilCallback(): Json
|
||||
{
|
||||
/*
|
||||
$model = new OrderModel;
|
||||
$list = $model->getAll([
|
||||
['partners_id', '=', 4],
|
||||
['oil_status', '=', 1],
|
||||
['oil_callback', '=', 0],
|
||||
])->toArray();
|
||||
$queueService = new QueueService();
|
||||
foreach ($list as $order){
|
||||
// 存入队列处理
|
||||
$queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $order['order_id'],
|
||||
$orderId = (int) $this->request->param('orderId');
|
||||
$order = OrderModel::detail($orderId);
|
||||
if (!$order) {
|
||||
return $this->renderError('订单不存在');
|
||||
}
|
||||
if ($order['oil_status'] != 1) {
|
||||
return $this->renderError('该单未发放成功,无可回调内容');
|
||||
}
|
||||
(new QueueService())->push('notify_queue', json_encode([
|
||||
'order_id' => $orderId,
|
||||
'type' => 'add',
|
||||
'optType' => 'share_oil',
|
||||
'retry_count' => 0,
|
||||
], 320));
|
||||
}
|
||||
return $this->renderSuccess('回调成功');*/
|
||||
|
||||
$postData = $this->request->param();
|
||||
$postData['order_id'] = $this->request->param('orderId');
|
||||
|
||||
$order = OrderModel::detail($postData['order_id']);
|
||||
if($order['oil_status'] == 0){
|
||||
return $this->renderError('未分油');
|
||||
}else {
|
||||
// 存入队列处理
|
||||
$queueService = new QueueService();
|
||||
$queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $order['order_id'],
|
||||
'type' => 'add',
|
||||
'optType' => 'share_oil',
|
||||
'retry_count' => 0,
|
||||
], 320));
|
||||
return $this->renderSuccess('回调成功');
|
||||
}
|
||||
return $this->renderSuccess('已重新推送发放结果');
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用回调
|
||||
* 重推「加油核销」结果给下单平台
|
||||
* @return Json
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function useCallback(): Json
|
||||
{
|
||||
/*
|
||||
$model = new OrderModel;
|
||||
$list = $model->getAll([
|
||||
['partners_id', '=', 4],
|
||||
['use_status', '=', 1],
|
||||
['use_callback', '=', 0],
|
||||
])->toArray();
|
||||
$queueService = new QueueService();
|
||||
foreach ($list as $order){
|
||||
// 存入队列处理
|
||||
$queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $order['order_id'],
|
||||
$orderId = (int) $this->request->param('orderId');
|
||||
$order = OrderModel::detail($orderId);
|
||||
if (!$order) {
|
||||
return $this->renderError('订单不存在');
|
||||
}
|
||||
if ($order['use_status'] != 1) {
|
||||
return $this->renderError('该单未加油核销,无可回调内容');
|
||||
}
|
||||
(new QueueService())->push('notify_queue', json_encode([
|
||||
'order_id' => $orderId,
|
||||
'type' => 'sub',
|
||||
'optType' => 'add_oil',
|
||||
'retry_count' => 0,
|
||||
], 320));
|
||||
}
|
||||
return $this->renderSuccess('回调成功');*/
|
||||
|
||||
$postData = $this->request->param();
|
||||
$postData['order_id'] = $this->request->param('orderId');
|
||||
|
||||
$order = OrderModel::detail($postData['order_id']);
|
||||
if($order['use_status'] == 0){
|
||||
return $this->renderError('未使用');
|
||||
}else {
|
||||
// 通知对接公司
|
||||
$queueService = new QueueService();
|
||||
$queueService->push('notify_queue', json_encode([
|
||||
'order_id' => $order['order_id'],
|
||||
'optType' => 'add_oil',
|
||||
'retry_count' => 0,
|
||||
], 320));
|
||||
return $this->renderSuccess('回调成功');
|
||||
}
|
||||
return $this->renderSuccess('已重新推送加油结果');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,8 @@ use think\Session;
|
||||
use app\common\model\Partners as PartnersModel;
|
||||
use app\store\model\Order as OrderModel;
|
||||
use app\store\model\store\User as UserModel;
|
||||
use app\store\model\PartnersGoods as PartnersGoodsModel;
|
||||
|
||||
use app\store\model\partners\BalanceLog as BalanceLogModel;
|
||||
use app\store\model\partners\StockLog as StockLogModel;
|
||||
use app\store\service\store\User as StoreUserService;
|
||||
use app\common\enum\partners\balanceLog\Scene as SceneEnum;
|
||||
use app\common\library\helper;
|
||||
@@ -51,8 +49,6 @@ class Partners extends PartnersModel
|
||||
$this->error = '请填写商户名称';
|
||||
return false;
|
||||
}
|
||||
// 检查商品数据
|
||||
$goodsList = PartnersGoodsModel::checkGoodsData($data['goodsList']);
|
||||
$this->startTrans();
|
||||
try {
|
||||
$data['orgNo'] = $this->createNo();
|
||||
@@ -75,10 +71,6 @@ class Partners extends PartnersModel
|
||||
$userModel->save($newData);
|
||||
// 新增角色关系记录
|
||||
UserRole::increased((int)$userModel['store_user_id'], [10014]);
|
||||
// 新增商品关系记录
|
||||
PartnersGoodsModel::increased((int)$this['partners_id'], $goodsList);
|
||||
// 新增合作商商品库存变动记录
|
||||
StockLogModel::increased((int)$this['partners_id'], $goodsList);
|
||||
$this->commit();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
@@ -146,16 +138,10 @@ class Partners extends PartnersModel
|
||||
$this->error = '请填写商户名称';
|
||||
return false;
|
||||
}
|
||||
// 检查商品数据
|
||||
$goodsList = PartnersGoodsModel::checkGoodsData($data['goodsList']);
|
||||
$this->startTrans();
|
||||
try {
|
||||
// 更新管理员记录
|
||||
$this->save($data);
|
||||
// 更新商品关系记录
|
||||
PartnersGoodsModel::updates((int)$this['partners_id'], $goodsList);
|
||||
// 新增合作商商品库存变动记录
|
||||
StockLogModel::increased((int)$this['partners_id'], $goodsList);
|
||||
$this->commit();
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\store\model;
|
||||
|
||||
use app\common\library\helper;
|
||||
use app\common\model\PartnersGoods as PartnersGoodsModel;
|
||||
use cores\exception\BaseException;
|
||||
|
||||
/**
|
||||
* 合作商商品关系模型
|
||||
* Class PartnersGoods
|
||||
* @package app\store\model
|
||||
*/
|
||||
class PartnersGoods extends PartnersGoodsModel
|
||||
{
|
||||
/**
|
||||
* 验证商品是否合法
|
||||
* @param array $goodsList
|
||||
* @throws BaseException
|
||||
*/
|
||||
public static function checkGoodsData(array $goodsList)
|
||||
{
|
||||
$values = helper::getArrayColumn($goodsList, 'goods_id');
|
||||
if (count($goodsList) != count(array_unique($values))) {
|
||||
throwError('很抱歉,不能存在重复的商品 请检查您的选择');
|
||||
}
|
||||
foreach ($goodsList as &$item) {
|
||||
if($item['allot_num'] < 0 && abs($item['allot_num']) > $item['stock_num']){
|
||||
throwError('很抱歉,分配数量减少不能低于库存数量 请检查您的输入');
|
||||
}elseif($item['allot_num'] > 100){
|
||||
throwError('很抱歉,分配数量不能大于100 请检查您的输入');
|
||||
}
|
||||
$item['before_num'] = $item['stock_num'];
|
||||
$item['stock_num'] += $item['allot_num'];
|
||||
$item['after_num'] = $item['stock_num'];
|
||||
$item['change_type'] = $item['allot_num'] < 0 ? 2 : 1;
|
||||
}
|
||||
unset($item);
|
||||
return $goodsList;
|
||||
}
|
||||
/**
|
||||
* 批量写入合作商与商品关系记录
|
||||
* @param int $partnersId
|
||||
* @param array $goodsList
|
||||
* @return array|false
|
||||
*/
|
||||
public static function increased(int $partnersId, array $goodsList)
|
||||
{
|
||||
$dataset = [];
|
||||
foreach ($goodsList as $item) {
|
||||
$dataset[] = [
|
||||
'partners_id' => $partnersId,
|
||||
'goods_id' => $item['goods_id'],
|
||||
'stock_num' => $item['stock_num'],
|
||||
'store_id' => self::$storeId
|
||||
];
|
||||
}
|
||||
return (new static)->addAll($dataset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新合作商和商品关系记录
|
||||
* @param int $partnersId
|
||||
* @param array $goodsList
|
||||
* @return array|false
|
||||
*/
|
||||
public static function updates(int $partnersId, array $goodsList)
|
||||
{
|
||||
// 删除所有的记录
|
||||
static::deleteAll(['partners_id' => $partnersId]);
|
||||
// 批量新增记录
|
||||
return static::increased($partnersId, $goodsList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,13 +31,13 @@ class Order extends OrderModel
|
||||
// 设置查询条件
|
||||
$filter = $this->getFilter($param);
|
||||
// 先查询总金额
|
||||
$totalPayPrice = $this->with(['goods.images.file', 'partners'])
|
||||
$totalPayPrice = $this->with(['partners'])
|
||||
->alias('order')
|
||||
->field('order.*')
|
||||
->where($filter)
|
||||
->sum('order.total_pay_price');
|
||||
// 获取列表数据
|
||||
$list = $this->with(['goods.images.file', 'partners'])
|
||||
$list = $this->with(['partners'])
|
||||
->alias('order')
|
||||
->field('order.*')
|
||||
->where($filter)
|
||||
@@ -60,23 +60,32 @@ class Order extends OrderModel
|
||||
// 设置默认的检索数据
|
||||
$params = $this->setQueryDefaultValue($param, [
|
||||
'partners_id' => 0, // 合作商ID
|
||||
'search' => '', // 用户昵称
|
||||
'goods_no' => '', // 商品编码
|
||||
'oil_status' => -1, // 分油状态
|
||||
'use_status' => -1, // 使用状态
|
||||
'search' => '', // 司机手机号
|
||||
'driver_name' => '', // 司机姓名
|
||||
'orderNo' => '', // 单号:油卡编号/下单平台单号/批次号/运单号
|
||||
'oil_status' => -1, // 分油(发放)状态
|
||||
'oil_status_zsy' => -1, // 企油通发放态 0未提交 2成功 3失败
|
||||
'use_status' => -1, // 加油核销状态
|
||||
'betweenTime' => [] // 起止时间
|
||||
]);
|
||||
// 检索查询条件
|
||||
$filter = [];
|
||||
// 合作商ID
|
||||
$params['partners_id'] > 0 && $filter[] = ['order.partners_id', '=', $params['partners_id']];
|
||||
// 用户昵称
|
||||
// 司机手机号
|
||||
!empty($params['search']) && $filter[] = ['order.mobile', 'like', "%{$params['search']}%"];
|
||||
// 商品编码
|
||||
!empty($params['goods_no']) && $filter[] = ['order.goods_no', 'like', "%{$params['goods_no']}%"];
|
||||
// 分油状态
|
||||
// 司机姓名
|
||||
!empty($params['driver_name']) && $filter[] = ['order.driver_name', 'like', "%{$params['driver_name']}%"];
|
||||
// 单号模糊检索(油卡编号 / 下单平台销售单号 / 企油通批次号 / 运单号)
|
||||
if (!empty($params['orderNo'])) {
|
||||
$kw = $params['orderNo'];
|
||||
$filter[] = ['order.oilCardNo|order.partners_order_no|order.batch_no|order.waybill_no', 'like', "%{$kw}%"];
|
||||
}
|
||||
// 分油(发放)状态
|
||||
$params['oil_status'] > -1 && $filter[] = ['oil_status', '=', (int)$params['oil_status']];
|
||||
// 使用状态
|
||||
// 企油通发放态
|
||||
$params['oil_status_zsy'] > -1 && $filter[] = ['oil_status_zsy', '=', (int)$params['oil_status_zsy']];
|
||||
// 加油核销状态
|
||||
$params['use_status'] > -1 && $filter[] = ['use_status', '=', (int)$params['use_status']];
|
||||
// 起止时间
|
||||
if (!empty($params['betweenTime'])) {
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\store\model\partners;
|
||||
|
||||
use app\common\model\partners\StockLog as StockLogModel;
|
||||
|
||||
/**
|
||||
* 合作商商品库存变动明细模型
|
||||
* Class StockLog
|
||||
* @package app\store\model\partners
|
||||
*/
|
||||
class StockLog extends StockLogModel
|
||||
{
|
||||
/**
|
||||
* 获取合作商商品库存变动明细列表
|
||||
* @param array $param
|
||||
* @return \think\Paginator
|
||||
*/
|
||||
public function getList(array $param = [])
|
||||
{
|
||||
// 设置查询条件
|
||||
$filter = $this->getFilter($param);
|
||||
// 获取列表数据
|
||||
return $this->alias('log')
|
||||
->field('log.*,partners.name')
|
||||
->where($filter)
|
||||
->join('partners', 'partners.partners_id = log.partners_id')
|
||||
->order(['log.create_time' => 'desc'])
|
||||
->paginate(15);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置查询条件
|
||||
* @param array $param
|
||||
* @return array
|
||||
*/
|
||||
private function getFilter(array $param): array
|
||||
{
|
||||
// 设置默认的检索数据
|
||||
$params = $this->setQueryDefaultValue($param, [
|
||||
'partners_id' => 0, // 合作商ID
|
||||
'search' => '', // 用户昵称
|
||||
'betweenTime' => [] // 起止时间
|
||||
]);
|
||||
// 检索查询条件
|
||||
$filter = [];
|
||||
// 用户ID
|
||||
$params['partners_id'] > 0 && $filter[] = ['log.partners_id', '=', $params['partners_id']];
|
||||
// 用户昵称
|
||||
!empty($params['search']) && $filter[] = ['partners.name', 'like', "%{$params['search']}%"];
|
||||
// 起止时间
|
||||
if (!empty($params['betweenTime'])) {
|
||||
$times = between_time($params['betweenTime']);
|
||||
$filter[] = ['log.create_time', '>=', $times['start_time']];
|
||||
$filter[] = ['log.create_time', '<', $times['end_time'] + 86400];
|
||||
}
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量写入合作商与商品库存变动记录
|
||||
* @param int $partnersId
|
||||
* @param array $goodsList
|
||||
* @return array|false
|
||||
*/
|
||||
public static function increased(int $partnersId, array $goodsList)
|
||||
{
|
||||
$dataset = [];
|
||||
foreach ($goodsList as $item) {
|
||||
if(!empty($item['allot_num'])) {
|
||||
$dataset[] = [
|
||||
'partners_id' => $partnersId,
|
||||
'goods_id' => $item['goods_id'],
|
||||
'before_num' => $item['before_num'],
|
||||
'after_num' => $item['after_num'],
|
||||
'change_type' => $item['change_type'],
|
||||
'change_num' => $item['allot_num'],
|
||||
'store_id' => self::$storeId
|
||||
];
|
||||
}
|
||||
}
|
||||
return (new static)->addAll($dataset);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,9 +7,9 @@ $config = [
|
||||
// 数据库名
|
||||
'database' => 'oil',
|
||||
// 用户名
|
||||
'username' => 'root',
|
||||
'username' => 'oil',
|
||||
// 密码
|
||||
'password' => 'qQ19961012',
|
||||
'password' => 'AxSZEJDp5nePyfMa',
|
||||
// 端口号
|
||||
'hostport' => '3306',
|
||||
// 数据库编码默认采用utf8
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 企油通对接配置(支付宝企业码通道)
|
||||
// +----------------------------------------------------------------------
|
||||
// | 本次仅对接 3 个接口:7.7 运单油费下发 / 7.15 H5 跳转地址 / 7.10 加油明细推送(异步回调)
|
||||
// | 标 ★ 的值需向企油通对接人索取后填入;敏感值建议用 .env 覆盖,不提交版本库
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
|
||||
// ============ 接口环境 ============
|
||||
|
||||
// ★ 接口域名(测试 / 正式不同),不含结尾斜杠,例如 https://xxx.worknoya.vip
|
||||
'base_url' => env('qyt.base_url', ''),
|
||||
|
||||
// ★ 平台分配的 appId(业务接口用)
|
||||
'app_id' => env('qyt.app_id', ''),
|
||||
|
||||
// ★ 我方(慧明)RSA 私钥:PEM 全文,或去头尾的 base64 单行均可
|
||||
'private_key' => env('qyt.private_key', ''),
|
||||
|
||||
// ★ 企油通平台公钥:PEM 或 base64(验签企油通的响应 / 回调)
|
||||
'platform_public_key' => env('qyt.platform_public_key', ''),
|
||||
|
||||
// 请求超时(秒)
|
||||
'timeout' => 15,
|
||||
|
||||
|
||||
// ============ 企业(单企业,线下已开户,固定支付宝企业码通道) ============
|
||||
|
||||
// ★ 营业执照编码 / 统一社会信用代码
|
||||
'business_license' => env('qyt.business_license', ''),
|
||||
|
||||
// ★ 机构号:支付宝企业码通道 7.7 必填,待企油通系统分配
|
||||
'institution_id' => env('qyt.institution_id', ''),
|
||||
|
||||
|
||||
// ============ 编号 / 业务参数 ============
|
||||
|
||||
// 全平台唯一编号前缀(batch_no / waybill_no / waybill_no_code 加前缀防撞号)
|
||||
// 建议:企业标识 + 环境标识,如 HM / HMTEST
|
||||
'no_prefix' => env('qyt.no_prefix', 'HM'),
|
||||
|
||||
// 7.7 凭证名称(voucher_name)
|
||||
'voucher_name' => '运单卡',
|
||||
|
||||
|
||||
// ============ 回调 / H5 ============
|
||||
|
||||
// ★ 我方对外回调地址(配置到企油通后台,用于 7.10 加油消费推送)
|
||||
// 形如 https://你的域名/qytconsume.php
|
||||
'consume_notify_url' => env('qyt.consume_notify_url', ''),
|
||||
|
||||
// 7.15 H5 免登落地页地址(测试 / 正式不同)
|
||||
// 测试:http://dev.paytaskpage.worknoya.vip/#/ 正式:https://paytaskpage.worknoya.vip/#/
|
||||
'h5_base_url' => env('qyt.h5_base_url', 'https://paytaskpage.worknoya.vip/#/'),
|
||||
|
||||
// ★ 7.15 H5 免登使用的 appId(可用企业级通道 appId 或商户级 appId,线下确认)
|
||||
'h5_app_id' => env('qyt.h5_app_id', ''),
|
||||
|
||||
// 7.15 是否把 creditcode(营业执照号)带入链接并入签(true 则本次登录固定到该企业)
|
||||
'h5_with_creditcode' => true,
|
||||
|
||||
|
||||
// ============ 杂项 ============
|
||||
|
||||
// 是否记录详细请求 / 响应日志到 runtime/storelog
|
||||
'log' => (bool) env('qyt.log', true),
|
||||
|
||||
// ★ 业务接口拼签字段顺序 —— 待对接人确认(见 Qyt::bizSign 的 TODO)
|
||||
'sign_mode' => env('qyt.sign_mode', 'ksort_md5_sha1rsa'),
|
||||
|
||||
// 7.7 重试幂等:企油通返回 message 命中以下任一关键字时,判定 batch_no 已存在 -> 按「已受理」处理
|
||||
'dup_batch_hints' => ['已存在', '重复', 'duplicate', 'exist'],
|
||||
];
|
||||
@@ -0,0 +1,124 @@
|
||||
-- ============================================================
|
||||
-- 开发/联调环境 数据库初始化清理脚本
|
||||
-- 生成:2026-09-06
|
||||
-- 作用:清空业务与测试流水,保留系统运行所需的账号、权限、字典、设置
|
||||
-- ⚠️ 执行前务必备份:mysqldump -uroot -p oil > backup.sql
|
||||
-- ============================================================
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1. 企油通 / 合作商 业务流水
|
||||
-- 注意:yoshop_partners(下游接口账户:orgNo/appKey/RSA密钥/回调地址)予以保留
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_partners_order`;
|
||||
TRUNCATE TABLE `yoshop_qyt_consume`;
|
||||
TRUNCATE TABLE `yoshop_partners_balance_log`;
|
||||
TRUNCATE TABLE `yoshop_partners_goods`;
|
||||
TRUNCATE TABLE `yoshop_partners_stock_log`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2. 商城订单与售后
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_order`;
|
||||
TRUNCATE TABLE `yoshop_order_goods`;
|
||||
TRUNCATE TABLE `yoshop_order_address`;
|
||||
TRUNCATE TABLE `yoshop_order_qrcode`;
|
||||
TRUNCATE TABLE `yoshop_order_record`;
|
||||
TRUNCATE TABLE `yoshop_order_refund`;
|
||||
TRUNCATE TABLE `yoshop_order_refund_address`;
|
||||
TRUNCATE TABLE `yoshop_order_refund_image`;
|
||||
TRUNCATE TABLE `yoshop_order_export`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3. 接口请求日志 / 已停用模块(分油公司、分油用户池)
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_request_log`;
|
||||
TRUNCATE TABLE `yoshop_account`;
|
||||
TRUNCATE TABLE `yoshop_company`;
|
||||
TRUNCATE TABLE `yoshop_company_balance_log`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4. 购物车 / 结算 / 兑换卡 / 充值
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_cart`;
|
||||
TRUNCATE TABLE `yoshop_checkout`;
|
||||
TRUNCATE TABLE `yoshop_card`;
|
||||
TRUNCATE TABLE `yoshop_card_log`;
|
||||
TRUNCATE TABLE `yoshop_card_print`;
|
||||
TRUNCATE TABLE `yoshop_recharge_order`;
|
||||
TRUNCATE TABLE `yoshop_recharge_order_plan`;
|
||||
TRUNCATE TABLE `yoshop_recharge_plan`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 5. 商户 / 代理商体系(支付聚合链路)
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_merchant`;
|
||||
TRUNCATE TABLE `yoshop_merchant_balance_log`;
|
||||
TRUNCATE TABLE `yoshop_merchant_order`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 6. 小程序用户及其附属数据(保留 yoshop_user_grade 等级配置)
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_user`;
|
||||
TRUNCATE TABLE `yoshop_user_oauth`;
|
||||
TRUNCATE TABLE `yoshop_user_address`;
|
||||
TRUNCATE TABLE `yoshop_user_balance_log`;
|
||||
TRUNCATE TABLE `yoshop_user_coupon`;
|
||||
TRUNCATE TABLE `yoshop_user_grade_log`;
|
||||
TRUNCATE TABLE `yoshop_user_points_log`;
|
||||
TRUNCATE TABLE `yoshop_user_commission_log`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 7. 商城基础数据(商品 / 分类 / 优惠券 / 装修页 / 文件库)
|
||||
-- 注意:图片物理文件仍在磁盘,仅清库记录
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_goods`;
|
||||
TRUNCATE TABLE `yoshop_goods_sku`;
|
||||
TRUNCATE TABLE `yoshop_goods_image`;
|
||||
TRUNCATE TABLE `yoshop_goods_category_rel`;
|
||||
TRUNCATE TABLE `yoshop_goods_service_rel`;
|
||||
TRUNCATE TABLE `yoshop_goods_spec_rel`;
|
||||
TRUNCATE TABLE `yoshop_goods_coupon`;
|
||||
TRUNCATE TABLE `yoshop_category`;
|
||||
TRUNCATE TABLE `yoshop_coupon`;
|
||||
TRUNCATE TABLE `yoshop_page`;
|
||||
TRUNCATE TABLE `yoshop_upload_file`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 8. 其余业务表
|
||||
-- ------------------------------------------------------------
|
||||
TRUNCATE TABLE `yoshop_notify`;
|
||||
TRUNCATE TABLE `yoshop_code`;
|
||||
TRUNCATE TABLE `yoshop_comment`;
|
||||
TRUNCATE TABLE `yoshop_comment_image`;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 9. 后台账号:只保留超级管理员 admin(store_user_id=10001)
|
||||
-- ------------------------------------------------------------
|
||||
DELETE FROM `yoshop_store_user` WHERE `store_user_id` <> 10001;
|
||||
DELETE FROM `yoshop_store_user_role` WHERE `store_user_id` <> 10001;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 10. 恢复 yoshop 惯用的自增起始值(10001)
|
||||
-- ------------------------------------------------------------
|
||||
ALTER TABLE `yoshop_cart` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_category` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_coupon` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_goods` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_goods_category_rel` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_goods_image` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_goods_service_rel` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_goods_sku` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_merchant_order` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_order` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_order_goods` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_page` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_upload_file` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_user` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_user_address` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_user_balance_log` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_user_coupon` AUTO_INCREMENT = 10001;
|
||||
ALTER TABLE `yoshop_user_oauth` AUTO_INCREMENT = 10001;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,33 @@
|
||||
; ============================================================
|
||||
; 企油通配置 —— 追加到 server-tp6/.env 文件末尾
|
||||
; ------------------------------------------------------------
|
||||
; ⚠️ ThinkPHP 用 parse_ini_file(..., INI_SCANNER_RAW) 解析 .env:
|
||||
; 值【不要加引号】,加了引号会连引号一起被读进去。
|
||||
; ⚠️ RSA 密钥请去掉 -----BEGIN/END----- 头尾与所有换行,压成【一行 base64】。
|
||||
; Qyt.php 会自动补回 PEM 头尾(见 loadPrivateKey / loadPublicKey)。
|
||||
; ============================================================
|
||||
|
||||
[QYT]
|
||||
; 接口域名,不含结尾斜杠(测试/正式不同,向企油通对接人索取)
|
||||
BASE_URL = https://xxx.worknoya.vip
|
||||
; 平台分配的 appId(业务接口用)
|
||||
APP_ID =
|
||||
; 我方 RSA 私钥(一行 base64,无头尾无换行)
|
||||
PRIVATE_KEY =
|
||||
; 企油通平台公钥(一行 base64,用于验签其响应/回调)
|
||||
PLATFORM_PUBLIC_KEY =
|
||||
; 我方企业营业执照编码 / 统一社会信用代码
|
||||
BUSINESS_LICENSE =
|
||||
; 机构号:支付宝企业码通道 7.7 必填,由企油通分配
|
||||
INSTITUTION_ID =
|
||||
; 全平台唯一编号前缀(batch_no / waybill_no / waybill_no_code 用,防与其他接入方撞号)
|
||||
; 建议区分环境,如正式 HM、测试 HMTEST
|
||||
NO_PREFIX = HM
|
||||
; 7.15 H5 免登落地页地址(测试:http://dev.paytaskpage.worknoya.vip/#/)
|
||||
H5_BASE_URL = https://paytaskpage.worknoya.vip/#/
|
||||
; 7.15 H5 免登用的 appId(可能与业务 appId 不同,需线下确认)
|
||||
H5_APP_ID =
|
||||
; 我方 7.10 回调地址(此项仅作记录,实际需在企油通后台配置)
|
||||
CONSUME_NOTIFY_URL = https://www.hmzkw.com/qytconsume.php
|
||||
; 是否记录详细请求/响应日志到 runtime/storelog
|
||||
LOG = true
|
||||
@@ -0,0 +1,48 @@
|
||||
SET NAMES utf8mb4;
|
||||
DELETE FROM `yoshop_partners` WHERE `appKey` = 'qyttest0000000000000000000001';
|
||||
INSERT INTO `yoshop_partners`
|
||||
(`name`,`address`,`contact_name`,`contact_tel`,`orgNo`,`appKey`,`privateKey`,`publicKey`,`callback`,`balance`,`store_id`,`store_user_id`,`update_time`,`create_time`)
|
||||
VALUES
|
||||
('企油通联调测试商','测试地址','测试联系人','13800000000','S88888888','qyttest0000000000000000000001',
|
||||
'-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDUOwdCCPSgPpR+
|
||||
WsYXVz/2FQ35ybQWJK14ytDk4ITv+fQMEnMbQ8D+4cREXIydE/NOzgn+hDfHbFDf
|
||||
91wti0P+1C+74wBA5xZlbhae8ZAB1hc5gmSJqE++LalfrmOIg5SDfQhtiaf4htEo
|
||||
RdxEsupS964izLoXeUgIE9lY87JCqluU1thvbk601sPi2q8WnfIKN8vnSvu31YRr
|
||||
86Hc4soyIdf1WZSoU4couE2QmOFm9jr55Obp+USfJg7Rjoce9ZOFj0lX3gkHqGOz
|
||||
l2toxfzyZp+KqlhQLWYLmiLM3Z3G2Gz118MGjaan7zIW15Feuae1v3eNaqF7Zq6C
|
||||
zDZckiwvAgMBAAECggEAWOOUSaMomkk7tqRcXYBMqMvuu5UwmSmpgnMoBQTIiR5e
|
||||
igPcNCovllGG+77rogquGG6RnwlPt3X1dajL8cNnqj7C82XDQGvJZJg0X0P7tdku
|
||||
hwbHByT4qUXEr++BfrblqCDhO8exE5Wb2stP03JAVJmqVKb8tkI02jU+DlSbb/HY
|
||||
9G//rx1Wkbwmk1jYBu5pSuQWsQaZyijeb8JfLzGYkHyV6mrBFyFrWHoH7fmC3M6R
|
||||
sLxdsj/KUIYyNHCTmRC7TG2MFQGyTRUb7Z73WgI4OzAD934sM93AMeDWtkp0Ar2r
|
||||
lm5xjojrpi63IiKhR66+Tzws8bV94e99k3UcftxDQQKBgQDut5RE/srMWvv584oY
|
||||
TKvVrJwm6C47QpfjY98F745cV7IYGF2ZXOcS7uavRjbI0ct3vKTJk3dfrQ9pqgIN
|
||||
vrLIIxWFv+xgIzTtbpUPpd4Y6dUIZYRS2Di03WlJnlHvnq8iZbQ2cK6T3nLETVa5
|
||||
sK/ab5vEIuCyEv5DF4ulmGtMYQKBgQDjmIsuRCuX7BhSSC6ZpRMPEDuTyczKAEgd
|
||||
m4qzSM4YFkhVGD9LdLwbMndTZk1iNie1UkpN52zzidx/ZTUfcewJem/C6re9cMM/
|
||||
xytUWz89TUYerkXpPx8K7CG3KG9v64rx3j8/pvsY82oBnJu3n0Pb0sbfpv0G0Cax
|
||||
GMzv+GHCjwKBgBPHVhuZWMgxyareCNUWlS4xDQcUObBjRh5rCfF99bek9HaWnjq0
|
||||
vdiNvsNK+AMPjuIu2SByfXOJ7Tr+AQmOgVWfworAah9VC2+Yt/UB8zLxPNtjPeF3
|
||||
VMt3hN+6pGNMLIqXDqVsFKrfxXaKSeM8xnU8xhUsJp3agQKiEsn3pPxBAoGAJ0Gg
|
||||
gBJyEno+l7KrlwTKDMcX/53HHPB/f9vcSKA+LBlr0IGmKTWxXF+QBWqX3mDI6JWR
|
||||
C27nc/pLdg3W492agOgFbvFdT+erRczsxFgYyFITzibxGBIzIIcqKZVn4z4VcTKM
|
||||
ZkY++UbC+hQxJ7Lo2Xm5o8oByrMMeW91qc6FzjECgYAwQX10LEqlWJDogvZP3MN9
|
||||
AUrlZUGBYnjMu8vbiFY9n7DW+2gzbhL/AqzkXSgjzee+r/71aolT2gGvXPO7S290
|
||||
9Ep8SF9gz1yVaYMlyj0hedF7jNkVGBRWRo0BtUqaFhthOsiD0M+/bYq0D5YCkCTZ
|
||||
QOwUIF9JWN+l5JNRws+jGA==
|
||||
-----END PRIVATE KEY-----
|
||||
',
|
||||
'-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1DsHQgj0oD6UflrGF1c/
|
||||
9hUN+cm0FiSteMrQ5OCE7/n0DBJzG0PA/uHERFyMnRPzTs4J/oQ3x2xQ3/dcLYtD
|
||||
/tQvu+MAQOcWZW4WnvGQAdYXOYJkiahPvi2pX65jiIOUg30IbYmn+IbRKEXcRLLq
|
||||
UveuIsy6F3lICBPZWPOyQqpblNbYb25OtNbD4tqvFp3yCjfL50r7t9WEa/Oh3OLK
|
||||
MiHX9VmUqFOHKLhNkJjhZvY6+eTm6flEnyYO0Y6HHvWThY9JV94JB6hjs5draMX8
|
||||
8mafiqpYUC1mC5oizN2dxths9dfDBo2mp+8yFteRXrmntb93jWqhe2augsw2XJIs
|
||||
LwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
',
|
||||
'http://127.0.0.1/qyt_test.php?act=notify_receiver',
|
||||
100000.00, 10001, 10001, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());
|
||||
SELECT partners_id, name, orgNo, appKey, balance, callback FROM `yoshop_partners`;
|
||||
@@ -0,0 +1,67 @@
|
||||
; ============================================================
|
||||
; 企油通对接 · Supervisor 守护进程配置
|
||||
; ------------------------------------------------------------
|
||||
; 三个常驻队列消费者,缺一不可:
|
||||
; partners:queue 下单 -> 企油通 7.7 运单油费下发(含丢单兜底巡检 reconcile)
|
||||
; callback:queue 企油通 7.10 加油消费回调入队后的落库与状态更新
|
||||
; notify:queue 我方 -> 下单平台 结果回调(含 60s/5min/30min 退避重试)
|
||||
;
|
||||
; 【使用前必改】
|
||||
; 1) command 里的 PHP 路径:宝塔用 `ls /www/server/php/` 看版本,
|
||||
; 如 PHP 7.4 -> /www/server/php/74/bin/php
|
||||
; 2) directory:站点根目录(think 文件所在目录,不是 public)
|
||||
; 3) user:宝塔站点默认运行用户一般是 www
|
||||
; 4) stdout_logfile 目录需先存在:mkdir -p /www/wwwlogs/supervisor
|
||||
;
|
||||
; 【进程数说明】
|
||||
; partners:queue 可多进程(同一订单由 RedisLock 串行,安全)
|
||||
; callback:queue / notify:queue 建议保持单进程
|
||||
; ============================================================
|
||||
|
||||
[program:qyt-partners-queue]
|
||||
command=/www/server/php/74/bin/php think partners:queue
|
||||
directory=/www/wwwroot/www.hmzkw.com
|
||||
user=www
|
||||
numprocs=1
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startsecs=3
|
||||
startretries=99
|
||||
stopwaitsecs=10
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/www/wwwlogs/supervisor/qyt-partners-queue.log
|
||||
stdout_logfile_maxbytes=50MB
|
||||
stdout_logfile_backups=5
|
||||
|
||||
[program:qyt-callback-queue]
|
||||
command=/www/server/php/74/bin/php think callback:queue
|
||||
directory=/www/wwwroot/www.hmzkw.com
|
||||
user=www
|
||||
numprocs=1
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startsecs=3
|
||||
startretries=99
|
||||
stopwaitsecs=10
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/www/wwwlogs/supervisor/qyt-callback-queue.log
|
||||
stdout_logfile_maxbytes=50MB
|
||||
stdout_logfile_backups=5
|
||||
|
||||
[program:qyt-notify-queue]
|
||||
command=/www/server/php/74/bin/php think notify:queue
|
||||
directory=/www/wwwroot/www.hmzkw.com
|
||||
user=www
|
||||
numprocs=1
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startsecs=3
|
||||
startretries=99
|
||||
stopwaitsecs=10
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/www/wwwlogs/supervisor/qyt-notify-queue.log
|
||||
stdout_logfile_maxbytes=50MB
|
||||
stdout_logfile_backups=5
|
||||
@@ -1,10 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
Options +FollowSymlinks -Multiviews
|
||||
RewriteEngine On
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
|
||||
|
||||
SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
|
||||
</IfModule>
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
<?php
|
||||
/**
|
||||
* ============================================================
|
||||
* 慧明宝入站接口 · 联调测试脚本(模拟「下单平台」)
|
||||
* ------------------------------------------------------------
|
||||
* 放在 public/ 下,浏览器访问:http://你的域名/qyt_test.php
|
||||
* 也可命令行:php qyt_test.php share
|
||||
*
|
||||
* 它做四件事:
|
||||
* 1) 从数据库读取合作商(appKey / RSA 私钥 / orgNo)
|
||||
* 2) 按「慧明宝」规范组装 RSA+AES 信封并调用我方入站接口
|
||||
* 3) 展示明文请求 / 待签串 / 密文报文 / 服务端响应
|
||||
* 4) act=notify_receiver 作为回调接收端,解密+验签我方推送的
|
||||
* syb.notify.oilCard.change,并返回 {"code":"00"}
|
||||
*
|
||||
* ⚠️ 仅用于联调,正式环境请删除本文件。
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
const TEST_APPKEY = 'qyttest0000000000000000000001'; // 测试合作商 appKey
|
||||
const API_VERSION = '1.0.0';
|
||||
|
||||
date_default_timezone_set('Asia/Shanghai');
|
||||
$ROOT = dirname(__DIR__);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 基础工具
|
||||
// ------------------------------------------------------------
|
||||
function envConf($root)
|
||||
{
|
||||
$file = $root . '/.env';
|
||||
if (!is_file($file)) {
|
||||
throw new Exception('.env 不存在:' . $file);
|
||||
}
|
||||
$ini = parse_ini_file($file, true, INI_SCANNER_RAW) ?: [];
|
||||
$db = isset($ini['DATABASE']) ? $ini['DATABASE'] : [];
|
||||
return [
|
||||
'host' => isset($db['HOSTNAME']) ? $db['HOSTNAME'] : '127.0.0.1',
|
||||
'port' => isset($db['HOSTPORT']) ? $db['HOSTPORT'] : '3306',
|
||||
'name' => isset($db['DATABASE']) ? $db['DATABASE'] : 'oil',
|
||||
'user' => isset($db['USERNAME']) ? $db['USERNAME'] : 'root',
|
||||
'pass' => isset($db['PASSWORD']) ? $db['PASSWORD'] : '',
|
||||
'char' => isset($db['CHARSET']) ? $db['CHARSET'] : 'utf8',
|
||||
];
|
||||
}
|
||||
|
||||
function db($root)
|
||||
{
|
||||
static $pdo = null;
|
||||
if ($pdo === null) {
|
||||
$c = envConf($root);
|
||||
$dsn = 'mysql:host=' . $c['host'] . ';port=' . $c['port'] . ';dbname=' . $c['name'] . ';charset=' . $c['char'];
|
||||
$pdo = new PDO($dsn, $c['user'], $c['pass'], [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]);
|
||||
}
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
/** 读取合作商(下单平台账户) */
|
||||
function getPartner($root, $appKey)
|
||||
{
|
||||
$st = db($root)->prepare('SELECT * FROM yoshop_partners WHERE appKey = ? LIMIT 1');
|
||||
$st->execute([$appKey]);
|
||||
$row = $st->fetch();
|
||||
if (!$row) {
|
||||
throw new Exception('未找到合作商,appKey=' . $appKey . '(请先执行 deploy/seed_test_partner.sql)');
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
/** 平台公钥:加密 AES 密钥 / 验签我方回调 */
|
||||
function platformPublicKey($root)
|
||||
{
|
||||
$p = $root . '/rsa/public_key.pem';
|
||||
if (!is_file($p)) {
|
||||
throw new Exception('平台公钥不存在:' . $p);
|
||||
}
|
||||
return file_get_contents($p);
|
||||
}
|
||||
|
||||
function uniqueRequestId($appKey)
|
||||
{
|
||||
return $appKey . strtoupper(bin2hex(random_bytes(12)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装请求信封(口径对齐 app\common\crypto\RsaUtil::processResponse)
|
||||
* 待签串:http_build_query([version, appKey, method, requestId, body])
|
||||
* body :json_encode($body, JSON_UNESCAPED_UNICODE)
|
||||
* 签名 :SHA256withRSA,用【合作商私钥】
|
||||
* AES :AES-256-ECB,随机 32 字节密钥;密钥用【平台公钥】RSA 加密
|
||||
*/
|
||||
function buildEnvelope($partner, $platformPub, $method, array $body)
|
||||
{
|
||||
$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE);
|
||||
$requestId = uniqueRequestId($partner['appKey']);
|
||||
|
||||
$signData = http_build_query([
|
||||
'version' => API_VERSION,
|
||||
'appKey' => $partner['appKey'],
|
||||
'method' => $method,
|
||||
'requestId' => $requestId,
|
||||
'body' => $bodyJson,
|
||||
]);
|
||||
|
||||
$pkey = openssl_pkey_get_private($partner['privateKey']);
|
||||
if ($pkey === false) {
|
||||
throw new Exception('合作商私钥无效:' . openssl_error_string());
|
||||
}
|
||||
$signature = '';
|
||||
openssl_sign($signData, $signature, $pkey, OPENSSL_ALGO_SHA256);
|
||||
|
||||
// AES-256-ECB 加密 body(与服务端 encryptData/decryptData 完全一致)
|
||||
$aesKey = openssl_random_pseudo_bytes(32);
|
||||
$encBody = base64_encode(openssl_encrypt($bodyJson, 'AES-256-ECB', $aesKey, OPENSSL_PKCS1_PADDING));
|
||||
|
||||
// 平台公钥加密 AES 密钥
|
||||
$pub = openssl_pkey_get_public($platformPub);
|
||||
if ($pub === false) {
|
||||
throw new Exception('平台公钥无效:' . openssl_error_string());
|
||||
}
|
||||
$encKey = '';
|
||||
openssl_public_encrypt($aesKey, $encKey, $pub, OPENSSL_PKCS1_PADDING);
|
||||
|
||||
return [
|
||||
'headers' => [
|
||||
'version' => API_VERSION,
|
||||
'appKey' => $partner['appKey'],
|
||||
'method' => $method,
|
||||
'requestId' => $requestId,
|
||||
'sign' => base64_encode($signature),
|
||||
],
|
||||
'body' => ['key' => base64_encode($encKey), 'data' => $encBody],
|
||||
'plain' => $body,
|
||||
'signData' => $signData,
|
||||
];
|
||||
}
|
||||
|
||||
function httpPost($url, array $headers, array $jsonBody)
|
||||
{
|
||||
$h = ['Content-Type: application/json', 'Charset: UTF-8'];
|
||||
foreach ($headers as $k => $v) {
|
||||
$h[] = $k . ': ' . $v;
|
||||
}
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => json_encode($jsonBody, JSON_UNESCAPED_UNICODE),
|
||||
CURLOPT_HTTPHEADER => $h,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 60,
|
||||
CURLOPT_SSL_VERIFYPEER => false,
|
||||
CURLOPT_SSL_VERIFYHOST => false,
|
||||
]);
|
||||
$resp = curl_exec($ch);
|
||||
$err = curl_error($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
return ['http' => $code, 'body' => $resp, 'error' => $err];
|
||||
}
|
||||
|
||||
/** 入站接口地址:public/partners.php/<控制器>/<方法> */
|
||||
function apiUrl($path)
|
||||
{
|
||||
if (!empty($_GET['api'])) {
|
||||
return rtrim($_GET['api'], '/') . '/partners.php' . $path;
|
||||
}
|
||||
if (PHP_SAPI === 'cli') {
|
||||
return 'http://127.0.0.1/partners.php' . $path;
|
||||
}
|
||||
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||
return $scheme . '://' . $_SERVER['HTTP_HOST'] . '/partners.php' . $path;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 回调接收端(模拟下单平台的 callback 地址)
|
||||
// 我方 NotifyQueue 用 RsaUtil::prepareRequest 推送,注意它的待签串是
|
||||
// 「原样拼接」,与入站的 http_build_query 不同。
|
||||
// ------------------------------------------------------------
|
||||
function notifyReceiver($root)
|
||||
{
|
||||
$raw = file_get_contents('php://input');
|
||||
$headers = [];
|
||||
foreach ($_SERVER as $k => $v) {
|
||||
if (strpos($k, 'HTTP_') === 0) {
|
||||
$headers[strtolower(str_replace('_', '', substr($k, 5)))] = $v;
|
||||
}
|
||||
}
|
||||
$log = $root . '/runtime/qyt_test_notify.log';
|
||||
@file_put_contents($log, date('Y-m-d H:i:s') . " 收到回调\nheaders=" . json_encode($headers, 320) . "\nbody=" . $raw . "\n", FILE_APPEND);
|
||||
|
||||
try {
|
||||
$data = json_decode($raw, true);
|
||||
$appKey = isset($headers['appkey']) ? $headers['appkey'] : TEST_APPKEY;
|
||||
$partner = getPartner($root, $appKey);
|
||||
|
||||
// 1) 合作商私钥解出 AES 密钥
|
||||
$pkey = openssl_pkey_get_private($partner['privateKey']);
|
||||
$aesKey = '';
|
||||
openssl_private_decrypt(base64_decode($data['key']), $aesKey, $pkey, OPENSSL_PKCS1_PADDING);
|
||||
// 2) 解密 body
|
||||
$plain = openssl_decrypt(base64_decode($data['data']), 'AES-256-ECB', $aesKey, OPENSSL_PKCS1_PADDING);
|
||||
$body = json_decode($plain, true);
|
||||
// 3) 平台公钥验签
|
||||
$signData = 'version=' . API_VERSION
|
||||
. '&appKey=' . $partner['appKey']
|
||||
. '&method=' . (isset($headers['method']) ? $headers['method'] : '')
|
||||
. '&requestId=' . (isset($headers['requestid']) ? $headers['requestid'] : '')
|
||||
. '&body=' . json_encode($body);
|
||||
$sign = isset($headers['sign']) ? $headers['sign'] : '';
|
||||
$ok = openssl_verify($signData, base64_decode($sign), openssl_pkey_get_public(platformPublicKey($root)), OPENSSL_ALGO_SHA256);
|
||||
|
||||
@file_put_contents($log, '解密结果=' . json_encode($body, 320) . ' 验签=' . ($ok === 1 ? 'OK' : 'FAIL') . "\n\n", FILE_APPEND);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['code' => '00', 'message' => '请求成功'], JSON_UNESCAPED_UNICODE);
|
||||
} catch (Throwable $e) {
|
||||
@file_put_contents($log, '异常:' . $e->getMessage() . "\n\n", FILE_APPEND);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['code' => '99', 'message' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 各接口默认入参
|
||||
// ------------------------------------------------------------
|
||||
function defaultBody($act, $orgNo)
|
||||
{
|
||||
$saleOrderNo = 'TEST' . date('YmdHis') . mt_rand(100, 999);
|
||||
$oilCardNo = isset($_GET['oilCardNo']) ? $_GET['oilCardNo'] : '';
|
||||
$mobile = isset($_GET['mobile']) ? $_GET['mobile'] : '13800000001';
|
||||
|
||||
if ($act === 'share') {
|
||||
return [
|
||||
'method' => 'syb.oil.oilCard.share',
|
||||
'path' => '/oilCard/share',
|
||||
'body' => [
|
||||
'orgNo' => $orgNo,
|
||||
'amount' => isset($_GET['amount']) ? $_GET['amount'] : '100.00',
|
||||
'mobile' => $mobile,
|
||||
'name' => isset($_GET['name']) ? $_GET['name'] : '张三',
|
||||
'saleOrderNo' => $saleOrderNo,
|
||||
'oilCardType' => 'zsy_ticket',
|
||||
],
|
||||
];
|
||||
}
|
||||
if ($act === 'qrcode') {
|
||||
return [
|
||||
'method' => 'syb.pay.qrCode.request',
|
||||
'path' => '/oilCard/getPayQrCode',
|
||||
'body' => ['orgNo' => $orgNo, 'oilCardNo' => $oilCardNo, 'mobile' => $mobile],
|
||||
];
|
||||
}
|
||||
if ($act === 'status') {
|
||||
return [
|
||||
'method' => 'syb.oil.oilCard.orderStatus',
|
||||
'path' => '/oilCard/orderStatus',
|
||||
'body' => ['orgNo' => $orgNo, 'oilCardNo' => $oilCardNo],
|
||||
];
|
||||
}
|
||||
if ($act === 'sharelist') {
|
||||
return [
|
||||
'method' => 'syb.oil.oilCard.shareList',
|
||||
'path' => '/oilCard/shareList',
|
||||
'body' => [
|
||||
'orgNo' => $orgNo,
|
||||
'mobile' => $mobile,
|
||||
'beginDate' => date('Ymd', strtotime('-7 day')),
|
||||
'endDate' => date('Ymd'),
|
||||
'pageLimit' => '10',
|
||||
'pageNum' => '1',
|
||||
],
|
||||
];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 主流程
|
||||
// ------------------------------------------------------------
|
||||
$act = isset($_GET['act']) ? $_GET['act'] : (isset($argv[1]) ? $argv[1] : '');
|
||||
$fatal = '';
|
||||
$result = null;
|
||||
$partner = null;
|
||||
|
||||
try {
|
||||
if ($act === 'notify_receiver') {
|
||||
notifyReceiver($ROOT);
|
||||
}
|
||||
$partner = getPartner($ROOT, TEST_APPKEY);
|
||||
$platformPub = platformPublicKey($ROOT);
|
||||
|
||||
if (in_array($act, ['share', 'qrcode', 'status', 'sharelist'], true)) {
|
||||
$def = defaultBody($act, $partner['orgNo']);
|
||||
$env = buildEnvelope($partner, $platformPub, $def['method'], $def['body']);
|
||||
$url = apiUrl($def['path']);
|
||||
$rsp = httpPost($url, $env['headers'], $env['body']);
|
||||
$result = ['def' => $def, 'env' => $env, 'url' => $url, 'rsp' => $rsp];
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$fatal = $e->getMessage();
|
||||
}
|
||||
|
||||
// ---------- 命令行输出 ----------
|
||||
if (PHP_SAPI === 'cli') {
|
||||
if ($fatal !== '') {
|
||||
echo '错误:' . $fatal . "\n";
|
||||
exit(1);
|
||||
}
|
||||
if (!$result) {
|
||||
echo "用法:php qyt_test.php [share|qrcode|status|sharelist]\n";
|
||||
exit;
|
||||
}
|
||||
echo '接口:' . $result['def']['method'] . "\n";
|
||||
echo 'URL :' . $result['url'] . "\n";
|
||||
echo '明文:' . json_encode($result['env']['plain'], 320) . "\n";
|
||||
echo 'HTTP:' . $result['rsp']['http'] . "\n";
|
||||
echo '响应:' . $result['rsp']['body'] . "\n";
|
||||
if ($result['rsp']['error'] !== '') {
|
||||
echo 'cURL:' . $result['rsp']['error'] . "\n";
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
$rspArr = $result ? json_decode($result['rsp']['body'], true) : null;
|
||||
$okFlag = is_array($rspArr) && isset($rspArr['code']) && $rspArr['code'] === '00';
|
||||
$newOil = is_array($rspArr) && isset($rspArr['data']['oilCardNo']) ? $rspArr['data']['oilCardNo'] : '';
|
||||
$curOil = isset($_GET['oilCardNo']) ? $_GET['oilCardNo'] : '';
|
||||
?><!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>慧明宝入站接口 · 联调测试</title>
|
||||
<style>
|
||||
body{font:14px/1.7 -apple-system,"Microsoft YaHei",sans-serif;margin:0;background:#f5f6f8;color:#222}
|
||||
.wrap{max-width:1000px;margin:0 auto;padding:24px}
|
||||
h1{font-size:20px;margin:0 0 4px}
|
||||
.sub{color:#888;font-size:13px;margin-bottom:18px}
|
||||
.card{background:#fff;border:1px solid #e6e8eb;border-radius:8px;padding:16px 18px;margin-bottom:16px}
|
||||
.card h2{font-size:15px;margin:0 0 12px;padding-bottom:8px;border-bottom:1px solid #eee}
|
||||
.btns a{display:inline-block;margin:0 8px 8px 0;padding:7px 16px;background:#1890ff;color:#fff;
|
||||
border-radius:4px;text-decoration:none;font-size:13px}
|
||||
.btns a.g{background:#52c41a}.btns a.o{background:#faad14}.btns a.p{background:#722ed1}
|
||||
table{border-collapse:collapse;width:100%;font-size:13px}
|
||||
th,td{border:1px solid #eee;padding:6px 10px;text-align:left;vertical-align:top;word-break:break-all}
|
||||
th{background:#fafafa;width:150px;font-weight:600;color:#555}
|
||||
pre{background:#282c34;color:#abb2bf;padding:12px;border-radius:6px;overflow:auto;
|
||||
font-size:12px;line-height:1.6;margin:0;white-space:pre-wrap;word-break:break-all}
|
||||
.ok{color:#52c41a;font-weight:600}.err{color:#ff4d4f;font-weight:600}
|
||||
.tip{background:#fffbe6;border:1px solid #ffe58f;padding:10px 14px;border-radius:6px;font-size:13px;margin-bottom:16px}
|
||||
.lbl{margin:12px 0 6px;color:#555}
|
||||
</style>
|
||||
</head>
|
||||
<body><div class="wrap">
|
||||
<h1>慧明宝入站接口 · 联调测试</h1>
|
||||
<div class="sub">模拟「下单平台」调用我方 API(RSA + AES 信封)。仅供联调,正式环境请删除本文件。</div>
|
||||
|
||||
<?php if ($fatal !== ''): ?>
|
||||
<div class="card"><h2>初始化失败</h2><p class="err"><?php echo htmlspecialchars($fatal); ?></p></div>
|
||||
<?php else: ?>
|
||||
|
||||
<div class="card">
|
||||
<h2>当前合作商</h2>
|
||||
<table>
|
||||
<tr><th>partners_id</th><td><?php echo (int)$partner['partners_id']; ?></td></tr>
|
||||
<tr><th>名称</th><td><?php echo htmlspecialchars($partner['name']); ?></td></tr>
|
||||
<tr><th>orgNo</th><td><?php echo htmlspecialchars($partner['orgNo']); ?></td></tr>
|
||||
<tr><th>appKey</th><td><?php echo htmlspecialchars($partner['appKey']); ?></td></tr>
|
||||
<tr><th>余额</th><td><b><?php echo htmlspecialchars($partner['balance']); ?></b> 元 (下单会扣减,不足返回 2028)</td></tr>
|
||||
<tr><th>回调地址</th><td><?php echo htmlspecialchars($partner['callback']); ?></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tip">
|
||||
接口地址默认取当前域名;如需指定,链接后加 <code>&api=http://你的域名</code>。<br>
|
||||
<b>下单前提</b>:三个队列进程已启动(partners:queue / callback:queue / notify:queue)、Redis 可用、合作商余额充足。
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>发起测试</h2>
|
||||
<div class="btns">
|
||||
<a class="g" href="?act=share">① 下单分油 (share)</a>
|
||||
<a class="o" href="?act=qrcode&oilCardNo=<?php echo urlencode($curOil); ?>">② 获取加油链接 (qrCode)</a>
|
||||
<a class="p" href="?act=status&oilCardNo=<?php echo urlencode($curOil); ?>">③ 订单状态 (orderStatus)</a>
|
||||
<a href="?act=sharelist">④ 分油记录 (shareList)</a>
|
||||
</div>
|
||||
<div class="sub" style="margin:6px 0 0">
|
||||
②③ 需要 oilCardNo:先点①拿到后会自动带上。<br>
|
||||
① 可自定义参数:<code>?act=share&amount=50.00&mobile=13800000002&name=李四</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($result): ?>
|
||||
<div class="card">
|
||||
<h2>请求 · <?php echo htmlspecialchars($result['def']['method']); ?></h2>
|
||||
<table>
|
||||
<tr><th>URL</th><td><?php echo htmlspecialchars($result['url']); ?></td></tr>
|
||||
<tr><th>requestId</th><td><?php echo htmlspecialchars($result['env']['headers']['requestId']); ?></td></tr>
|
||||
</table>
|
||||
<p class="lbl">明文 body</p>
|
||||
<pre><?php echo htmlspecialchars(json_encode($result['env']['plain'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); ?></pre>
|
||||
<p class="lbl">待签串(http_build_query)</p>
|
||||
<pre><?php echo htmlspecialchars($result['env']['signData']); ?></pre>
|
||||
<p class="lbl">实际发送(密文信封)</p>
|
||||
<pre><?php echo htmlspecialchars(json_encode($result['env']['body'], JSON_PRETTY_PRINT)); ?></pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>响应 <?php echo $okFlag ? '<span class="ok">成功</span>' : '<span class="err">失败</span>'; ?></h2>
|
||||
<table>
|
||||
<tr><th>HTTP 状态</th><td><?php echo (int)$result['rsp']['http']; ?></td></tr>
|
||||
<?php if ($result['rsp']['error'] !== ''): ?>
|
||||
<tr><th>cURL 错误</th><td class="err"><?php echo htmlspecialchars($result['rsp']['error']); ?></td></tr>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
<p class="lbl">响应体</p>
|
||||
<pre><?php echo htmlspecialchars(is_array($rspArr) ? json_encode($rspArr, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $result['rsp']['body']); ?></pre>
|
||||
<?php if ($newOil !== ''): ?>
|
||||
<div class="btns" style="margin-top:14px">
|
||||
<a class="o" href="?act=qrcode&oilCardNo=<?php echo urlencode($newOil); ?>">用 <?php echo htmlspecialchars($newOil); ?> 取加油链接</a>
|
||||
<a class="p" href="?act=status&oilCardNo=<?php echo urlencode($newOil); ?>">查该单状态</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
</div></body></html>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
// [ 企油通 7.10 加油消费回调入口 ]
|
||||
namespace think;
|
||||
|
||||
// 检测PHP环境
|
||||
if (version_compare(PHP_VERSION, '7.1.0', '<')) die('require PHP > 7.1.0 !');
|
||||
|
||||
// 加载核心文件
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// 执行HTTP应用并响应
|
||||
$http = (new App())->http;
|
||||
|
||||
// 手动指定路由
|
||||
$_SERVER['PATH_INFO'] = '/qytNotify/consume';
|
||||
|
||||
// 绑定 api 应用
|
||||
$response = $http->name('api')->run();
|
||||
|
||||
$response->send();
|
||||
|
||||
$http->end($response);
|
||||
@@ -5,6 +5,7 @@ window.publicConfig = {
|
||||
// 例如: https://www.你的域名.com/index.php?s=/store
|
||||
// BASE_API: '../index.php?s=/store'
|
||||
// BASE_API: 'http://139.129.21.253/index.php?s=/store'
|
||||
BASE_API: 'https://www.hmzkw.com/index.php?s=/store',
|
||||
BASE_DOMAIN: 'https://www.hmzkw.com/'
|
||||
// BASE_DOMAIN: 'http://139.129.21.253/'
|
||||
BASE_API: 'http://47.104.73.7/index.php?s=/store',
|
||||
BASE_DOMAIN: 'http:/47.104.73.7/'
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1 @@
|
||||
.ant-modal-body[data-v-547be636]{padding-top:0!important}.ant-form-item[data-v-547be636]{margin-bottom:15px}.ant-tabs-nav .ant-tabs-tab[data-v-547be636]{padding:10px 16px}.ant-card-body[data-v-c8e4e012]{padding:22px 29px 25px}.tab-list[data-v-c8e4e012]{margin-right:20px}.ant-card-body[data-v-78d16cc2]{padding:22px 29px 25px}.tab-list[data-v-78d16cc2]{margin-right:20px}
|
||||
+1
@@ -0,0 +1 @@
|
||||
.platform-icon{font-size:16px}.platform-icon .icon{margin-right:5px}.platform-icon .icon:last-child{margin-right:0}.platform-icon .H5-WEIXIN,.platform-icon .MP-WEIXIN{color:#04be02}.platform-icon .H5{color:#e44c27}.user-info[data-v-3d0bc671]{width:160px;height:55px;line-height:1.3}.user-info .in-left[data-v-3d0bc671]{float:left;margin-right:10px}.user-info .in-left img[data-v-3d0bc671]{width:40px;height:40px;border-radius:50%}.user-info .in-right[data-v-3d0bc671]{float:left;width:100px;height:100%}.user-info .in-right .user-name[data-v-3d0bc671]{margin-bottom:2px}.goods-info[data-v-6d71ff35]{width:270px;line-height:1.3;white-space:normal}.goods-info .in-left[data-v-6d71ff35]{float:left;margin-right:8px}.goods-info .in-left img[data-v-6d71ff35]{width:60px;height:60px}.goods-info .in-right[data-v-6d71ff35]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;float:left;height:60px}.goods-info .in-right .title[data-v-6d71ff35]{font-size:13px;margin-bottom:5px}.goods-info .in-right .subtitle[data-v-6d71ff35]{font-size:12px;color:#7b7b7b}.goods-info .goods-props[data-v-6d71ff35]{color:#8a8a8a;font-size:12px;overflow:hidden}.goods-info .goods-props-item[data-v-6d71ff35]{display:inline-block;margin-right:4px}
|
||||
+1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1 @@
|
||||
.ant-form-item[data-v-1e3b16a8]{margin-bottom:15px}[data-v-1e3b16a8] .ant-form-item-control{padding-left:10px}[data-v-1e3b16a8] .ant-form-item-control .ant-form-item-control{padding-left:0}.ant-divider[data-v-1e3b16a8]{margin-top:50px!important}.ant-form-item[data-v-42865d94]{margin-bottom:15px}[data-v-42865d94] .ant-form-item-control{padding-left:10px}[data-v-42865d94] .ant-form-item-control .ant-form-item-control{padding-left:0}.ant-divider[data-v-42865d94]{margin-top:60px!important}.ant-form-item[data-v-0d8ee9ca]{margin-bottom:24px}[data-v-0d8ee9ca] .ant-form-item-control{padding-left:10px}[data-v-0d8ee9ca] .ant-form-item-control .ant-form-item-control{padding-left:0}.ant-divider[data-v-0d8ee9ca]{margin-top:60px!important}
|
||||
@@ -0,0 +1 @@
|
||||
.ant-card-body[data-v-650748d8],.ant-card-body[data-v-46700646]{padding:22px 29px 25px}.flex-box[data-v-46700646]{display:-webkit-box;display:-ms-flexbox;display:flex}.button-group[data-v-46700646]{margin-right:10px}.form-total[data-v-46700646]{color:#1890ff;margin-right:10px;font-size:20px;font-weight:500}.ant-card-body[data-v-1b1d1568]{padding:22px 29px 25px}.tab-list[data-v-1b1d1568]{margin-right:20px}.ant-card-body[data-v-614fa1f7],.ant-card-body[data-v-669bb9b6],.ant-card-body[data-v-2466693d],.ant-card-body[data-v-e7f9db82]{padding:22px 29px 25px}.tab-list[data-v-614fa1f7]{margin-right:20px}.ant-card-body[data-v-58bb637f]{padding:22px 29px 25px}.tab-list[data-v-58bb637f]{margin-right:20px}.preview-box[data-v-58bb637f]{width:120px;height:80px;line-height:80px}.preview-box img[data-v-58bb637f]{display:block;max-width:100%;max-height:100%}[data-v-74b71be6] .ant-form-item-control{padding-left:10px}[data-v-74b71be6] .ant-form-item-control .ant-form-item-control{padding-left:0}.ant-divider[data-v-74b71be6]{margin-top:50px!important}.table-rules .operation{text-align:right}.table-rules .operation a{font-size:13px;margin-left:6px}.table-rules .content{color:#505050;white-space:normal}.table-rules .content .city-name{font-size:12.5px;color:#7b7b7b}.ant-checkbox-wrapper+.ant-checkbox-wrapper[data-v-4c243eb9]{margin-left:0}.ant-checkbox-wrapper[data-v-4c243eb9]{margin-right:14px;margin-bottom:18px}[data-v-4c243eb9] .ant-form-item-control{padding-left:10px}[data-v-4c243eb9] .ant-form-item-control .ant-form-item-control{padding-left:0}
|
||||
@@ -0,0 +1 @@
|
||||
[data-v-6bcd977c]{margin:0;padding:0;-webkit-tap-highlight-color:transparent}[data-v-6bcd977c],[data-v-6bcd977c]:after,[data-v-6bcd977c]:before{-webkit-box-sizing:border-box;box-sizing:border-box}address[data-v-6bcd977c],applet[data-v-6bcd977c],area[data-v-6bcd977c],article[data-v-6bcd977c],aside[data-v-6bcd977c],blockquote[data-v-6bcd977c],fieldset[data-v-6bcd977c],figcaption[data-v-6bcd977c],figure[data-v-6bcd977c],footer[data-v-6bcd977c],header[data-v-6bcd977c],map[data-v-6bcd977c],section[data-v-6bcd977c],summary[data-v-6bcd977c]{display:block}body[data-v-6bcd977c]{font:12px/1.5 Microsoft YaHei,tahoma,arial,Hiragino Sans GB,\\5b8b\4f53,sans-serif;background:#fff}.container[data-v-6bcd977c]{text-align:center;max-width:640px}.img[data-v-6bcd977c]{width:60px;vertical-align:middle}.box-title[data-v-6bcd977c]{line-height:30px}.box-p[data-v-6bcd977c]{line-height:35px;text-align:left;height:40px}.text-val[data-v-6bcd977c]{display:inline-block;width:240px;border:1px solid grey;height:29px;line-height:25px;padding:0 5px;background-color:#ededed}.copy[data-v-6bcd977c]{margin-left:10px;color:#000;font-size:13px;border:1px solid;padding:5px;background-color:#e9e9e9}.sure-but[data-v-6bcd977c]{display:inline-block;width:100%;height:45px;line-height:45px;background-color:#4caf50;color:#fff;text-align:center;margin-bottom:60px;margin-top:20px;border-radius:5px;font-size:21px}.text-input[data-v-6bcd977c]{display:inline-block;width:176px;border:1px solid grey;height:29px;line-height:25px;padding:0 5px}.tick-text[data-v-6bcd977c]{line-height:30px}.tick-text-no[data-v-6bcd977c]{height:60px;line-height:60px;font-weight:600}.explain[data-v-6bcd977c]{color:red;font-weight:600;width:90%;margin:0 auto;text-align:left;font-size:16px}.explain-text[data-v-6bcd977c]{text-align:left;width:90%;margin:0 auto;height:36px}.explain-blue[data-v-6bcd977c]{color:#fff;font-weight:unset;width:80%;font-size:19px;background-color:#40a9ff;border-radius:5px}.orange[data-v-6bcd977c]{color:#ff5200;font-weight:600}.text-box-top[data-v-6bcd977c]{width:90%;margin:0 auto}.red[data-v-6bcd977c]{color:red}.title[data-v-6bcd977c]{height:75px;line-height:75px}.title-text[data-v-6bcd977c]{font-size:40px;vertical-align:middle;margin-left:15px}.money[data-v-6bcd977c]{font-size:40px;color:#ff5200;margin-right:8px}.qrcode[data-v-6bcd977c]{width:70%}.qrcode-div[data-v-6bcd977c]{border-top:1px solid #ebebeb;border-bottom:1px solid #ebebeb;margin:20px 0 20px 0}.black[data-v-6bcd977c]{color:#000!important;font-size:13px}.center[data-v-6bcd977c]{text-align:center;margin:15px auto!important}.min[data-v-6bcd977c],.sec[data-v-6bcd977c]{color:red}.ali-img[data-v-6bcd977c]{width:170px;vertical-align:middle}.ali-explain[data-v-6bcd977c]{font-weight:600;width:90%;margin:0 auto;font-size:15px}.ali-title[data-v-6bcd977c]{height:125px;line-height:125px}.ali-a[data-v-6bcd977c]{color:#fff;display:inline-block;width:100%}.ali-time[data-v-6bcd977c]{color:#000;font-size:14px}.ali-explain-trip[data-v-6bcd977c]{margin-top:27%!important}.down img[data-v-6bcd977c]{width:270px!important}.box[data-v-6bcd977c]{margin-top:10%}.c-red[data-v-6bcd977c]{color:#c7171e}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.card-title[data-v-0fc1832e]{font-size:14px;font-weight:700;margin-bottom:15px}.statistics[data-v-0fc1832e]{line-height:1}.statistics .ant-card .ant-card-body[data-v-0fc1832e]{height:100%;padding:30px 40px}.statistics .col-left[data-v-0fc1832e]{margin-right:25px;font-size:24px;color:#4799ff}.statistics .col-left .icon-body[data-v-0fc1832e]{width:58px;height:58px;border-radius:50%;background-color:#eff6ff}.statistics .col-right[data-v-0fc1832e]{margin-top:-5px}.statistics .col-right .keynote[data-v-0fc1832e]{font-size:26px}.pending[data-v-0fc1832e]{text-align:center;padding:15px 0}.pending .item[data-v-0fc1832e]{display:inline-block;padding:0 20px}.pending .item a[data-v-0fc1832e]{color:unset}.pending .item a[data-v-0fc1832e]:hover{color:#1890ff}.pending .name[data-v-0fc1832e]{font-weight:700;margin-bottom:10px;font-size:13.6px}.pending .value[data-v-0fc1832e]{font-weight:700;color:red;font-size:16px}.functions .item[data-v-0fc1832e]{display:block;padding:13px 20px;cursor:pointer}.functions .item[data-v-0fc1832e]:hover{color:#1890ff}.functions .name[data-v-0fc1832e]{font-size:13px;margin-left:10px}.functions .icon[data-v-0fc1832e]{width:28px;height:28px;color:#fff;font-size:13px;border-radius:5px}.overview a[data-v-0fc1832e]{color:unset}.overview a[data-v-0fc1832e]:hover{color:#1890ff}.overview .item[data-v-0fc1832e]{padding:13px 20px}.overview .col-left[data-v-0fc1832e]{color:#4799ff;font-size:28px;margin-right:35px}.overview .col-left .icon-body[data-v-0fc1832e]{width:58px;height:58px;border-radius:50%;background-color:#eff6ff}.overview .col-right .name[data-v-0fc1832e]{font-size:13px;color:#666}.overview .col-right .value[data-v-0fc1832e]{color:#000;font-size:24px}.overview .col-right .yesterday[data-v-0fc1832e]{display:none;font-size:12px;color:#999}
|
||||
@@ -0,0 +1 @@
|
||||
.ant-form-item .ant-form-item[data-v-0a4749e4],.ant-form-item .ant-form-item[data-v-65eaa220],.ant-form-item .ant-form-item[data-v-270e929b]{margin-bottom:0}[data-v-65eaa220] .ant-form-item-control{padding-left:10px}[data-v-65eaa220] .ant-form-item-control .ant-form-item-control{padding-left:0}.ant-form-item .ant-form-item[data-v-3a1c101e]{margin-bottom:0}[data-v-3a1c101e] .ant-form-item-control{padding-left:10px}[data-v-3a1c101e] .ant-form-item-control .ant-form-item-control{padding-left:0}.ant-form-item .ant-form-item[data-v-e0c5fd3e]{margin-bottom:0}[data-v-e0c5fd3e] .ant-form-item-control{padding-left:10px}[data-v-e0c5fd3e] .ant-form-item-control .ant-form-item-control{padding-left:0}
|
||||
@@ -0,0 +1 @@
|
||||
.pagination[data-v-57882a87]{margin-top:16px}.pagination .ant-pagination[data-v-57882a87]{float:right}.ant-table table[data-v-57882a87]{border:none;border-collapse:collapse}.ant-table .ant-table-thead>tr[data-v-57882a87]{border:1px solid #e8e8e8}.ant-table tr.order-empty[data-v-57882a87]{height:15px;border:1px solid #fff}.ant-table tr.order-empty td[data-v-57882a87]{padding:0;border-right:none;border-left:none;background:none!important}.ant-table-thead>tr>th[data-v-57882a87]{border-right:none;border-bottom:none;padding:12px 12px;font-weight:700}.ant-table-tbody>tr>td[data-v-57882a87]{border-right:1px solid #e8e8e8;border-left:1px solid #e8e8e8;padding:12px 12px}.form-total[data-v-57882a87]{color:#1890ff;margin-right:10px;font-size:20px;font-weight:500}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user