test
This commit is contained in:
Submodule digital_doctor/vendor/wanghua/general-utility-tools-php deleted from 622c42b186
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/HEAD
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/HEAD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/ORIG_HEAD
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/ORIG_HEAD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177
|
||||
16
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/config
vendored
Normal file
16
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/config
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = false
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
symlinks = false
|
||||
ignorecase = true
|
||||
[remote "origin"]
|
||||
url = https://gitee.com/drop_drop/general_utility_tools_php.git
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[branch "master"]
|
||||
remote = origin
|
||||
merge = refs/heads/master
|
||||
[remote "composer"]
|
||||
url = https://gitee.com/drop_drop/general_utility_tools_php.git
|
||||
fetch = +refs/heads/*:refs/remotes/composer/*
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/description
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/description
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
15
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/applypatch-msg.sample
vendored
Normal file
15
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/applypatch-msg.sample
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message taken by
|
||||
# applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit. The hook is
|
||||
# allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "applypatch-msg".
|
||||
|
||||
. git-sh-setup
|
||||
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
|
||||
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
|
||||
:
|
||||
24
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/commit-msg.sample
vendored
Normal file
24
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/commit-msg.sample
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message.
|
||||
# Called by "git commit" with one argument, the name of the file
|
||||
# that has the commit message. The hook should exit with non-zero
|
||||
# status after issuing an appropriate message if it wants to stop the
|
||||
# commit. The hook is allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "commit-msg".
|
||||
|
||||
# Uncomment the below to add a Signed-off-by line to the message.
|
||||
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
|
||||
# hook is more suited to it.
|
||||
#
|
||||
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
||||
|
||||
# This example catches duplicate Signed-off-by lines.
|
||||
|
||||
test "" = "$(grep '^Signed-off-by: ' "$1" |
|
||||
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
|
||||
echo >&2 Duplicate Signed-off-by lines.
|
||||
exit 1
|
||||
}
|
||||
174
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/fsmonitor-watchman.sample
vendored
Normal file
174
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/fsmonitor-watchman.sample
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IPC::Open2;
|
||||
|
||||
# An example hook script to integrate Watchman
|
||||
# (https://facebook.github.io/watchman/) with git to speed up detecting
|
||||
# new and modified files.
|
||||
#
|
||||
# The hook is passed a version (currently 2) and last update token
|
||||
# formatted as a string and outputs to stdout a new update token and
|
||||
# all files that have been modified since the update token. Paths must
|
||||
# be relative to the root of the working tree and separated by a single NUL.
|
||||
#
|
||||
# To enable this hook, rename this file to "query-watchman" and set
|
||||
# 'git config core.fsmonitor .git/hooks/query-watchman'
|
||||
#
|
||||
my ($version, $last_update_token) = @ARGV;
|
||||
|
||||
# Uncomment for debugging
|
||||
# print STDERR "$0 $version $last_update_token\n";
|
||||
|
||||
# Check the hook interface version
|
||||
if ($version ne 2) {
|
||||
die "Unsupported query-fsmonitor hook version '$version'.\n" .
|
||||
"Falling back to scanning...\n";
|
||||
}
|
||||
|
||||
my $git_work_tree = get_working_dir();
|
||||
|
||||
my $retry = 1;
|
||||
|
||||
my $json_pkg;
|
||||
eval {
|
||||
require JSON::XS;
|
||||
$json_pkg = "JSON::XS";
|
||||
1;
|
||||
} or do {
|
||||
require JSON::PP;
|
||||
$json_pkg = "JSON::PP";
|
||||
};
|
||||
|
||||
launch_watchman();
|
||||
|
||||
sub launch_watchman {
|
||||
my $o = watchman_query();
|
||||
if (is_work_tree_watched($o)) {
|
||||
output_result($o->{clock}, @{$o->{files}});
|
||||
}
|
||||
}
|
||||
|
||||
sub output_result {
|
||||
my ($clockid, @files) = @_;
|
||||
|
||||
# Uncomment for debugging watchman output
|
||||
# open (my $fh, ">", ".git/watchman-output.out");
|
||||
# binmode $fh, ":utf8";
|
||||
# print $fh "$clockid\n@files\n";
|
||||
# close $fh;
|
||||
|
||||
binmode STDOUT, ":utf8";
|
||||
print $clockid;
|
||||
print "\0";
|
||||
local $, = "\0";
|
||||
print @files;
|
||||
}
|
||||
|
||||
sub watchman_clock {
|
||||
my $response = qx/watchman clock "$git_work_tree"/;
|
||||
die "Failed to get clock id on '$git_work_tree'.\n" .
|
||||
"Falling back to scanning...\n" if $? != 0;
|
||||
|
||||
return $json_pkg->new->utf8->decode($response);
|
||||
}
|
||||
|
||||
sub watchman_query {
|
||||
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
|
||||
or die "open2() failed: $!\n" .
|
||||
"Falling back to scanning...\n";
|
||||
|
||||
# In the query expression below we're asking for names of files that
|
||||
# changed since $last_update_token but not from the .git folder.
|
||||
#
|
||||
# To accomplish this, we're using the "since" generator to use the
|
||||
# recency index to select candidate nodes and "fields" to limit the
|
||||
# output to file names only. Then we're using the "expression" term to
|
||||
# further constrain the results.
|
||||
my $last_update_line = "";
|
||||
if (substr($last_update_token, 0, 1) eq "c") {
|
||||
$last_update_token = "\"$last_update_token\"";
|
||||
$last_update_line = qq[\n"since": $last_update_token,];
|
||||
}
|
||||
my $query = <<" END";
|
||||
["query", "$git_work_tree", {$last_update_line
|
||||
"fields": ["name"],
|
||||
"expression": ["not", ["dirname", ".git"]]
|
||||
}]
|
||||
END
|
||||
|
||||
# Uncomment for debugging the watchman query
|
||||
# open (my $fh, ">", ".git/watchman-query.json");
|
||||
# print $fh $query;
|
||||
# close $fh;
|
||||
|
||||
print CHLD_IN $query;
|
||||
close CHLD_IN;
|
||||
my $response = do {local $/; <CHLD_OUT>};
|
||||
|
||||
# Uncomment for debugging the watch response
|
||||
# open ($fh, ">", ".git/watchman-response.json");
|
||||
# print $fh $response;
|
||||
# close $fh;
|
||||
|
||||
die "Watchman: command returned no output.\n" .
|
||||
"Falling back to scanning...\n" if $response eq "";
|
||||
die "Watchman: command returned invalid output: $response\n" .
|
||||
"Falling back to scanning...\n" unless $response =~ /^\{/;
|
||||
|
||||
return $json_pkg->new->utf8->decode($response);
|
||||
}
|
||||
|
||||
sub is_work_tree_watched {
|
||||
my ($output) = @_;
|
||||
my $error = $output->{error};
|
||||
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
|
||||
$retry--;
|
||||
my $response = qx/watchman watch "$git_work_tree"/;
|
||||
die "Failed to make watchman watch '$git_work_tree'.\n" .
|
||||
"Falling back to scanning...\n" if $? != 0;
|
||||
$output = $json_pkg->new->utf8->decode($response);
|
||||
$error = $output->{error};
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
# Uncomment for debugging watchman output
|
||||
# open (my $fh, ">", ".git/watchman-output.out");
|
||||
# close $fh;
|
||||
|
||||
# Watchman will always return all files on the first query so
|
||||
# return the fast "everything is dirty" flag to git and do the
|
||||
# Watchman query just to get it over with now so we won't pay
|
||||
# the cost in git to look up each individual file.
|
||||
my $o = watchman_clock();
|
||||
$error = $output->{error};
|
||||
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
output_result($o->{clock}, ("/"));
|
||||
$last_update_token = $o->{clock};
|
||||
|
||||
eval { launch_watchman() };
|
||||
return 0;
|
||||
}
|
||||
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub get_working_dir {
|
||||
my $working_dir;
|
||||
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
|
||||
$working_dir = Win32::GetCwd();
|
||||
$working_dir =~ tr/\\/\//;
|
||||
} else {
|
||||
require Cwd;
|
||||
$working_dir = Cwd::cwd();
|
||||
}
|
||||
|
||||
return $working_dir;
|
||||
}
|
||||
8
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/post-update.sample
vendored
Normal file
8
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/post-update.sample
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to prepare a packed repository for use over
|
||||
# dumb transports.
|
||||
#
|
||||
# To enable this hook, rename this file to "post-update".
|
||||
|
||||
exec git update-server-info
|
||||
14
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-applypatch.sample
vendored
Normal file
14
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-applypatch.sample
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed
|
||||
# by applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-applypatch".
|
||||
|
||||
. git-sh-setup
|
||||
precommit="$(git rev-parse --git-path hooks/pre-commit)"
|
||||
test -x "$precommit" && exec "$precommit" ${1+"$@"}
|
||||
:
|
||||
49
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-commit.sample
vendored
Normal file
49
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-commit.sample
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git commit" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message if
|
||||
# it wants to stop the commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-commit".
|
||||
|
||||
if git rev-parse --verify HEAD >/dev/null 2>&1
|
||||
then
|
||||
against=HEAD
|
||||
else
|
||||
# Initial commit: diff against an empty tree object
|
||||
against=$(git hash-object -t tree /dev/null)
|
||||
fi
|
||||
|
||||
# If you want to allow non-ASCII filenames set this variable to true.
|
||||
allownonascii=$(git config --type=bool hooks.allownonascii)
|
||||
|
||||
# Redirect output to stderr.
|
||||
exec 1>&2
|
||||
|
||||
# Cross platform projects tend to avoid non-ASCII filenames; prevent
|
||||
# them from being added to the repository. We exploit the fact that the
|
||||
# printable range starts at the space character and ends with tilde.
|
||||
if [ "$allownonascii" != "true" ] &&
|
||||
# Note that the use of brackets around a tr range is ok here, (it's
|
||||
# even required, for portability to Solaris 10's /usr/bin/tr), since
|
||||
# the square bracket bytes happen to fall in the designated range.
|
||||
test $(git diff-index --cached --name-only --diff-filter=A -z $against |
|
||||
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
|
||||
then
|
||||
cat <<\EOF
|
||||
Error: Attempt to add a non-ASCII file name.
|
||||
|
||||
This can cause problems if you want to work with people on other platforms.
|
||||
|
||||
To be portable it is advisable to rename the file.
|
||||
|
||||
If you know what you are doing you can disable this check using:
|
||||
|
||||
git config hooks.allownonascii true
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If there are whitespace errors, print the offending file names and fail.
|
||||
exec git diff-index --check --cached $against --
|
||||
13
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-merge-commit.sample
vendored
Normal file
13
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-merge-commit.sample
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git merge" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message to
|
||||
# stderr if it wants to stop the merge commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-merge-commit".
|
||||
|
||||
. git-sh-setup
|
||||
test -x "$GIT_DIR/hooks/pre-commit" &&
|
||||
exec "$GIT_DIR/hooks/pre-commit"
|
||||
:
|
||||
53
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-push.sample
vendored
Normal file
53
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-push.sample
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to verify what is about to be pushed. Called by "git
|
||||
# push" after it has checked the remote status, but before anything has been
|
||||
# pushed. If this script exits with a non-zero status nothing will be pushed.
|
||||
#
|
||||
# This hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- Name of the remote to which the push is being done
|
||||
# $2 -- URL to which the push is being done
|
||||
#
|
||||
# If pushing without using a named remote those arguments will be equal.
|
||||
#
|
||||
# Information about the commits which are being pushed is supplied as lines to
|
||||
# the standard input in the form:
|
||||
#
|
||||
# <local ref> <local oid> <remote ref> <remote oid>
|
||||
#
|
||||
# This sample shows how to prevent push of commits where the log message starts
|
||||
# with "WIP" (work in progress).
|
||||
|
||||
remote="$1"
|
||||
url="$2"
|
||||
|
||||
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||
|
||||
while read local_ref local_oid remote_ref remote_oid
|
||||
do
|
||||
if test "$local_oid" = "$zero"
|
||||
then
|
||||
# Handle delete
|
||||
:
|
||||
else
|
||||
if test "$remote_oid" = "$zero"
|
||||
then
|
||||
# New branch, examine all commits
|
||||
range="$local_oid"
|
||||
else
|
||||
# Update to existing branch, examine new commits
|
||||
range="$remote_oid..$local_oid"
|
||||
fi
|
||||
|
||||
# Check for WIP commit
|
||||
commit=$(git rev-list -n 1 --grep '^WIP' "$range")
|
||||
if test -n "$commit"
|
||||
then
|
||||
echo >&2 "Found WIP commit in $local_ref, not pushing"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
169
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-rebase.sample
vendored
Normal file
169
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-rebase.sample
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006, 2008 Junio C Hamano
|
||||
#
|
||||
# The "pre-rebase" hook is run just before "git rebase" starts doing
|
||||
# its job, and can prevent the command from running by exiting with
|
||||
# non-zero status.
|
||||
#
|
||||
# The hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- the upstream the series was forked from.
|
||||
# $2 -- the branch being rebased (or empty when rebasing the current branch).
|
||||
#
|
||||
# This sample shows how to prevent topic branches that are already
|
||||
# merged to 'next' branch from getting rebased, because allowing it
|
||||
# would result in rebasing already published history.
|
||||
|
||||
publish=next
|
||||
basebranch="$1"
|
||||
if test "$#" = 2
|
||||
then
|
||||
topic="refs/heads/$2"
|
||||
else
|
||||
topic=`git symbolic-ref HEAD` ||
|
||||
exit 0 ;# we do not interrupt rebasing detached HEAD
|
||||
fi
|
||||
|
||||
case "$topic" in
|
||||
refs/heads/??/*)
|
||||
;;
|
||||
*)
|
||||
exit 0 ;# we do not interrupt others.
|
||||
;;
|
||||
esac
|
||||
|
||||
# Now we are dealing with a topic branch being rebased
|
||||
# on top of master. Is it OK to rebase it?
|
||||
|
||||
# Does the topic really exist?
|
||||
git show-ref -q "$topic" || {
|
||||
echo >&2 "No such branch $topic"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Is topic fully merged to master?
|
||||
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
|
||||
if test -z "$not_in_master"
|
||||
then
|
||||
echo >&2 "$topic is fully merged to master; better remove it."
|
||||
exit 1 ;# we could allow it, but there is no point.
|
||||
fi
|
||||
|
||||
# Is topic ever merged to next? If so you should not be rebasing it.
|
||||
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
|
||||
only_next_2=`git rev-list ^master ${publish} | sort`
|
||||
if test "$only_next_1" = "$only_next_2"
|
||||
then
|
||||
not_in_topic=`git rev-list "^$topic" master`
|
||||
if test -z "$not_in_topic"
|
||||
then
|
||||
echo >&2 "$topic is already up to date with master"
|
||||
exit 1 ;# we could allow it, but there is no point.
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
|
||||
/usr/bin/perl -e '
|
||||
my $topic = $ARGV[0];
|
||||
my $msg = "* $topic has commits already merged to public branch:\n";
|
||||
my (%not_in_next) = map {
|
||||
/^([0-9a-f]+) /;
|
||||
($1 => 1);
|
||||
} split(/\n/, $ARGV[1]);
|
||||
for my $elem (map {
|
||||
/^([0-9a-f]+) (.*)$/;
|
||||
[$1 => $2];
|
||||
} split(/\n/, $ARGV[2])) {
|
||||
if (!exists $not_in_next{$elem->[0]}) {
|
||||
if ($msg) {
|
||||
print STDERR $msg;
|
||||
undef $msg;
|
||||
}
|
||||
print STDERR " $elem->[1]\n";
|
||||
}
|
||||
}
|
||||
' "$topic" "$not_in_next" "$not_in_master"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
<<\DOC_END
|
||||
|
||||
This sample hook safeguards topic branches that have been
|
||||
published from being rewound.
|
||||
|
||||
The workflow assumed here is:
|
||||
|
||||
* Once a topic branch forks from "master", "master" is never
|
||||
merged into it again (either directly or indirectly).
|
||||
|
||||
* Once a topic branch is fully cooked and merged into "master",
|
||||
it is deleted. If you need to build on top of it to correct
|
||||
earlier mistakes, a new topic branch is created by forking at
|
||||
the tip of the "master". This is not strictly necessary, but
|
||||
it makes it easier to keep your history simple.
|
||||
|
||||
* Whenever you need to test or publish your changes to topic
|
||||
branches, merge them into "next" branch.
|
||||
|
||||
The script, being an example, hardcodes the publish branch name
|
||||
to be "next", but it is trivial to make it configurable via
|
||||
$GIT_DIR/config mechanism.
|
||||
|
||||
With this workflow, you would want to know:
|
||||
|
||||
(1) ... if a topic branch has ever been merged to "next". Young
|
||||
topic branches can have stupid mistakes you would rather
|
||||
clean up before publishing, and things that have not been
|
||||
merged into other branches can be easily rebased without
|
||||
affecting other people. But once it is published, you would
|
||||
not want to rewind it.
|
||||
|
||||
(2) ... if a topic branch has been fully merged to "master".
|
||||
Then you can delete it. More importantly, you should not
|
||||
build on top of it -- other people may already want to
|
||||
change things related to the topic as patches against your
|
||||
"master", so if you need further changes, it is better to
|
||||
fork the topic (perhaps with the same name) afresh from the
|
||||
tip of "master".
|
||||
|
||||
Let's look at this example:
|
||||
|
||||
o---o---o---o---o---o---o---o---o---o "next"
|
||||
/ / / /
|
||||
/ a---a---b A / /
|
||||
/ / / /
|
||||
/ / c---c---c---c B /
|
||||
/ / / \ /
|
||||
/ / / b---b C \ /
|
||||
/ / / / \ /
|
||||
---o---o---o---o---o---o---o---o---o---o---o "master"
|
||||
|
||||
|
||||
A, B and C are topic branches.
|
||||
|
||||
* A has one fix since it was merged up to "next".
|
||||
|
||||
* B has finished. It has been fully merged up to "master" and "next",
|
||||
and is ready to be deleted.
|
||||
|
||||
* C has not merged to "next" at all.
|
||||
|
||||
We would want to allow C to be rebased, refuse A, and encourage
|
||||
B to be deleted.
|
||||
|
||||
To compute (1):
|
||||
|
||||
git rev-list ^master ^topic next
|
||||
git rev-list ^master next
|
||||
|
||||
if these match, topic has not merged in next at all.
|
||||
|
||||
To compute (2):
|
||||
|
||||
git rev-list master..topic
|
||||
|
||||
if this is empty, it is fully merged to "master".
|
||||
|
||||
DOC_END
|
||||
24
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-receive.sample
vendored
Normal file
24
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/pre-receive.sample
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to make use of push options.
|
||||
# The example simply echoes all push options that start with 'echoback='
|
||||
# and rejects all pushes when the "reject" push option is used.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-receive".
|
||||
|
||||
if test -n "$GIT_PUSH_OPTION_COUNT"
|
||||
then
|
||||
i=0
|
||||
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
|
||||
do
|
||||
eval "value=\$GIT_PUSH_OPTION_$i"
|
||||
case "$value" in
|
||||
echoback=*)
|
||||
echo "echo from the pre-receive-hook: ${value#*=}" >&2
|
||||
;;
|
||||
reject)
|
||||
exit 1
|
||||
esac
|
||||
i=$((i + 1))
|
||||
done
|
||||
fi
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to prepare the commit log message.
|
||||
# Called by "git commit" with the name of the file that has the
|
||||
# commit message, followed by the description of the commit
|
||||
# message's source. The hook's purpose is to edit the commit
|
||||
# message file. If the hook fails with a non-zero status,
|
||||
# the commit is aborted.
|
||||
#
|
||||
# To enable this hook, rename this file to "prepare-commit-msg".
|
||||
|
||||
# This hook includes three examples. The first one removes the
|
||||
# "# Please enter the commit message..." help message.
|
||||
#
|
||||
# The second includes the output of "git diff --name-status -r"
|
||||
# into the message, just before the "git status" output. It is
|
||||
# commented because it doesn't cope with --amend or with squashed
|
||||
# commits.
|
||||
#
|
||||
# The third example adds a Signed-off-by line to the message, that can
|
||||
# still be edited. This is rarely a good idea.
|
||||
|
||||
COMMIT_MSG_FILE=$1
|
||||
COMMIT_SOURCE=$2
|
||||
SHA1=$3
|
||||
|
||||
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
|
||||
|
||||
# case "$COMMIT_SOURCE,$SHA1" in
|
||||
# ,|template,)
|
||||
# /usr/bin/perl -i.bak -pe '
|
||||
# print "\n" . `git diff --cached --name-status -r`
|
||||
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
|
||||
# *) ;;
|
||||
# esac
|
||||
|
||||
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
|
||||
# if test -z "$COMMIT_SOURCE"
|
||||
# then
|
||||
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
|
||||
# fi
|
||||
78
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/push-to-checkout.sample
vendored
Normal file
78
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/push-to-checkout.sample
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to update a checked-out tree on a git push.
|
||||
#
|
||||
# This hook is invoked by git-receive-pack(1) when it reacts to git
|
||||
# push and updates reference(s) in its repository, and when the push
|
||||
# tries to update the branch that is currently checked out and the
|
||||
# receive.denyCurrentBranch configuration variable is set to
|
||||
# updateInstead.
|
||||
#
|
||||
# By default, such a push is refused if the working tree and the index
|
||||
# of the remote repository has any difference from the currently
|
||||
# checked out commit; when both the working tree and the index match
|
||||
# the current commit, they are updated to match the newly pushed tip
|
||||
# of the branch. This hook is to be used to override the default
|
||||
# behaviour; however the code below reimplements the default behaviour
|
||||
# as a starting point for convenient modification.
|
||||
#
|
||||
# The hook receives the commit with which the tip of the current
|
||||
# branch is going to be updated:
|
||||
commit=$1
|
||||
|
||||
# It can exit with a non-zero status to refuse the push (when it does
|
||||
# so, it must not modify the index or the working tree).
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Or it can make any necessary changes to the working tree and to the
|
||||
# index to bring them to the desired state when the tip of the current
|
||||
# branch is updated to the new commit, and exit with a zero status.
|
||||
#
|
||||
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
|
||||
# in order to emulate git fetch that is run in the reverse direction
|
||||
# with git push, as the two-tree form of git read-tree -u -m is
|
||||
# essentially the same as git switch or git checkout that switches
|
||||
# branches while keeping the local changes in the working tree that do
|
||||
# not interfere with the difference between the branches.
|
||||
|
||||
# The below is a more-or-less exact translation to shell of the C code
|
||||
# for the default behaviour for git's push-to-checkout hook defined in
|
||||
# the push_to_deploy() function in builtin/receive-pack.c.
|
||||
#
|
||||
# Note that the hook will be executed from the repository directory,
|
||||
# not from the working tree, so if you want to perform operations on
|
||||
# the working tree, you will have to adapt your code accordingly, e.g.
|
||||
# by adding "cd .." or using relative paths.
|
||||
|
||||
if ! git update-index -q --ignore-submodules --refresh
|
||||
then
|
||||
die "Up-to-date check failed"
|
||||
fi
|
||||
|
||||
if ! git diff-files --quiet --ignore-submodules --
|
||||
then
|
||||
die "Working directory has unstaged changes"
|
||||
fi
|
||||
|
||||
# This is a rough translation of:
|
||||
#
|
||||
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
|
||||
if git cat-file -e HEAD 2>/dev/null
|
||||
then
|
||||
head=HEAD
|
||||
else
|
||||
head=$(git hash-object -t tree --stdin </dev/null)
|
||||
fi
|
||||
|
||||
if ! git diff-index --quiet --cached --ignore-submodules $head --
|
||||
then
|
||||
die "Working directory has staged changes"
|
||||
fi
|
||||
|
||||
if ! git read-tree -u -m "$commit"
|
||||
then
|
||||
die "Could not update working tree to new HEAD"
|
||||
fi
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to validate a patch (and/or patch series) before
|
||||
# sending it via email.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an appropriate
|
||||
# message if it wants to prevent the email(s) from being sent.
|
||||
#
|
||||
# To enable this hook, rename this file to "sendemail-validate".
|
||||
#
|
||||
# By default, it will only check that the patch(es) can be applied on top of
|
||||
# the default upstream branch without conflicts in a secondary worktree. After
|
||||
# validation (successful or not) of the last patch of a series, the worktree
|
||||
# will be deleted.
|
||||
#
|
||||
# The following config variables can be set to change the default remote and
|
||||
# remote ref that are used to apply the patches against:
|
||||
#
|
||||
# sendemail.validateRemote (default: origin)
|
||||
# sendemail.validateRemoteRef (default: HEAD)
|
||||
#
|
||||
# Replace the TODO placeholders with appropriate checks according to your
|
||||
# needs.
|
||||
|
||||
validate_cover_letter () {
|
||||
file="$1"
|
||||
# TODO: Replace with appropriate checks (e.g. spell checking).
|
||||
true
|
||||
}
|
||||
|
||||
validate_patch () {
|
||||
file="$1"
|
||||
# Ensure that the patch applies without conflicts.
|
||||
git am -3 "$file" || return
|
||||
# TODO: Replace with appropriate checks for this patch
|
||||
# (e.g. checkpatch.pl).
|
||||
true
|
||||
}
|
||||
|
||||
validate_series () {
|
||||
# TODO: Replace with appropriate checks for the whole series
|
||||
# (e.g. quick build, coding style checks, etc.).
|
||||
true
|
||||
}
|
||||
|
||||
# main -------------------------------------------------------------------------
|
||||
|
||||
if test "$GIT_SENDEMAIL_FILE_COUNTER" = 1
|
||||
then
|
||||
remote=$(git config --default origin --get sendemail.validateRemote) &&
|
||||
ref=$(git config --default HEAD --get sendemail.validateRemoteRef) &&
|
||||
worktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) &&
|
||||
git worktree add -fd --checkout "$worktree" "refs/remotes/$remote/$ref" &&
|
||||
git config --replace-all sendemail.validateWorktree "$worktree"
|
||||
else
|
||||
worktree=$(git config --get sendemail.validateWorktree)
|
||||
fi || {
|
||||
echo "sendemail-validate: error: failed to prepare worktree" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
unset GIT_DIR GIT_WORK_TREE
|
||||
cd "$worktree" &&
|
||||
|
||||
if grep -q "^diff --git " "$1"
|
||||
then
|
||||
validate_patch "$1"
|
||||
else
|
||||
validate_cover_letter "$1"
|
||||
fi &&
|
||||
|
||||
if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL"
|
||||
then
|
||||
git config --unset-all sendemail.validateWorktree &&
|
||||
trap 'git worktree remove -ff "$worktree"' EXIT &&
|
||||
validate_series
|
||||
fi
|
||||
128
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/update.sample
vendored
Normal file
128
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/hooks/update.sample
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to block unannotated tags from entering.
|
||||
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
|
||||
#
|
||||
# To enable this hook, rename this file to "update".
|
||||
#
|
||||
# Config
|
||||
# ------
|
||||
# hooks.allowunannotated
|
||||
# This boolean sets whether unannotated tags will be allowed into the
|
||||
# repository. By default they won't be.
|
||||
# hooks.allowdeletetag
|
||||
# This boolean sets whether deleting tags will be allowed in the
|
||||
# repository. By default they won't be.
|
||||
# hooks.allowmodifytag
|
||||
# This boolean sets whether a tag may be modified after creation. By default
|
||||
# it won't be.
|
||||
# hooks.allowdeletebranch
|
||||
# This boolean sets whether deleting branches will be allowed in the
|
||||
# repository. By default they won't be.
|
||||
# hooks.denycreatebranch
|
||||
# This boolean sets whether remotely creating branches will be denied
|
||||
# in the repository. By default this is allowed.
|
||||
#
|
||||
|
||||
# --- Command line
|
||||
refname="$1"
|
||||
oldrev="$2"
|
||||
newrev="$3"
|
||||
|
||||
# --- Safety check
|
||||
if [ -z "$GIT_DIR" ]; then
|
||||
echo "Don't run this script from the command line." >&2
|
||||
echo " (if you want, you could supply GIT_DIR then run" >&2
|
||||
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
||||
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Config
|
||||
allowunannotated=$(git config --type=bool hooks.allowunannotated)
|
||||
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
|
||||
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
|
||||
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
|
||||
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
|
||||
|
||||
# check for no description
|
||||
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
|
||||
case "$projectdesc" in
|
||||
"Unnamed repository"* | "")
|
||||
echo "*** Project description file hasn't been set" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Check types
|
||||
# if $newrev is 0000...0000, it's a commit to delete a ref.
|
||||
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||
if [ "$newrev" = "$zero" ]; then
|
||||
newrev_type=delete
|
||||
else
|
||||
newrev_type=$(git cat-file -t $newrev)
|
||||
fi
|
||||
|
||||
case "$refname","$newrev_type" in
|
||||
refs/tags/*,commit)
|
||||
# un-annotated tag
|
||||
short_refname=${refname##refs/tags/}
|
||||
if [ "$allowunannotated" != "true" ]; then
|
||||
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
|
||||
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/tags/*,delete)
|
||||
# delete tag
|
||||
if [ "$allowdeletetag" != "true" ]; then
|
||||
echo "*** Deleting a tag is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/tags/*,tag)
|
||||
# annotated tag
|
||||
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
|
||||
then
|
||||
echo "*** Tag '$refname' already exists." >&2
|
||||
echo "*** Modifying a tag is not allowed in this repository." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*,commit)
|
||||
# branch
|
||||
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
|
||||
echo "*** Creating a branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*,delete)
|
||||
# delete branch
|
||||
if [ "$allowdeletebranch" != "true" ]; then
|
||||
echo "*** Deleting a branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/remotes/*,commit)
|
||||
# tracking branch
|
||||
;;
|
||||
refs/remotes/*,delete)
|
||||
# delete tracking branch
|
||||
if [ "$allowdeletebranch" != "true" ]; then
|
||||
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Anything else (is there anything else?)
|
||||
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Finished
|
||||
exit 0
|
||||
BIN
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/index
vendored
Normal file
BIN
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/index
vendored
Normal file
Binary file not shown.
6
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/info/exclude
vendored
Normal file
6
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/info/exclude
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
||||
4
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/info/refs
vendored
Normal file
4
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/info/refs
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177 refs/heads/master
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177 refs/remotes/origin/HEAD
|
||||
58562ddc524fd11b529855134aa6227d5a537d70 refs/remotes/origin/dev
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177 refs/remotes/origin/master
|
||||
3
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/logs/HEAD
vendored
Normal file
3
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/logs/HEAD
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
0000000000000000000000000000000000000000 622c42b186706c0d7354d04b8c957fe715d0c177 wh <382379437@qq.com> 1721188454 +0800 clone: from C:/Users/lenovo/AppData/Local/Composer/vcs/https---gitee.com-drop-drop-general-utility-tools-php.git/
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177 622c42b186706c0d7354d04b8c957fe715d0c177 wh <382379437@qq.com> 1721188455 +0800 checkout: moving from master to master
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177 622c42b186706c0d7354d04b8c957fe715d0c177 wh <382379437@qq.com> 1721188455 +0800 reset: moving to 622c42b186706c0d7354d04b8c957fe715d0c177
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/logs/refs/heads/master
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/logs/refs/heads/master
vendored
Normal file
@@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 622c42b186706c0d7354d04b8c957fe715d0c177 wh <382379437@qq.com> 1721188454 +0800 clone: from C:/Users/lenovo/AppData/Local/Composer/vcs/https---gitee.com-drop-drop-general-utility-tools-php.git/
|
||||
@@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 622c42b186706c0d7354d04b8c957fe715d0c177 wh <382379437@qq.com> 1721188454 +0800 clone: from C:/Users/lenovo/AppData/Local/Composer/vcs/https---gitee.com-drop-drop-general-utility-tools-php.git/
|
||||
2
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/objects/info/packs
vendored
Normal file
2
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/objects/info/packs
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
P pack-ef866fac58cb9abd740db8b68f4b3caac8981535.pack
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/packed-refs
vendored
Normal file
3
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/packed-refs
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
58562ddc524fd11b529855134aa6227d5a537d70 refs/remotes/origin/dev
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177 refs/remotes/origin/master
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/refs/heads/master
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/refs/heads/master
vendored
Normal file
@@ -0,0 +1 @@
|
||||
622c42b186706c0d7354d04b8c957fe715d0c177
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/refs/remotes/origin/HEAD
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/.git - 副本/refs/remotes/origin/HEAD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/remotes/origin/master
|
||||
6
digital_doctor/vendor/wanghua/general-utility-tools-php/.gitignore
vendored
Normal file
6
digital_doctor/vendor/wanghua/general-utility-tools-php/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.idea
|
||||
.git
|
||||
|
||||
/.git
|
||||
/.idea
|
||||
/composer.lock
|
||||
37
digital_doctor/vendor/wanghua/general-utility-tools-php/README.en.md
vendored
Normal file
37
digital_doctor/vendor/wanghua/general-utility-tools-php/README.en.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# general_utility_tools_php
|
||||
|
||||
#### Description
|
||||
php常用工具箱
|
||||
general utility tool for php
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
142
digital_doctor/vendor/wanghua/general-utility-tools-php/README.md
vendored
Normal file
142
digital_doctor/vendor/wanghua/general-utility-tools-php/README.md
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
# general_utility_tools_php
|
||||
|
||||
#### 介绍
|
||||
|
||||
[PHP常用通用工具库]
|
||||
|
||||
一、常用验证类库
|
||||
1. 验证手机号是否正确
|
||||
2. 验证邮箱
|
||||
3. 验证身份证号码
|
||||
4. 是否字母或数字
|
||||
5. 是否是小数格式
|
||||
6. 更多功能请参考代码
|
||||
|
||||
二、PHP日期处理工具
|
||||
1. 日期加上N年、月、日、时、分、秒,得到计算后的时间
|
||||
2. 两个日期相减得到天、时、分、秒(没有两个日期相加一说)
|
||||
3. 更多更完善功能敬请期待......
|
||||
|
||||
三、更多类库参考本类库目录
|
||||
1. 每个目录都有使用说明.
|
||||
|
||||
#### 软件架构
|
||||
|
||||
每一种工具独立为一个功能类库。
|
||||
#### 软件要求
|
||||
thinkphp5.0+,PHP7.1+
|
||||
|
||||
|
||||
#### 安装教程
|
||||
composer require wanghua/general-utility-tools-php dev-master
|
||||
|
||||
###### 注意:如果总是安装失败,可切换国内或者国外源;如果是找不到版本则加上dev-master尝试
|
||||
###### 注意:如果总是安装失败,可卸载此包重新安装,卸载指令:composer remove wanghua/general-utility-tools-php
|
||||
###### 注意:如果总是不能提交 vendor下面的一个文件夹(或文件),请参考这篇文章解决:https://blog.csdn.net/qq_15941409/article/details/113184021
|
||||
|
||||
### 一、常用验证类库使用说明
|
||||
##### 初始化
|
||||
|
||||
//静态方法无需实例化直接调用
|
||||
|
||||
##### 验证参数是否是小数格式
|
||||
$str = '1.223';
|
||||
var_dump(Validate::is_float_number($str));
|
||||
|
||||
##### 验证参数是否字母或数字
|
||||
$str = 'qwer#199';
|
||||
var_dump(Validate::is_letter_or_number($str));
|
||||
|
||||
###### 注: 更多功能请参考源码
|
||||
|
||||
### 二、PHP日期处理工具使用说明
|
||||
|
||||
##### 初始化
|
||||
$date = (new Date());
|
||||
$date->date_format = 'Y-m-d H:i:s';//设置格式,默认Y-m-d H:i:s
|
||||
|
||||
##### 日期类型参数(第2个参数)可选项:
|
||||
//分、时、天、周、月、年
|
||||
protected $data_type = [
|
||||
'm' =>'minute',//分钟
|
||||
'minute' =>'minute',//分钟
|
||||
'h' =>'hour',//小时
|
||||
'hour' =>'hour',//小时
|
||||
'd' =>'day',//天
|
||||
'day' =>'day',//天
|
||||
'w' =>'week',//周
|
||||
'week' =>'week',//周
|
||||
'M' =>'month',//月
|
||||
'month' =>'month',//月
|
||||
'y' =>'year',//年
|
||||
'year' =>'year',//年
|
||||
];
|
||||
|
||||
|
||||
##### 在当前时间基础上加3天(第三个参数不传默认使用当前时间)
|
||||
$res = $date->addTime(3, 'd');//支持单词和字母,例如:d表示天,day也表示天
|
||||
dump($res);
|
||||
|
||||
##### 在当前时间基础上加1小时(第三个参数不传默认使用当前时间)
|
||||
$res = $date->addTime(1, 'h');//支持单词和字母,例如:h表示小时,hour也表示小时
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上加1小时
|
||||
$res = $date->addTime(1, 'h', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减1个月 (注意:月是大写M字母,分钟是小写m字母)
|
||||
$res = $date->reduceTime(1, 'M', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减20分钟 (注意:分钟是小写m字母)
|
||||
$res = $date->reduceTime(20, 'm', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
##### 在指定时间基础上减1年
|
||||
$res = $date->reduceTime(1, 'y', strtotime('2010-10-01 12:00:10'));
|
||||
dump($res);
|
||||
|
||||
### 日期时间相减
|
||||
|
||||
//时间相减返回的时间类型 秒、分、时、天 默认返回秒
|
||||
protected $time_type = [
|
||||
's' =>1,//秒
|
||||
'second' =>1,//秒
|
||||
'm' =>60,//分钟
|
||||
'minute' =>60,//分钟
|
||||
'h' =>3600,//小时
|
||||
'hour' =>3600,//小时
|
||||
'd' =>86400,//天
|
||||
'day' =>86400,//天
|
||||
];
|
||||
|
||||
$start_time = '2010-05-01 12:30:00';
|
||||
$end_time = '2010-10-28 12:30:00';
|
||||
|
||||
//结束时间减去开始时间得到秒数 (返回类型参考上方配置)
|
||||
$res = $date->timeReduceTime($end_time, $start_time);
|
||||
dump($res);
|
||||
|
||||
//结束时间减去开始时间得到天数 (返回类型参考上方配置)
|
||||
$res = $date->timeReduceTime($end_time, $start_time, 'day');
|
||||
dump($res);
|
||||
|
||||
###### 注: 更多功能请参考源码
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
25
digital_doctor/vendor/wanghua/general-utility-tools-php/composer.json
vendored
Normal file
25
digital_doctor/vendor/wanghua/general-utility-tools-php/composer.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"type": "library",
|
||||
"name": "wanghua/general-utility-tools-php",
|
||||
"homepage": "https://gitee.com/drop_drop/general_utility_tools_php.git",
|
||||
"description": "general utility tools for thinkPHP",
|
||||
"license": "Apache-2.0",
|
||||
"version":"1.0.1",
|
||||
"keywords": ["general-utility-tools","php tool","common tool"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "wanghua",
|
||||
"email": "wanghua@qq.com",
|
||||
"homepage": "https://blog.csdn.net/qq_15941409"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"ext-json": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"wanghua\\general_utility_tools_php\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
||||
396
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Date.php
vendored
Normal file
396
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Date.php
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/10/27} {11:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
/**
|
||||
* 日期时间处理类
|
||||
* Class Date
|
||||
* @package libraries
|
||||
*/
|
||||
class Date
|
||||
{
|
||||
//时间默认返回格式
|
||||
public $date_format = 'Y-m-d H:i:s';
|
||||
//分、时、天、周、月、年
|
||||
protected $data_type = [
|
||||
'm' =>'minute',//分钟
|
||||
'minute' =>'minute',//分钟
|
||||
'h' =>'hour',//小时
|
||||
'hour' =>'hour',//小时
|
||||
'd' =>'day',//天
|
||||
'day' =>'day',//天
|
||||
'w' =>'week',//周
|
||||
'week' =>'week',//周
|
||||
'M' =>'month',//月
|
||||
'month' =>'month',//月
|
||||
'y' =>'year',//年
|
||||
'year' =>'year',//年
|
||||
];
|
||||
//秒、分、时、天
|
||||
protected $time_type = [
|
||||
's' =>1,//秒
|
||||
'second' =>1,//秒
|
||||
'm' =>60,//分钟
|
||||
'minute' =>60,//分钟
|
||||
'h' =>3600,//小时
|
||||
'hour' =>3600,//小时
|
||||
'd' =>86400,//天
|
||||
'day' =>86400,//天
|
||||
];
|
||||
/**
|
||||
* desc:日期时间加N
|
||||
*
|
||||
* 【注意】
|
||||
* 请在计算月时使用$date->date_format = 'Y-m'防止跳月份
|
||||
* 例如:2020-03-31月基础上加一个月,在默认$date->date_format='Y-m-d H:i:s'时,会跳到2020-05-01
|
||||
*
|
||||
* author:wh
|
||||
* @param int $times 相加的时间数量 整型
|
||||
* @param string $date_type 要相加的时间类型 可选值:m 分钟;h 小时;d 天;w 周;M 月;y 年
|
||||
* @param int $default_time 时间戳,默认当前时间
|
||||
* @return false|string 返回$this->date_format格式,可根据需要设定格式
|
||||
*/
|
||||
function addTime(int $times, string $date_type, int $default_time=0){
|
||||
return date($this->date_format, strtotime("+{$times} {$this->data_type[$date_type]}", $default_time?$default_time:time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期时间减N
|
||||
*
|
||||
* 【注意】
|
||||
* 请在计算月时使用$date->date_format = 'Y-m'防止跳月份
|
||||
* 例如:2020-03-31月基础上加一个月,在默认$date->date_format='Y-m-d H:i:s'时,会跳到2020-05-01
|
||||
*
|
||||
* author:wh
|
||||
* @param int $times 减去的时间数量 整型
|
||||
* @param string $date_type 要相减的时间类型 可选值:m 分钟;h 小时;d 天;w 周;M 月;y 年
|
||||
* @param int $default_time 时间戳,默认当前时间
|
||||
* @return false|string 返回$this->date_format格式,可根据需要设定格式
|
||||
*/
|
||||
function reduceTime(int $times, string $date_type, int $default_time=0){
|
||||
return date($this->date_format, strtotime("-{$times} {$this->data_type[$date_type]}", $default_time?$default_time:time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期时间相减,通常结束时间大于开始时间
|
||||
* author:wh
|
||||
* @param string $end_time 结束时间
|
||||
* @param string $start_time 开始时间
|
||||
* @param string $return_type 日期时间相减后得到的时间类型,可能是小数。可选值:s 秒;m 分钟;h 小时;d;天
|
||||
* @return float|int 返回计算后的天、时、分、秒数
|
||||
*/
|
||||
function timeReduceTime(string $end_time, string $start_time, string $return_type='s'){
|
||||
return (strtotime($end_time) - strtotime($start_time)) / $this->time_type[$return_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期减日期, 返回月数或年数
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间
|
||||
* @param string $end_time 结束时间
|
||||
* @param string $return_type M 返回一共有多少个月,y 返回有多少个年
|
||||
* @return float|int
|
||||
*/
|
||||
function dateCutDate(string $start_time, string $end_time, string $return_type='M'){
|
||||
$e = date_create($end_time);
|
||||
|
||||
$s = date_create($start_time);
|
||||
|
||||
$diff = date_diff($e, $s);
|
||||
|
||||
//计算月份
|
||||
if ($diff->y > 0) {
|
||||
$m = $diff->y * 12 + $diff->m;
|
||||
}else{
|
||||
$m = $diff->m;
|
||||
}
|
||||
return $return_type=='M'?$m:$diff->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:日期相减得到月数
|
||||
* 注意:不是计算的时间戳,而是计算的月份差值
|
||||
* author:wh
|
||||
* @param string $start_time
|
||||
* @param string $end_time
|
||||
* @return false|float|int|string
|
||||
*/
|
||||
function dateCutMonth(string $start_time, string $end_time){
|
||||
$start_y = date('Y', strtotime($start_time));
|
||||
$end_y = date('Y', strtotime($end_time));
|
||||
$start_m = date('m', strtotime($start_time));
|
||||
$end_m = date('m', strtotime($end_time));
|
||||
$ym = ($end_y-$start_y) * 12;
|
||||
return $ym - $start_m + $end_m;
|
||||
}
|
||||
/**
|
||||
* desc:日期相减得到年数
|
||||
* 注意:不是计算的时间戳,而是计算的年份差值
|
||||
* author:wh
|
||||
* @param string $start_time
|
||||
* @param string $end_time
|
||||
* @return false|float|int|string
|
||||
*/
|
||||
function dateCutYear(string $start_time, string $end_time){
|
||||
$start_y = date('Y', strtotime($start_time));
|
||||
$end_y = date('Y', strtotime($end_time));
|
||||
return ($end_y-$start_y) * 12;
|
||||
}
|
||||
/**
|
||||
* desc:返回年中第几天
|
||||
* author:wh
|
||||
* @param string $month 指定月份
|
||||
* @param string $day 指定日
|
||||
* @param string $year 指定年份
|
||||
* @return false|string
|
||||
*/
|
||||
function get_day_Year(string $month, string $day, string $year){
|
||||
return date('z',mktime(0,0,0,$month,$day,$year));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:今天的开始时间
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginToday(){
|
||||
return date('Y-m-d').' 00:00:00';
|
||||
}
|
||||
/**
|
||||
* desc:今天的结束时间
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endToday(){
|
||||
return date('Y-m-d').' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:昨天的开始时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function beginYesterday(){
|
||||
return date('Y-m-d', strtotime('-1 day')).' 00:00:00';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:昨天的结束时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function endYesterday(){
|
||||
return date('Y-m-d', strtotime('-1 day')).' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前天的开始时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function beginBeforeYesterday(){
|
||||
return date('Y-m-d', strtotime('-2 day')).' 00:00:00';
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前天的结束时间
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function endBeforeYesterday(){
|
||||
return date('Y-m-d', strtotime('-2 day')).' 23:59:59';
|
||||
}
|
||||
|
||||
/**
|
||||
* 本周的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginWeek($His = true)
|
||||
{
|
||||
//此代码会跳周、月、年
|
||||
//$timestamp = mktime(0, 0, 0, date('m'), date('d') - date('w') + 1, date('Y'));
|
||||
//return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
|
||||
//改进
|
||||
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
|
||||
$first=1;
|
||||
$sdefaultDate = date("Y-m-d");
|
||||
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
|
||||
$w=date('w',strtotime($sdefaultDate));
|
||||
//是否展示时分秒
|
||||
$week_start = date('Y-m-d',strtotime("$sdefaultDate -".($w ? $w - $first : 6).' days'));
|
||||
//是否展示时分秒
|
||||
if($His){
|
||||
//$week_start
|
||||
return $week_start.' 00:00:00';
|
||||
}
|
||||
//$week_start
|
||||
return $week_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* 本周的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endWeek($His = true)
|
||||
{
|
||||
//此代码会跳周、月、年
|
||||
//$timestamp = mktime(23, 59, 59, date('m'), date('d') - date('w') + 7, date('Y'));
|
||||
//return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
|
||||
//改进
|
||||
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
|
||||
$first=1;
|
||||
$sdefaultDate = date("Y-m-d");
|
||||
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
|
||||
$w=date('w',strtotime($sdefaultDate));
|
||||
//是否展示时分秒
|
||||
$week_start = date('Y-m-d',strtotime("$sdefaultDate -".($w ? $w - $first : 6).' days'));
|
||||
$week_end=date('Y-m-d',strtotime("$week_start +6 days"));
|
||||
//是否展示时分秒
|
||||
return $His?$week_end.' 23:59:59':$week_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上周开始
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginBeforeWeek(){
|
||||
$week = $this->beginWeek();
|
||||
$this->date_format = 'Y-m-d';
|
||||
return $this->reduceTime(7,'d',strtotime($week)) . ' 00:00:00';
|
||||
|
||||
//此代码会跳周、月、年
|
||||
//return date('Y-m-d', strtotime('-1 monday', time())).' 00:00:00';//上周一,无论今天几号,-1 monday为上一个有效周未
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上周结束
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endBeforeWeek(){
|
||||
|
||||
$week = $this->beginWeek();
|
||||
$this->date_format = 'Y-m-d';
|
||||
return $this->reduceTime(1,'d',strtotime($week)) . ' 23:59:59';
|
||||
|
||||
//此代码会跳周、月、年
|
||||
//return date('Y-m-d', strtotime('-1 sunday', time())).' 23:59:59'; //上一个有效周日,同样适用于其它星期
|
||||
}
|
||||
|
||||
/**
|
||||
* 本月的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginMonth($His = true)
|
||||
{
|
||||
return $His ? date('Y-m-').'01 00:00:00' : date('Y-m-').'01';
|
||||
}
|
||||
/**
|
||||
* 本月的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endMonth($His = true)
|
||||
{
|
||||
$timestamp = mktime(23, 59, 59, date('m'), date('t'), date('Y'));
|
||||
return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:上月开始时间(上月一日)
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function beginBeforeMonth(){
|
||||
return date('Y-m-d', strtotime('-1 month', strtotime(date('Y-m', time()) . '-01 00:00:00'))).' 00:00:00'; //本月一日直接strtotime上减一个月
|
||||
}
|
||||
/**
|
||||
* desc:上月结束时间(上月最后一日)
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function endBeforeMonth(){
|
||||
return date('Y-m-d', strtotime(date('Y-m', time()) . '-01 00:00:00') - 86400).' 23:59:59'; //本月一日减一天即是上月最后一日
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:七天(一周)以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerWeekDay(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 7 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
/**
|
||||
* desc:一月以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerMonth(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 30 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
/**
|
||||
* desc:一年以内
|
||||
* author:wh
|
||||
* @return false|string
|
||||
*/
|
||||
function innerYear(){
|
||||
$time = time();
|
||||
//当前时间减去30天
|
||||
$second = $time - 365 * 86400;
|
||||
return date('Y-m-d', $second);
|
||||
}
|
||||
|
||||
/**
|
||||
* 几年的开始日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function beginYear($His = true)
|
||||
{
|
||||
$timestamp = date('Y');
|
||||
return $His ? $timestamp.'-01-01 00:00:00' : $timestamp.'-01-01';
|
||||
}
|
||||
|
||||
/**
|
||||
* 几年的结束日期
|
||||
*
|
||||
* @param bool $His 是否展示时分秒 默认true
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function endYear($His = true)
|
||||
{
|
||||
$timestamp = date('Y');
|
||||
return $His ? $timestamp.'-12-31 23:59:59' : $timestamp.'-12-31';
|
||||
}
|
||||
}
|
||||
125
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Mmodel.php
vendored
Normal file
125
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Mmodel.php
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/1} {21:28}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* thinkphp5模型快捷方法库
|
||||
* Class Mmodel
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class Mmodel
|
||||
{
|
||||
/**
|
||||
* desc:存在则更新否则插入
|
||||
* author:wh
|
||||
* @param string $table 表名
|
||||
* @param array $where 更新条件(只在更新时有效)
|
||||
* @param array $data 更新或写入数据
|
||||
* @return int 数据主键id
|
||||
*/
|
||||
static function existsUpdateInsert($table,$where,$data){
|
||||
if(empty($where)){
|
||||
return Db::table($table)->insertGetId($data);
|
||||
}
|
||||
$res = Db::table($table)
|
||||
->where($where)
|
||||
->find();
|
||||
if($res){
|
||||
Db::table($table)
|
||||
->where($where)
|
||||
->data($data)
|
||||
->update();
|
||||
return $res['id'];
|
||||
}
|
||||
return Db::table($table)->insertGetId($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 无事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catch($fn){
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
return $fn();
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('操作失败.',$e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 无事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchJson($fn){
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
return json($res);
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return json(Tools::set_fail('操作失败.',$e->getMessage()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 自动事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchTrans($fn){
|
||||
Db::startTrans();
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
Db::commit();
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Db::rollback();
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail('操作失败.',$e->getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* desc:捕获式函数块
|
||||
*
|
||||
* 自动事务处理
|
||||
*
|
||||
* author:wh
|
||||
* @param $fn
|
||||
*/
|
||||
static function catchTransJson($fn){
|
||||
Db::startTrans();
|
||||
try{
|
||||
Tools::log_to_write_txt(['input'=>input()]);
|
||||
$res = $fn();
|
||||
Db::commit();
|
||||
return json($res);
|
||||
}catch (\Exception $e){
|
||||
Db::rollback();
|
||||
Tools::error_txt_log($e);
|
||||
return json(Tools::set_fail('操作失败.',$e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
94
digital_doctor/vendor/wanghua/general-utility-tools-php/src/PinYin.php
vendored
Normal file
94
digital_doctor/vendor/wanghua/general-utility-tools-php/src/PinYin.php
vendored
Normal file
File diff suppressed because one or more lines are too long
50
digital_doctor/vendor/wanghua/general-utility-tools-php/src/SundryConfig.php
vendored
Normal file
50
digital_doctor/vendor/wanghua/general-utility-tools-php/src/SundryConfig.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2023/12/31} {21:56}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 系统杂项配置
|
||||
*
|
||||
* 读取fa_sundry_config表中的配置
|
||||
*
|
||||
* Class SundryConfig
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class SundryConfig
|
||||
{
|
||||
private static $tablename = 'fa_zc_sundry_config';
|
||||
|
||||
/**
|
||||
* desc:获取配置的值,设置配置的值
|
||||
*
|
||||
* 默认缓存值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $key
|
||||
* @param string $val
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
static function val(string $key,string $val=''){
|
||||
$tabname = self::$tablename;
|
||||
if($val){
|
||||
$obj = Db::table($tabname);
|
||||
$obj->where('key',$key);
|
||||
$obj->data(['val'=>$val]);
|
||||
return $obj->update();
|
||||
}
|
||||
$obj = Db::table($tabname);
|
||||
return $obj->where(['key'=>$key])
|
||||
->cache($tabname.'_'.$key,0,$tabname)
|
||||
->value('val');
|
||||
}
|
||||
}
|
||||
360
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Validate.php
vendored
Normal file
360
digital_doctor/vendor/wanghua/general-utility-tools-php/src/Validate.php
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/11/1} {15:09}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php;
|
||||
|
||||
|
||||
class Validate
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:验证手机号是否正确
|
||||
* author:wh
|
||||
* @param $m
|
||||
* @return bool
|
||||
*/
|
||||
static function is_mobile($m) {
|
||||
return preg_match('/^1[3,4,5,6,7,8,9]{1}\d{9}$/', $m) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邮箱
|
||||
* author:wh
|
||||
* @param $email
|
||||
* @return bool
|
||||
*/
|
||||
static function is_email($email){
|
||||
return preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/",$email)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [is_IDCard 验证身份证号码]
|
||||
* @Author
|
||||
* @Date 2019-11-26
|
||||
* @param [string] $string [身份证号]
|
||||
* @return boolean [description]
|
||||
*/
|
||||
static function is_IDCard($string){
|
||||
return preg_match("/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/", $string)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [is_money_times 验证金额是否是100的整数倍]
|
||||
* @Author
|
||||
* @Date 2019-12-12
|
||||
* @param [type] $money [金额]
|
||||
* @return boolean [description]
|
||||
*/
|
||||
static function is_money_times($money){
|
||||
if(!is_numeric($money) || $money <= 0){
|
||||
return false;
|
||||
}
|
||||
return $money%100===0;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是金额
|
||||
* author:wh
|
||||
* @param $money
|
||||
* @return bool
|
||||
*/
|
||||
static function is_money($money){
|
||||
return (preg_match('/^[0-9]+.[0-9]+$/', $money) || preg_match('/^\d+$/', $money))?true:false;
|
||||
}
|
||||
/**
|
||||
* desc:是否是金额,并且最多只有两位小数
|
||||
*
|
||||
* 严格金额格式校验
|
||||
*
|
||||
* author:wh
|
||||
* @param $money
|
||||
* @return bool
|
||||
*/
|
||||
static function is_money_double($money){
|
||||
|
||||
$r = (preg_match('/^[0-9]+.[0-9]+$/', $money) || preg_match('/^\d+$/', $money))?true:false;
|
||||
|
||||
$exp = explode('.',$money);
|
||||
|
||||
if(strpos($money,'.') && preg_match('/^[0-9]+.[0-9]+$/', $money) && strlen($exp[1])>2){
|
||||
//返回false,表示非严格的2位数金额
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是小数格式
|
||||
* author:wh
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
static function is_float_number(string $num){
|
||||
return preg_match('/^[0-9]+.[0-9]+$/', $num)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是数字
|
||||
* author:wh
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
static function is_number(string $num){
|
||||
return preg_match('/^\d+$/', $num)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是字母
|
||||
* author: wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_letter(string $str){
|
||||
return preg_match('/^[a-zA-Z]+$/', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否字母或数字
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_letter_or_number(string $str){
|
||||
return preg_match('/^[a-zA-Z|0-9]+$/', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证数组是否存在空值
|
||||
* 仅针对基本数据类型
|
||||
* 仅针对一维数组
|
||||
* author:wh
|
||||
* @param $array
|
||||
* @return bool
|
||||
*/
|
||||
static function check_array_val_empty($array){
|
||||
$is_empty = false;
|
||||
foreach ($array as $value){
|
||||
if(($value!==0 && $value !=='0') && empty($value)){
|
||||
$is_empty = true;
|
||||
break;
|
||||
}
|
||||
if(is_int($value) && empty(1*$value)){
|
||||
$is_empty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $is_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否是url
|
||||
* author:wh
|
||||
* @param $v
|
||||
* @return bool
|
||||
*/
|
||||
static function is_url($v){
|
||||
$pattern="#(http|https)://(.*\.)?.*\..*#i";
|
||||
return preg_match($pattern,$v)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* [是否全部大写]
|
||||
*
|
||||
* @param $str
|
||||
* @return bool
|
||||
* @example
|
||||
* @see
|
||||
* @link
|
||||
*/
|
||||
static function is_upper($str){
|
||||
return preg_match('/^[A-Z]+$/', $str)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* [是否全部小写]
|
||||
*
|
||||
* @param $str
|
||||
* @return bool
|
||||
* @example
|
||||
* @see
|
||||
* @link
|
||||
*/
|
||||
static function is_lower($str){
|
||||
return preg_match('/^[a-z]+$/', $str)?true:false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:验证是微信内还是微信外
|
||||
*
|
||||
* 是否在微信内,是否在微信中
|
||||
*
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
static function is_weixin(){
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否包含特殊字符
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_special_character(string $str){
|
||||
$res = preg_match ( '/[\Q~!@#$%^&*()+-_=.:?<>\E]/', $str );
|
||||
return $res ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证字符串是否全部是中文
|
||||
*
|
||||
* 返回 true表示全部是中文,false表示部分是中文或没有中文
|
||||
*
|
||||
* author:wh
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
static function is_all_chinese(string $str){
|
||||
return preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$str)?true:false;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证两个浮点数值是否相等
|
||||
*
|
||||
* 例如:
|
||||
* $num1 = 0.1;
|
||||
$num2 = 0.7;
|
||||
|
||||
$res = $num1 + $num2;
|
||||
|
||||
var_dump($res);
|
||||
|
||||
var_dump($res == 0.8);//false 不相等
|
||||
|
||||
var_dump(intval(strval($res)) == intval(strval(0.8)));//true 相等
|
||||
*
|
||||
* author:wh
|
||||
* @param $float_num1
|
||||
* @param $float_num2
|
||||
* @return bool
|
||||
*/
|
||||
static function is_equal_num_val($float_num1, $float_num2){
|
||||
|
||||
return intval(strval($float_num1)) == intval(strval($float_num2));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:是否包含给定的主域名
|
||||
* author:wh
|
||||
* @param $domain
|
||||
* @param $main_domain
|
||||
* @return bool
|
||||
*/
|
||||
static function is_main_domain($domain,$main_domain){
|
||||
$exp_arr = explode('.',$domain);
|
||||
$str = $exp_arr[count($exp_arr)-2] .'.'. $exp_arr[count($exp_arr)-1];
|
||||
return $str==$main_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:国内国外IP校验,校验IP来源
|
||||
*
|
||||
* author:wh
|
||||
* @param $ip
|
||||
* @return bool
|
||||
*/
|
||||
static function validate_ip($ip) {
|
||||
$chinaStart = ip2long('1.0.1.0'); // 中国大陆起始IP
|
||||
$chinaEnd = ip2long('254.254.254.254'); // 中国大陆结束IP
|
||||
|
||||
$hongKongStart = ip2long('8.36.0.0'); // 香港起始IP
|
||||
$hongKongEnd = ip2long('8.37.255.255'); // 香港结束IP
|
||||
|
||||
$taiwanStart = ip2long('192.168.0.0'); // 台湾起始IP
|
||||
$taiwanEnd = ip2long('192.168.255.255'); // 台湾结束IP
|
||||
|
||||
$ipLong = ip2long($ip);
|
||||
|
||||
if ($ipLong >= $chinaStart && $ipLong <= $chinaEnd ||
|
||||
$ipLong >= $hongKongStart && $ipLong <= $hongKongEnd ||
|
||||
$ipLong >= $taiwanStart && $ipLong <= $taiwanEnd) {
|
||||
return true; // IP属于国内
|
||||
} else {
|
||||
return false; // IP不属于国内
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否移动端访问访问
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function is_mobile_client()
|
||||
{
|
||||
// 如果有HTTP_X_WAP_PROFILE则一定是移动设备
|
||||
if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
|
||||
if (isset($_SERVER['HTTP_VIA'])) {
|
||||
//找不到为flase,否则为true
|
||||
return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
|
||||
}
|
||||
|
||||
//判断手机发送的客户端标志
|
||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||
$clientkeywords = [
|
||||
'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp',
|
||||
'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu',
|
||||
'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi',
|
||||
'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile','alipay'
|
||||
];
|
||||
|
||||
// 从HTTP_USER_AGENT中查找手机浏览器的关键字
|
||||
if (preg_match("/(".implode('|', $clientkeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//协议法,因为有可能不准确,放到最后判断
|
||||
if (isset($_SERVER['HTTP_ACCEPT'])) {
|
||||
// 如果只支持wml并且不支持html那一定是移动设备
|
||||
// 如果支持wml和html但是wml在html之前则是移动设备
|
||||
if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否微信内置浏览器访问
|
||||
* @return bool
|
||||
*/
|
||||
static function is_wx_client()
|
||||
{
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否支付宝内置浏览器访问
|
||||
* @return bool
|
||||
*/
|
||||
static function is_ali_client()
|
||||
{
|
||||
return strpos($_SERVER['HTTP_USER_AGENT'], 'Alipay') !== false;
|
||||
}
|
||||
}
|
||||
160
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/AlibabaAuth.php
vendored
Normal file
160
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/AlibabaAuth.php
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/28} {14:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba;
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*
|
||||
* 注意:
|
||||
* 分销自研自用版不需要授权,直接使用永久accessToken
|
||||
* 请把当前账号添加为应用的日常测试账号
|
||||
*
|
||||
* Class Auth
|
||||
* @package app\index\logic\alibaba
|
||||
*/
|
||||
class AlibabaAuth
|
||||
{
|
||||
public $base_url = '';//不同业务线,授权地址不一样
|
||||
public $config = [];
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
function trusteeshipAuth(){
|
||||
//待开发
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:授权分为托管式授权和WEB端授权,这里是WEB端授权(后去code临时凭证)
|
||||
*
|
||||
* author:wh
|
||||
* @param string $appKey app注册时,分配给app的唯一标识
|
||||
* @param string $redirect_uri app的入口地址,授权临时令牌会以queryString的形式跟在该url后返回。注意参数中回调地址的域名必须与app注册时填写的回调地址的域名匹配。
|
||||
* @param string $site site参数标识当前授权的站点,直接填写1688
|
||||
* @param string $state 可选,app自定义参数,回跳到redirect_uri时,会原样返回
|
||||
* return 用户输入用户名密码,并确认授权,返回临时授权码code给app,具体返回方式,参照redirect_uri说明
|
||||
*/
|
||||
function webAppAuth($redirect_uri,$site='1688',$state=''){
|
||||
$appKey = $this->config['appkey'];
|
||||
|
||||
$url = "https://auth.1688.com/oauth/authorize?client_id={$appKey}&site={$site}&redirect_uri={$redirect_uri}&state={$state}";
|
||||
|
||||
|
||||
//$res = Curl::curl_post($url,[]);
|
||||
return "<script>location.href='{$url}'</script>";
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:使用code获取令牌【code有效期(2分钟)】
|
||||
*
|
||||
* 注:此接口必须使用POST方法提交;必须使用https
|
||||
getToken接口参数说明:
|
||||
a) grant_type为授权类型,使用authorization_code即可
|
||||
b) need_refresh_token为是否需要返回refresh_token,如果返回了refresh_token,原来获取的refresh_token也不会失效,除非超过半年有效期
|
||||
c) client_id为app唯一标识,即appKey
|
||||
d) client_secret为app密钥
|
||||
e) redirect_uri为app入口地址
|
||||
f) code为授权完成后返回的一次性令牌
|
||||
g) 调用getToken接口不需要签名
|
||||
注:如果超过code有效期(2分钟)或者已经使用code获取了一次令牌,code都将失效,需要返回第二步重新获取code
|
||||
* author:wh
|
||||
*/
|
||||
function getTokenByCode($code,$redirect_uri){
|
||||
$appkey = $this->config['appkey'];
|
||||
$secret = $this->config['appsecret'];
|
||||
$url = "https://gw.open.1688.com/openapi/";
|
||||
$urlPath = "http/1/system.oauth2/getToken/".$appkey;
|
||||
$paramstr = "?grant_type=authorization_code&need_refresh_token=true&client_id={$appkey}&client_secret={$secret}&redirect_uri={$redirect_uri}&code={$code}";
|
||||
|
||||
$url = $url.$urlPath.$paramstr;
|
||||
return Curl::curl_post($url,[]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
*
|
||||
1、 构造urlPath。urlPath是url 中的一部分,从协议开始截取,到“?”为止,包含了协议、namespace、apiName和apiVersion,如urlPath=http/1/system/currentTime/1688
|
||||
|
||||
2、 拼装参数。首先将所有参数按照key+value拼装得到一个字符串数组(如[b1,a2]),然后对数组进行排序([a2,b1]),最后将排序后的数组合并为字符串(a2b1)
|
||||
|
||||
3、 合并。把前两步的字符串拼接(http/1/system/currentTime/1688a2b1)
|
||||
|
||||
4、 执行hmac_sha1算法。 Signature=uppercase (hex (hmac_sha1 (concatString, secretKey)),假设secretKey=test123,那么得到的签名为2F1E96587451DE0E171978F4AAE1A90FF9B2F94B
|
||||
|
||||
a) concatString为合并后的字符串
|
||||
|
||||
b) secretKey为签名密钥,与urlPath中的appKey(1000000)对应
|
||||
|
||||
c) hmac_sha1为通用的hmac_sha1算法,各编程语言一般都对应类库
|
||||
|
||||
d) hex为转为十六进制
|
||||
|
||||
e) uppercase为转为大写字符
|
||||
* author:wh
|
||||
* @param string $urlPath eg: param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/7571561
|
||||
* @param array $params 请求参数
|
||||
* @return string
|
||||
*/
|
||||
public function signature($urlPath,$params)
|
||||
{
|
||||
$accessToken = $this->config['accessToken'];
|
||||
$params['access_token'] = $accessToken;
|
||||
//$url = 'http://gw.open.1688.com/openapi';//1688开放平台使用gw.open.1688.com域名
|
||||
//$appKey = $this->config['appkey'];
|
||||
$appSecret = $this->config['appsecret'];
|
||||
|
||||
//dump('$urlPath: '.$urlPath);
|
||||
//$apiInfo = 'param2/1/system/currentTime/' . $appKey;//此处请用具体api进行替换
|
||||
//$urlPath = $urlPath . $appKey;//此处请用具体api进行替换
|
||||
|
||||
//配置参数,请用apiInfo对应的api参数进行替换
|
||||
$aliParams = array();
|
||||
foreach ($params as $key => $val) {
|
||||
$aliParams[] = $key . $val;
|
||||
}
|
||||
sort($aliParams);
|
||||
$sign_str = join('', $aliParams);
|
||||
$sign_str = $urlPath . $sign_str;
|
||||
$code_sign = strtoupper(bin2hex(hash_hmac("sha1", $sign_str, $appSecret, true)));
|
||||
|
||||
return $code_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:发起请求,自动完成签名并返回结果
|
||||
* author:wh
|
||||
* @param string $urlPath eg: param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/23222222
|
||||
* @param array $request_data 接口请求数据
|
||||
*/
|
||||
function request($urlPath, $request_data){
|
||||
set_time_limit(0);
|
||||
$request_params_str = '';
|
||||
foreach ($request_data as $k=>$v){
|
||||
if($request_params_str == ''){
|
||||
$request_params_str .= $k.'='.$v;
|
||||
}else{
|
||||
$request_params_str .= '&'.$k.'='.$v;
|
||||
}
|
||||
}
|
||||
$accessToken = $this->config['accessToken'];
|
||||
//dump($request_params_str);
|
||||
$_aop_signature = $this->signature($urlPath,$request_data);
|
||||
//dump($_aop_signature);
|
||||
//$request_data['_aop_signature'] = $_aop_signature;
|
||||
|
||||
$url = $this->base_url.$urlPath.'?'.$request_params_str.'&access_token='.$accessToken.'&_aop_signature='.$_aop_signature;
|
||||
//dump($url);
|
||||
$res = Curl::curl_post($url,[]);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
23
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/BaseStrict.php
vendored
Normal file
23
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/BaseStrict.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {12:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes;
|
||||
|
||||
|
||||
class BaseStrict
|
||||
{
|
||||
public $base_url = 'https://gw.open.1688.com/openapi/';
|
||||
//授权对象
|
||||
protected $authObj = null;
|
||||
public function __construct($authObj)
|
||||
{
|
||||
$this->authObj = $authObj;
|
||||
//初始化并设置当前模块的基础url
|
||||
$this->authObj->base_url = $this->base_url;
|
||||
}
|
||||
}
|
||||
3
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/README.MD
vendored
Normal file
3
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/README.MD
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
## distributes 分销模块
|
||||
|
||||
### strict 分销中严选模块(商家自营)
|
||||
144
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/Testexample.php
vendored
Normal file
144
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alibaba/distributes/Testexample.php
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {12:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use wanghua\general_utility_tools_php\alibaba\AlibabaAuth;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\CustomerService;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictCategory;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictGoods;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictLogistics;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictOrder;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\strict\StrictPay;
|
||||
|
||||
|
||||
/**
|
||||
* 测试案例
|
||||
*
|
||||
* Class Testexample
|
||||
* @package wanghua\general_utility_tools_php\alibaba\distributes
|
||||
*/
|
||||
class Testexample
|
||||
{
|
||||
/**
|
||||
* desc:查询订单是否开通免密支付
|
||||
*/
|
||||
function queryOrderIsNoPassPay(){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictPay($authObj);
|
||||
return $obj->queryOrderIsNoPassPay();
|
||||
}
|
||||
function getLogisticsTemplate(){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictLogistics($authObj);
|
||||
return $obj->getLogisticsTemplate();
|
||||
}
|
||||
//物流模板详情
|
||||
function getLogisticsTemplateDetail($template_id){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictLogistics($authObj);
|
||||
return $obj->getLogisticsTemplateDetail($template_id);
|
||||
}
|
||||
function getGoodsList($where){
|
||||
set_time_limit(0);
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictGoods($authObj);
|
||||
return $obj->getGoodsList($where);
|
||||
}
|
||||
function getGoodsListsPft($where){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictGoods($authObj);
|
||||
return $obj->getGoodsListsPft($where);
|
||||
}
|
||||
function getGoodsDetail(array $itemIds){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictGoods($authObj);
|
||||
return $obj->getGoodsDetail($itemIds);
|
||||
}
|
||||
function getCategoryByCID($category_id){
|
||||
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictCategory($authObj);
|
||||
return $obj->getCategoryByCID($category_id);
|
||||
}
|
||||
function testGetRootCategory(){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$obj = new StrictCategory($authObj);
|
||||
return $obj->getRootCategory();
|
||||
}
|
||||
|
||||
function testWebAuth($redirect_uri){
|
||||
$config = config('meebo_supply_config');
|
||||
$res = (new AlibabaAuth($config))->webAppAuth($redirect_uri);
|
||||
return $res;
|
||||
}
|
||||
function getTokenByCode($code,$redirect_uri){
|
||||
$config = config('meebo_supply_config');
|
||||
$res = (new AlibabaAuth($config))->getTokenByCode($code,$redirect_uri);
|
||||
return $res;
|
||||
}
|
||||
//测试创建订单
|
||||
function createOrder(){
|
||||
$order_info = Db::table(TabConf::$fa_order)
|
||||
->where('orderid','mm70wgex1719586377768')
|
||||
->find();
|
||||
$address = Db::table(TabConf::$fa_useraddress)
|
||||
->where('id',$order_info['useraddress_id'])
|
||||
->where('users_id',$order_info['users_id'])
|
||||
->find();
|
||||
$goods = Db::table(TabConf::$fa_goods)
|
||||
->where('id',$order_info['goods_id'])
|
||||
->find();
|
||||
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new StrictOrder($authObj);
|
||||
$order->setAddress($address);
|
||||
$order->setGoods($goods,$order_info['buy_num']);
|
||||
return $order->createOrder($order_info);
|
||||
}
|
||||
|
||||
function previewOrder(){
|
||||
$order_info = Db::table(TabConf::$fa_order)
|
||||
->where('orderid','mm70wgex1719586377768')
|
||||
->find();
|
||||
$address = Db::table(TabConf::$fa_useraddress)
|
||||
->where('id',$order_info['useraddress_id'])
|
||||
->where('users_id',$order_info['users_id'])
|
||||
->find();
|
||||
$goods = Db::table(TabConf::$fa_goods)
|
||||
->where('id',$order_info['goods_id'])
|
||||
->find();
|
||||
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new StrictOrder($authObj);
|
||||
$order->setAddress($address);
|
||||
$order->setGoods($goods,$order_info['buy_num']);
|
||||
return $order->previewOrder();
|
||||
}
|
||||
|
||||
//获取唤起旺旺聊天的链接
|
||||
function getCustomerServiceLink($toOpenUid){
|
||||
$config = config('meebo_supply_config');
|
||||
$authObj = new AlibabaAuth($config);
|
||||
$order = new CustomerService($authObj);
|
||||
return $order->getCustomerServiceLink($toOpenUid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/9} {13:42}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\notify;
|
||||
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 弃用,通知属于业务模块,直接在业务控制器中处理,这里仅作参考
|
||||
* 分销严选消息通知基类
|
||||
*
|
||||
* 初始化该基类,按需调用通知处理类
|
||||
*
|
||||
* Class BaseStrictNotify
|
||||
* @package app\index\logic\alibaba\distributes\notify
|
||||
*/
|
||||
class BaseStrictNotify
|
||||
{
|
||||
|
||||
private $object = null;
|
||||
|
||||
/**
|
||||
* desc:执行消息处理
|
||||
* author:wh
|
||||
* @param $callback
|
||||
* @return array
|
||||
*/
|
||||
function doMessage($callback=null){
|
||||
return Mmodel::catch(function () use ($callback){
|
||||
Tools::log_to_write_txt(['执行消息处理']);
|
||||
//根据消息类型,选择对应的处理类
|
||||
$message_data = input('message');
|
||||
if(empty($message_data)){
|
||||
return Tools::set_fail('message为空');
|
||||
}
|
||||
$message_data = json_decode($message_data,true);
|
||||
Tools::log_to_write_txt(['消息解码'=>$message_data]);
|
||||
if(empty($message_data['type'])){
|
||||
return Tools::set_fail('type为空');
|
||||
}
|
||||
//获取消息类型
|
||||
$fn = strtolower($message_data['type']);//类型即为方法名
|
||||
//消息类型前缀即为类名
|
||||
$class = '\\app\\index\\logic\\alibaba\\distributes\\notify\\'.ucfirst(explode('_',$fn)[0]).'Notify';
|
||||
$this->object = (new $class());//实例化类
|
||||
return $this->object->{$fn}($callback);//调用方法
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/9} {13:25}
|
||||
*/
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\notify;
|
||||
|
||||
use app\index\logic\alibaba\distributes\Testexample;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated 弃用,通知属于业务模块,直接在业务控制器中处理,这里仅作参考
|
||||
* 产品 消息通知
|
||||
*
|
||||
* Class ProductNotify
|
||||
* @package app\index\logic\alibaba\distributes\notify
|
||||
*/
|
||||
class ProductNotify extends BaseStrictNotify
|
||||
{
|
||||
|
||||
/**
|
||||
* @deprecated 弃用,通知属于业务模块,直接在业务控制器中处理,这里仅作参考
|
||||
* desc:商品上架通知
|
||||
* author:wh
|
||||
*
|
||||
* 输出message
|
||||
{"message":"{\"data\":{\"productIds\":\"107680826\",\"msgSendTime\":\"2018-05-30 20:29:37\",\"memberId\":\"shyxsscl\",\"status\":\"RELATION_VIEW_PRODUCT_REPOST\"},\"gmtBorn\":1720514151217,\"msgId\":88922343751,\"type\":\"PRODUCT_RELATION_VIEW_PRODUCT_REPOST\",\"userInfo\":\"b2b-1881150273\"}","_aop_signature":"03EB6538BB8864BC141ADB5A4923005BB0204F85"}
|
||||
*/
|
||||
function product_relation_view_product_repost($callback=null)
|
||||
{
|
||||
return Mmodel::catch(function () use ($callback){
|
||||
$message_data = input('message');
|
||||
if(empty($message_data)){
|
||||
return Tools::set_fail('message不能为空');
|
||||
}
|
||||
$message_data = json_decode($message_data,true);
|
||||
if(empty($message_data['data'])){
|
||||
return Tools::set_fail('data不能为空');
|
||||
}
|
||||
$productIds = $data['productIds'];//商品ID集合,至少有一个,用逗号分割
|
||||
$productIdsArr = explode(',',$productIds);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#这是异步通知案例
|
||||
|
||||
##业务逻辑自行编写
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/7/9} {0:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
class CustomerService extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:获取唤起旺旺聊天的链接
|
||||
* author:wh
|
||||
* @param $toOpenUid
|
||||
* @return mixed
|
||||
*/
|
||||
function getCustomerServiceLink($toOpenUid){
|
||||
$urlPath = "param2/1/com.alibaba.account/account.wangwangUrl.get/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, ['toOpenUid'=>$toOpenUid]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
## 分销严选模块
|
||||
只能使用分销严选方案里的接口
|
||||
DOC:
|
||||
https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.product:alibaba.category.get-1&aopApiCategory=category_new
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/29} {12:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
/**
|
||||
* 根据类目Id查询类目
|
||||
*
|
||||
* 传0获取所有一级类目,循环调用可以获取类目树
|
||||
*
|
||||
* 注意:类目id,必须大于等于0, 如果为0,则查询所有一级类目
|
||||
*
|
||||
* 类目查询。如果需要获取所有1688类目信息,需要从根类目开始遍历获取整个类目树。
|
||||
* 即:先传0获取所有一级类目ID,然后在通过获取到的一级类目ID遍历获取所二级类目,最后通过遍历二级类目ID获取三级类目。
|
||||
* 注意:1688类目仅三级,三级类目即发布商品所需的叶子类目。
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.product:alibaba.category.get-1&aopApiCategory=category_new
|
||||
* Class StrictCategory
|
||||
* @package app\index\logic\alibaba\distributes\strict
|
||||
*/
|
||||
class StrictCategory extends BaseStrict
|
||||
{
|
||||
|
||||
public function __construct($authObj)
|
||||
{
|
||||
parent::__construct($authObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取严选一级分类(顶级分类)
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getRootCategory(){
|
||||
//$base_url = "https://gw.open.1688.com/openapi/";
|
||||
$urlPath = "param2/1/com.alibaba.product/alibaba.category.get/".$this->authObj->config['appkey'];
|
||||
|
||||
$request_data = [];
|
||||
$request_data['categoryID'] = '0';
|
||||
return $this->authObj->request($urlPath,$request_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:根据类目id获取类目信息
|
||||
* author:wh
|
||||
* @param $category_id
|
||||
* @return mixed
|
||||
*/
|
||||
function getCategoryByCID($category_id){
|
||||
$urlPath = "param2/1/com.alibaba.product/alibaba.category.get/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['categoryID'] = $category_id;
|
||||
return $this->authObj->request($urlPath,$request_data);
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/30} {1:54}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
/**
|
||||
* 物流
|
||||
* Class StrictLogistics
|
||||
* @package app\index\logic\alibaba\distributes\strict
|
||||
*/
|
||||
class StrictLogistics extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取物流模板详情
|
||||
*
|
||||
* 根据物流模版ID获取卖家的物流模板。运费模板ID为0表示运费说明,为1表示卖家承担运费
|
||||
*
|
||||
* doc:https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.logistics:alibaba.logistics.myFreightTemplate.list.get-1&aopApiCategory=Logistics_NEW
|
||||
*/
|
||||
function getLogisticsTemplateDetail($template_id){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.logistics.myFreightTemplate.list.get/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, ['templateId'=>$template_id]);
|
||||
}
|
||||
function getLogisticsTemplate(){
|
||||
$urlPath = "param2/1/com.alibaba.logistics/alibaba.logistics.myFreightTemplate.list.get/".$this->authObj->config['appkey'];
|
||||
|
||||
return $this->authObj->request($urlPath, []);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/28} {15:11}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
use think\Exception;
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
|
||||
/**
|
||||
* 分销订单
|
||||
* Class Order
|
||||
* @package app\index\logic\alibaba\distributes
|
||||
*/
|
||||
class StrictOrder extends BaseStrict
|
||||
{
|
||||
//用户收货地址
|
||||
private $address = [];
|
||||
//商品信息
|
||||
private $goods = [];
|
||||
//发票信息
|
||||
private $invoice = [];
|
||||
//交易类型 由于不同的商品支持的交易方式不同,没有一种交易方式是全局通用的,所以当前下单可使用的交易方式必须通过下单预览接口的tradeModeNameList获取。
|
||||
private $tradeType = '';
|
||||
|
||||
/**
|
||||
* desc:收货地址说明
|
||||
1、使用保存的收货地址传参示例:{"addressId":593861699},其中addressId是调用“买家获取保存的收货地址信息列表”接口获取;
|
||||
2、使用地址编码传参示例:{"address":"桃浦镇 金达路888号贸易8楼","phone": "0517-88990077","mobile": "15251667788","fullName": "张三","postCode": "000000","districtCode": "310107"},其中districtCode需要调用“根据地址解析地区码”接口获取;
|
||||
3、直接使用文本地址示例:{"address":"网商路699号","phone": "0517-88990077","mobile": "15251667788","fullName": "张三","postCode": "000000","areaText": "滨江区","townText": "","cityText": "杭州市","provinceText": "浙江省"},省市区要传文本;
|
||||
4、优先级说明,如果同时传入以上参数,系统按从1至3的优先级获取地址,满足1的条件下不会使用上示2中的参数,满足2的条件下不会使用上示3中的参数;
|
||||
* author:wh
|
||||
* @param $address
|
||||
*/
|
||||
function setAddress($address){
|
||||
//{
|
||||
//"address":"网商路699号",
|
||||
//"phone":"0517-88990077",
|
||||
//"mobile":"15251667788",
|
||||
//"fullName":"张三",
|
||||
//"postCode":"000000",
|
||||
//"areaText":"滨江区",
|
||||
//"townText":"",
|
||||
//"cityText":"杭州市",
|
||||
//"provinceText":"浙江省"
|
||||
//}
|
||||
//用户收货地址
|
||||
$this->address = [
|
||||
//'addressId'=>$address['id'],
|
||||
'address'=>$address['address'],//街道地 网商路699号
|
||||
'phone'=>$address['mobile'],//电话 0517-88990077
|
||||
'mobile'=>$address['mobile'],//手机
|
||||
'fullName'=>$address['name'],
|
||||
'postCode'=>'000000',//邮编 000000
|
||||
'areaText'=>$address['area'],//区文本
|
||||
'townText'=>$address['town'],//镇文本
|
||||
'cityText'=>$address['city'],//市文本
|
||||
'provinceText'=>$address['provice'],//省份文本
|
||||
//'districtCode'=>'000000',//地址编码 310107
|
||||
];
|
||||
|
||||
}
|
||||
function setGoods($goods,$buy_num){
|
||||
$this->goods = [
|
||||
'offerId'=>$goods['offerid'],
|
||||
'specId'=>$goods['specid'],//商品规格id
|
||||
'quantity'=>$buy_num,//$goods['quantity'],//商品数量(计算金额用)
|
||||
|
||||
];
|
||||
}
|
||||
/**
|
||||
* desc:创建分销订单
|
||||
*
|
||||
* 获取订单运费,请调用预览订单接口 alibaba.createOrder.preview
|
||||
* author:wh
|
||||
*/
|
||||
function createOrder($order){
|
||||
if(empty($this->authObj)){
|
||||
throw new Exception('未初始化授权对象');
|
||||
}
|
||||
if(empty($this->address)){
|
||||
throw new Exception('未设置收货地址');
|
||||
}
|
||||
if(empty($this->goods)){
|
||||
throw new Exception('未设置商品信息');
|
||||
}
|
||||
//$base_url = "https://gw.open.1688.com/openapi/";
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.fastCreateOrder/".$this->authObj->config['appkey'];
|
||||
|
||||
if(empty($this->tradeType)){
|
||||
throw new Exception('交易类型必须');
|
||||
}
|
||||
$request_data = ['tradeType'=>$this->tradeType];
|
||||
|
||||
//boutiquefenxiao(新分销严选)
|
||||
$request_data['flow'] = 'boutiquefenxiao';
|
||||
$request_data['isvBizTypeStr'] = 'fenxiaoMedia';
|
||||
|
||||
$request_data['message'] = $order['remark'];//买家留言
|
||||
//地址
|
||||
$request_data['addressParam'] = json_encode($this->address,JSON_UNESCAPED_UNICODE);
|
||||
//商品信息
|
||||
$request_data['cargoParamList'] = json_encode($this->goods,JSON_UNESCAPED_UNICODE);
|
||||
//发票信息
|
||||
$request_data['invoiceParam'] = json_encode($this->invoice,JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建订单前预览数据接口
|
||||
*
|
||||
* 订单创建只允许购买同一个供应商的商品。
|
||||
* 本接口返回创建订单相关的优惠等信息。
|
||||
* 1、校验商品数据是否允许订购。 2、校验代销关系 3、校验库存、起批量、是否满足混批条件
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.createOrder.preview-1&aopApiCategory=trade_new
|
||||
*/
|
||||
function previewOrder(){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.createOrder.preview/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//boutiquefenxiao(新分销严选)
|
||||
$request_data['flow'] = 'boutiquefenxiao';
|
||||
//$request_data['isvBizTypeStr'] = 'fenxiaoMedia';
|
||||
|
||||
//$request_data['message'] = $order['remark'];//买家留言
|
||||
//地址
|
||||
$request_data['addressParam'] = json_encode($this->address,JSON_UNESCAPED_UNICODE);
|
||||
//商品信息
|
||||
$request_data['cargoParamList'] = json_encode($this->goods,JSON_UNESCAPED_UNICODE);
|
||||
//发票信息
|
||||
$request_data['invoiceParam'] = json_encode($this->invoice,JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消交易
|
||||
*
|
||||
* 买家或者卖家取消交易,注意只有特定状态的交易才能取消,1688可用于取消未付款的订单。
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.cancel-1&aopApiCategory=trade_new
|
||||
*
|
||||
* author:wh
|
||||
* @param string $order_id 订单号
|
||||
* @param string $cancelReason 原因描述;buyerCancel:买家取消订单;sellerGoodsLack:卖家库存不足;other:其它
|
||||
*
|
||||
* 返回:{
|
||||
"success": true
|
||||
}
|
||||
*/
|
||||
function cancelOrder($order_id, $cancelReason, $remark=''){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.cancel/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['tradeID'] = $order_id;
|
||||
$request_data['webSite'] = 1688;
|
||||
//原因描述;buyerCancel:买家取消订单;sellerGoodsLack:卖家库存不足;other:其它
|
||||
$request_data['cancelReason'] = $cancelReason;
|
||||
if($remark){
|
||||
$request_data['remark'] = $remark;
|
||||
}
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改订单备忘
|
||||
*
|
||||
* 授权用户为卖家修改卖家备忘,授权用户为买家修改买家备忘 注意:该接口可重复调用,备注内容将覆盖前一次调用
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.order.memoAdd-1&aopApiCategory=trade_new
|
||||
*
|
||||
*/
|
||||
function updateOrderRemark($order_id,$remark){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.order.memoAdd/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
$request_data['orderId'] = $order_id;
|
||||
$request_data['memo'] = $remark;
|
||||
//备忘图标,目前仅支持数字。1位红色图标,2为蓝色图标,3为绿色图标,4为黄色图标
|
||||
$request_data['remarkIcon'] = 2;
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据地址解析地区码
|
||||
*
|
||||
* 根据地址信息,解析地区码
|
||||
*
|
||||
* doc:https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.addresscode.parse-1&aopApiCategory=trade_new
|
||||
*
|
||||
*返回:{
|
||||
"result": {
|
||||
"address": "网商路699号",
|
||||
"addressCode": "330108",
|
||||
"isDefault": false,
|
||||
"latest": false,
|
||||
"postCode": "310051"
|
||||
}
|
||||
}
|
||||
*/
|
||||
function getAreaCode($address){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.addresscode.parse/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//地址信息 eg: 浙江省 杭州市 滨江区网商路699号
|
||||
$request_data['addressInfo'] = $address;
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取交易地址代码表详情
|
||||
*
|
||||
* 获取交易地址代码表,该API会返回输入code的详情和该code的下一级地区code.
|
||||
*
|
||||
* doc: https://open.1688.com/api/apidocdetail.htm?id=com.alibaba.trade:alibaba.trade.addresscode.get-1&aopApiCategory=trade_new
|
||||
*
|
||||
* 返回:{
|
||||
"result": {
|
||||
"code": "330108",
|
||||
"name": "滨江区",
|
||||
"parentCode": "330100",
|
||||
"post": "310051",
|
||||
"children": ["330108001",
|
||||
"330108002",
|
||||
"330108003"]
|
||||
}
|
||||
}
|
||||
*/
|
||||
function getAreaCodeDetail($areaCode){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.addresscode.get/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
//地址code码 eg: 330108
|
||||
$request_data['areaCode'] = $areaCode;
|
||||
$request_data['webSite'] = 1688;
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/30} {12:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alibaba\distributes\strict;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\alibaba\distributes\BaseStrict;
|
||||
/**
|
||||
* 支付相关
|
||||
*
|
||||
* Class StrictPay
|
||||
* @package app\index\logic\alibaba\distributes\strict
|
||||
*/
|
||||
class StrictPay extends BaseStrict
|
||||
{
|
||||
|
||||
/**
|
||||
* desc: 查询订单是否开通免密支付
|
||||
* author:wh
|
||||
*/
|
||||
function queryOrderIsNoPassPay(){
|
||||
$urlPath = "param2/1/com.alibaba.trade/alibaba.trade.pay.protocolPay.isopen/".$this->authObj->config['appkey'];
|
||||
$request_data = [];
|
||||
|
||||
$res = $this->authObj->request($urlPath, $request_data);
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
82
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayLogic.php
vendored
Normal file
82
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/AlipayLogic.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/08/24} {10:20}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay;
|
||||
|
||||
|
||||
use app\index\model\AppOrderPayReqRecordModel;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 调起支付宝支付
|
||||
*
|
||||
* Class AlipayLogic
|
||||
*
|
||||
* 依赖:
|
||||
* composer require wanghua/general-utility-tools-php dev-master
|
||||
* @deprecated
|
||||
*/
|
||||
class AlipayLogic
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:调起支付
|
||||
* author:wh
|
||||
* @return false|mixed|\SimpleXMLElement|string|\提交表单HTML文本|null
|
||||
* @throws \think\Exception
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
//function pay(string $notify_url,string $return_url=''){
|
||||
|
||||
|
||||
///* *
|
||||
// * 功能:支付宝手机网站支付接口(alipay.trade.wap.pay)接口调试入口页面
|
||||
// * 版本:2.0
|
||||
// * 修改日期:2016-11-01
|
||||
// * 说明:
|
||||
// * 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
|
||||
// 请确保项目文件有可写权限,不然打印不了日志。
|
||||
// */
|
||||
//
|
||||
//header("Content-type: text/html; charset=utf-8");
|
||||
//
|
||||
//
|
||||
//require_once Tools::get_root_path().'library/AlipayTradeWapPay/wappay/service/AlipayTradeService.php';
|
||||
//require_once Tools::get_root_path().'library/AlipayTradeWapPay/wappay/buildermodel/AlipayTradeWapPayContentBuilder.php';
|
||||
////require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../config.php';
|
||||
//$config = config('pay_config.alipay');
|
||||
//if(empty($_POST['WIDout_trade_no']) || trim($_POST['WIDout_trade_no'])=="") return null;
|
||||
////商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
//$out_trade_no = input('WIDout_trade_no');
|
||||
//if(empty($out_trade_no)){
|
||||
// return '参数错误';
|
||||
//}
|
||||
//$order = AppOrderPayReqRecordModel::getOrder($out_trade_no);
|
||||
//if(empty($order)){
|
||||
// return '订单错误';
|
||||
//}
|
||||
////超时时间
|
||||
//$timeout_express="1m";
|
||||
//
|
||||
//$payRequestBuilder = new \AlipayTradeWapPayContentBuilder();
|
||||
//$payRequestBuilder->setBody($order['goods_name']);
|
||||
//$payRequestBuilder->setSubject($order['goods_name']);
|
||||
//$payRequestBuilder->setOutTradeNo($out_trade_no);
|
||||
//$payRequestBuilder->setTotalAmount($order['goods_price']);
|
||||
//$payRequestBuilder->setTimeExpress($timeout_express);
|
||||
//
|
||||
//$payResponse = new \AlipayTradeService($config);
|
||||
|
||||
|
||||
//$result = $payResponse->wapPay($payRequestBuilder,$return_url,$notify_url);
|
||||
//return $result;
|
||||
//}
|
||||
}
|
||||
195
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayScanPay.php
vendored
Normal file
195
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/pay/AlipayScanPay.php
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/6/10} {23:15}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\pay;
|
||||
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use app\common\model\TabConf;
|
||||
use app\common\tools\EmailTool;
|
||||
use app\index\logic\AlipayBarcodePayLogic;
|
||||
use app\index\logic\CheckstandLogic;
|
||||
use app\index\model\OrderModel;
|
||||
use app\index\model\PartnerAccountModel;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝面对面扫码支付(用户出示付款码)
|
||||
*
|
||||
* 【扫码支付专用】
|
||||
*
|
||||
* 依赖:"alipaysdk/easysdk": "^2.2" || composer require alipaysdk/easysdk
|
||||
*
|
||||
* Class AlipayScanPay
|
||||
* @package wanghua\general_utility_tools_php\alipay\transfer
|
||||
*/
|
||||
class AlipayScanPay
|
||||
{
|
||||
/**
|
||||
* 支付参数配置
|
||||
* @var array
|
||||
*/
|
||||
private array $config = [];
|
||||
|
||||
function __construct($config)
|
||||
{
|
||||
/** 设置支付参数 */
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:面对面扫码支付-(扫用户的付款码)
|
||||
*
|
||||
* 注意:
|
||||
* 免密支付是同步返回支付结果,输入密码支付是异步通知支付结果,
|
||||
* 所以需要处理异步支付结果通知。
|
||||
* @param array $order 订单信息
|
||||
* @param string $auth_code 扫码枪扫描后的授权码
|
||||
* @return array 返回支付结果(一维数组)
|
||||
*/
|
||||
function scanPay($order,$auth_code){
|
||||
if(empty($auth_code)){
|
||||
return Tools::set_res(500,'授权码错误');
|
||||
}
|
||||
try {
|
||||
//1. 设置参数(全局只需设置一次)
|
||||
Factory::setOptions($this->getOptions());
|
||||
//2. 发起API调用(以支付能力下的统一收单交易创建接口为例)
|
||||
$result = Factory::payment()->faceToFace()
|
||||
->optional('scene','bar_code')
|
||||
->pay($order['title'], $order['orderid'], $order['real_amount'], $auth_code);
|
||||
|
||||
if($result->code == 10003){
|
||||
return Tools::set_res(230,'交易进行中(提示用户输入密码)'.$result->msg);
|
||||
}
|
||||
//必须解析json
|
||||
$resp = json_decode($result->httpBody, true);
|
||||
//支付宝面对面扫码支付后续流程
|
||||
return Tools::set_ok('ok',$resp['alipay_trade_pay_response']);//返回支付结果(一维数组)
|
||||
} catch (\Exception $e) {
|
||||
$err_data = [
|
||||
'error'=>'支付宝付款码支付错误'.$e->getMessage(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
];
|
||||
Tools::log_to_write_txt($err_data);
|
||||
return Tools::set_fail('错误.'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取支付配置
|
||||
* author:wh
|
||||
* @return Config
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getOptions()
|
||||
{
|
||||
if(empty($this->config)){
|
||||
throw new Exception('支付宝配置错误');
|
||||
}
|
||||
if(empty($this->config['notifyUrl'])){
|
||||
throw new Exception('支付宝配置错误:notifyUrl通知地址字段必须配置(免密支付是同步返回支付结果,输入密码支付是异步通知支付结果)');
|
||||
}
|
||||
$config = $this->config;
|
||||
$options = new Config();
|
||||
$options->protocol = 'https';
|
||||
$options->gatewayHost = 'openapi.alipay.com';
|
||||
$options->signType = $config['sign_type'];
|
||||
|
||||
$options->appId = $config['app_id'];//'<-- 请填写您的AppId,例如:2019022663440152 -->';
|
||||
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
$options->merchantPrivateKey = $config['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
|
||||
$options->alipayCertPath = Tools::get_root_path().$config['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$options->alipayRootCertPath = Tools::get_root_path().$config['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$options->merchantCertPath = Tools::get_root_path().$config['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
|
||||
|
||||
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
// $options->alipayPublicKey = '<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
$options->notifyUrl = $this->config['notifyUrl'];//request()->domain().'/index/alipay/notify';//"<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->";
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:支付宝扫码异步通知
|
||||
*
|
||||
* 【通知结果是一维数组】
|
||||
*
|
||||
* {"gmt_create":"2024-06-10 11:53:37","charset":"UTF-8","seller_email":"15023017325",
|
||||
* "subject":"购物消费",
|
||||
* "sign":"oCR3X0ViRrydigLMeOCTrMBNx7O8bSZnEflT0qZYo0gXk2jTI2OVB9mG2UPCkGuSND3wq/pMRFN
|
||||
* ljuz+2r3KMha9a6ArD/ey8w1am3yCKI+FMqUMQSv9TJqfpWdAsc8B45egtr+txBBOA1NMfN41hPnTxM3QzQ82cm
|
||||
* 7VYw6pnYpxJVj/3AsqYxY+wcyMq5+v25eC4TgBo+YJ9pfb3rqaAV91cJBoHRq1Cwh0XEnOzm9zpv7b5cu3r+V0oeW
|
||||
* wTCCi8S1TXW2dfE4H8o63xgASYfJO2fgGIu19YICQdUONkDhu9Tfbf3fFf9SHw3RIw8zrQRqkwAXC32NwfUv4Ru5NqQ==",
|
||||
* "buyer_id":"2088612757425274","invoice_amount":"3258.60","notify_id":"2024061001222115350025271439748729",
|
||||
* "fund_bill_list":"[{\"amount\":\"3258.60\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
|
||||
* "notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"3258.60",
|
||||
* "app_id":"2021004136614333","buyer_pay_amount":"3258.60","sign_type":"RSA2",
|
||||
* "seller_id":"2088642975857443","gmt_payment":"2024-06-10 11:53:50",
|
||||
* "notify_time":"2024-06-10 12:07:40","version":"1.0","out_trade_no":"cs25obpv1717991615660",
|
||||
* "total_amount":"3258.60","trade_no":"2024061022001425271426453509","auth_app_id":"2021004136614333",
|
||||
* "buyer_logon_id":"146***@qq.com","point_amount":"0.00"}
|
||||
*
|
||||
* author:wh
|
||||
* param function $fn 传入订单处理逻辑函数 要求返回success、fail
|
||||
* @return string
|
||||
*/
|
||||
function scanPayNotify($fn){
|
||||
Tools::log_to_write_txt([
|
||||
'支付宝异步通知',
|
||||
'input'=>input()
|
||||
]);
|
||||
|
||||
$out_trade_no = input('out_trade_no');
|
||||
if(empty($out_trade_no)){
|
||||
Tools::log_to_write_txt(['error'=>'out_trade_no为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
//$order = Db::table(TabConf::$fa_order)
|
||||
// ->where('orderid',$out_trade_no)
|
||||
// ->find();
|
||||
//if(empty($order)){
|
||||
// Tools::log_to_write_txt(['error'=>'订单不存在,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
// return '';
|
||||
//}
|
||||
//该字段用于判断成功、失败
|
||||
$trade_status = input('trade_status');
|
||||
if(empty($trade_status)){
|
||||
Tools::log_to_write_txt(['error'=>'trade_status为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
if(empty($this->config['seller_id'])){
|
||||
Tools::log_to_write_txt(['error'=>'卖家seller_id为空,文件:'.__FILE__.',line:'.__LINE__]);
|
||||
return '';
|
||||
}
|
||||
|
||||
//判断来源
|
||||
$seller_id = input('seller_id');
|
||||
if($seller_id != $this->config['seller_id']){
|
||||
Tools::log_to_write_txt(['error'=>'支付通知来源错误','seller_id'=>$seller_id,'config'=>$this->config['seller_id']]);
|
||||
return 'fail';
|
||||
}
|
||||
//支付宝面对面扫码支付后续流程
|
||||
$result = input();
|
||||
//异步通知
|
||||
//$res = CheckstandLogic::alipayScanSuccessFlow($result,$order);
|
||||
//if($res['code'] == 200 || $res['code'] == 230){//成功或进行中
|
||||
// return 'success';
|
||||
//}
|
||||
return $fn($result);//要求返回success、fail
|
||||
}
|
||||
}
|
||||
143
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/AlipayTransfer.php
vendored
Normal file
143
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/AlipayTransfer.php
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/09/24} {19:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\transfer;
|
||||
|
||||
use Alipay\EasySDK\Kernel\Config;
|
||||
use Alipay\EasySDK\Kernel\Factory;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 支付宝转账(独立且区别于支付,连参数都不能用支付参数)
|
||||
*
|
||||
* 注:换句话说,转账是转账的参数,支付是支付的参数,不能混为一谈(以此备注长记性)。
|
||||
*
|
||||
* 环境要求:PHP7.0+,ThinkPHP5.0+
|
||||
*
|
||||
* 依赖:
|
||||
* composer require alipaysdk/easysdk:^2.0
|
||||
*
|
||||
* composer require wanghua/general-utility-tools-php dev-master
|
||||
*
|
||||
* 重要说明:
|
||||
*
|
||||
* 支付宝开放平台可能有多个应用,可能存在一个默认应用(应用名称:应用2.0签约2020102692466480),转账配置就用此应用的参数,而不是其它应用的配置!
|
||||
*
|
||||
*/
|
||||
class AlipayTransfer
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:转账到支付宝(证书模式)
|
||||
* author:wh
|
||||
* @param array $alipayConfig
|
||||
* @param $transferConfig TransferConfig.php
|
||||
* @return mixed
|
||||
*
|
||||
* 使用案例:
|
||||
*
|
||||
function transfer(array $trans_data){
|
||||
$alipayConfig = \config('pay_config.alipay_transfer');//转账配置
|
||||
|
||||
$trans_config = new TransferConfig();
|
||||
$trans_config->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$trans_config->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$trans_config->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
$order_prefix = 'trs';
|
||||
$order_id = Tools::to_create_order_no($order_prefix);
|
||||
$trans_config->order_id = $order_id;//订单号 必须
|
||||
$trans_config->timestamp = Tools::get_now_date();//请求时间 eg:2020-01-08 10:12:50
|
||||
$trans_config->trans_amount = $trans_data['trans_amount'];//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
$trans_config->order_title = $trans_data['order_title'];//订单标题 可选
|
||||
$trans_config->phone = $trans_data['phone'];//支付宝登录手机号 必须
|
||||
$trans_config->name = $trans_data['name'];//支付宝真实姓名 必须
|
||||
$trans_config->remark = $trans_data['remark'];//支付备注 可选
|
||||
|
||||
|
||||
$trans = new AlipayTransfer();
|
||||
Tools::log_to_write_txt(['转账到支付宝,入参:'=>input(), 'trans_config'=>$trans_config]);
|
||||
$pay_res = $trans->alitransfer($alipayConfig, $trans_config);
|
||||
Tools::log_to_write_txt(['转账到支付宝,出参:'=>$pay_res]);
|
||||
//直接返回转账结果,自主验证成功失败的status。code=10000表示操作成功,status=SUCCESS表示转账成功
|
||||
//由于是同步响应,所以不需要对结果验签
|
||||
return $pay_res;
|
||||
}
|
||||
*
|
||||
*/
|
||||
function alitransfer(array $alipayConfig, $transferConfig){
|
||||
//$transferConfig = new TransferConfig();
|
||||
Factory::setOptions($this->getAlipayOptions($alipayConfig, $transferConfig));
|
||||
|
||||
$method = 'alipay.fund.trans.uni.transfer';
|
||||
//公共参数
|
||||
$textParams = [
|
||||
'app_id'=>$alipayConfig['app_id'],
|
||||
'charset'=>'utf-8',
|
||||
'sign_type'=>'RSA2',
|
||||
'timestamp'=>$transferConfig->timestamp,
|
||||
'version'=>'1.0',
|
||||
];
|
||||
|
||||
//请求参数
|
||||
//订单号前缀
|
||||
$biz_content = [
|
||||
'out_biz_no'=>$transferConfig->order_id,//商家支付订单号
|
||||
'trans_amount'=>$transferConfig->trans_amount,
|
||||
'product_code'=>'TRANS_ACCOUNT_NO_PWD',
|
||||
'biz_scene'=>'DIRECT_TRANSFER',
|
||||
'order_title'=>$transferConfig->order_title,
|
||||
'payee_info'=>[
|
||||
'identity'=>$transferConfig->phone,//手机号
|
||||
'identity_type'=>'ALIPAY_LOGON_ID',
|
||||
'name'=>$transferConfig->name,//参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。
|
||||
],
|
||||
'remark'=>$transferConfig->remark,
|
||||
];
|
||||
$pay_res = Factory::util()->generic()->execute($method,$textParams,$biz_content);
|
||||
|
||||
return $pay_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:证书模式参数(非证书模式参数需单独获取)
|
||||
* author:wh
|
||||
* @param array $alipayConfig 支付宝转账配置(非支付配置)
|
||||
* @return Config
|
||||
*/
|
||||
protected function getAlipayOptions(array $alipayConfig, $transferConfig)
|
||||
{
|
||||
$options = new Config();
|
||||
$options->protocol = 'https';
|
||||
$options->gatewayHost = 'openapi.alipay.com';
|
||||
$options->signType = 'RSA2';
|
||||
|
||||
//'<-- 请填写您的AppId,例如:2019022663440152 -->'
|
||||
$options->appId = $alipayConfig['app_id'];//'2021002103639985';
|
||||
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
$options->merchantPrivateKey = $alipayConfig['alipay_app_private_key'];//'<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->';
|
||||
|
||||
$options->alipayCertPath = $transferConfig->cert_path_alipayCertPublicKey_RSA2;//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$options->alipayRootCertPath = $transferConfig->cert_path_alipayRootCert;//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$options->merchantCertPath = $transferConfig->appCertPublicKey;//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->';
|
||||
|
||||
//注:如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
// $options->alipayPublicKey = $alipayConfig['alipay_public_key'];//'<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->';
|
||||
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
$options->notifyUrl = $transferConfig->notifyUrl;//"<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->";
|
||||
|
||||
//可设置AES密钥,调用AES加解密相关接口时需要(可选)
|
||||
//$options->encryptKey = "<-- 请填写您的AES密钥,例如:aa4BtZ4tspm2wnXLb1ThQA== -->";
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
63
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/TransferConfig.php
vendored
Normal file
63
digital_doctor/vendor/wanghua/general-utility-tools-php/src/alipay/transfer/TransferConfig.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/09/24} {20:07}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\alipay\transfer;
|
||||
|
||||
|
||||
/**
|
||||
* 调用转账之前请配置此参数
|
||||
*
|
||||
* 配置示例:
|
||||
*
|
||||
$alipayConfig = \config('pay_config.alipay_transfer');//转账配置
|
||||
|
||||
$trans_config = new TransferConfig();
|
||||
$trans_config->cert_path_alipayCertPublicKey_RSA2 = Tools::get_root_path().$alipayConfig['cert_path_alipayCertPublicKey_RSA2'];//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
$trans_config->cert_path_alipayRootCert = Tools::get_root_path().$alipayConfig['cert_path_alipayRootCert'];//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
$trans_config->appCertPublicKey = Tools::get_root_path().$alipayConfig['appCertPublicKey'];//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
|
||||
|
||||
$order_prefix = 'trs';
|
||||
$order_id = Tools::to_create_order_no($order_prefix);
|
||||
$trans_config->order_id = $order_id;//订单号 必须
|
||||
$trans_config->timestamp = Tools::get_now_date();//请求时间 eg:2020-01-08 10:12:50
|
||||
$trans_config->trans_amount = '0.21';//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
$trans_config->order_title = '代理提现';//订单标题 可选
|
||||
$trans_config->phone = '18290416033';//支付宝登录手机号 必须
|
||||
$trans_config->name = '王华';//支付宝真实姓名 必须
|
||||
$trans_config->remark = '代理提现到支付宝';//支付备注 可选
|
||||
|
||||
$trans = new AlipayTransfer();
|
||||
$pay_res = $trans->alitransfer($alipayConfig, $trans_config);
|
||||
|
||||
dump($pay_res);
|
||||
*
|
||||
*/
|
||||
class TransferConfig
|
||||
{
|
||||
//'<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->';
|
||||
public $cert_path_alipayCertPublicKey_RSA2 = '';//必须
|
||||
//'<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt" -->';
|
||||
public $cert_path_alipayRootCert = '';//必须
|
||||
//'<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->'
|
||||
public $appCertPublicKey = '';//必须
|
||||
|
||||
public $notifyUrl = '';//接收异步通知(可选)
|
||||
|
||||
|
||||
//业务参数
|
||||
public $order_id = '';//订单号 必须
|
||||
public $timestamp = '';//请求时间 必须 eg:2020-01-08 10:12:50
|
||||
public $trans_amount = '';//转账金额 必须 且为字符串 最低0.1元 取值范围[0.1,100000000]
|
||||
public $order_title = '';//订单标题 可选
|
||||
public $phone = '';//支付宝登录手机号 必须
|
||||
public $name = '';//支付宝真实姓名 必须
|
||||
public $remark = '';//支付备注 可选
|
||||
|
||||
|
||||
}
|
||||
425
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/Api.php
vendored
Normal file
425
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/Api.php
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {11:21}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\mysql\lib\Table;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Api extends BaseLibApi
|
||||
{
|
||||
private $apidir = '';
|
||||
private $namespace = 'app\api\controller';
|
||||
|
||||
private $table_obj = null;
|
||||
|
||||
//一维数组
|
||||
private $functions_arr = [];//要创建的初始方法
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//默认api目录
|
||||
$this->apidir = Tools::get_root_path().'application/api/controller/';
|
||||
if(!$this->table_obj)
|
||||
$this->table_obj = new Table();
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api目录
|
||||
* author:wh
|
||||
* @param string $dir api创建目录,格式必须按照例子填写 eg: application/api/controller/
|
||||
*/
|
||||
function setapidir(string $dir){
|
||||
$this->apidir = $dir;
|
||||
$nsp = str_replace('application','app',substr($dir,0,strlen($dir)-2));
|
||||
$this->namespace = str_replace('/','\\',$nsp);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:替换表前缀
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return false|string
|
||||
*/
|
||||
function replaceTablePrefix($tablename){
|
||||
$prefix = config('database.prefix');
|
||||
if($prefix){
|
||||
return substr($tablename,strlen($prefix));
|
||||
}
|
||||
$tmp_prefix = 't_';
|
||||
if(false !== strpos($tablename,$tmp_prefix)){
|
||||
return substr($tablename,strlen($tmp_prefix));
|
||||
}
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置方法名称
|
||||
*
|
||||
* author:wh
|
||||
* @param array $functions_arr
|
||||
*/
|
||||
function setApiFunctionsName(array $functions_arr){
|
||||
$this->functions_arr = array_merge($functions_arr,$this->functions_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:动态创建方法
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function syncCreateFunction(array $func_name_arr){
|
||||
$code = '';
|
||||
foreach ($func_name_arr as $func_name=>$func_remark){ //接口方法公共代码模块
|
||||
$commonFunctionCodeModule = $this->commonFunctionCodeModule($func_remark);
|
||||
$code .= <<<EOF
|
||||
|
||||
/**
|
||||
* desc:{$func_remark}
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
function {$func_name}(){
|
||||
{$commonFunctionCodeModule}
|
||||
}
|
||||
EOF;
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建查询接口的代码体
|
||||
*
|
||||
* 本接口只针对简单查询逻辑
|
||||
*
|
||||
* and
|
||||
* like%,%like%,
|
||||
* >, <, >=, <=, !=
|
||||
* between
|
||||
* in
|
||||
*
|
||||
* author:wh
|
||||
* @param array $select_in_params eg:
|
||||
* [
|
||||
* 'gameid'=>['and'],
|
||||
* 'nickname'=>['like%'],
|
||||
* 'reg_time'=>['between'],//时间区间查询
|
||||
* 'audit_time'=>['2015-01-3','eq'],//时间区间查询
|
||||
* ]
|
||||
*
|
||||
*/
|
||||
function setQueryCodeBody(array $select_in_params){
|
||||
$code = '';
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:写入查询接口的代码体
|
||||
*
|
||||
* author:wh
|
||||
* @param array $insert_params
|
||||
* @return string
|
||||
*/
|
||||
function setInsertCodeBody(array $insert_params){
|
||||
$code = '';
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:快速构建api代码
|
||||
*
|
||||
* 本方法不验证接口名称是否重复
|
||||
*
|
||||
* author:wh
|
||||
* @param string $tablename 数据表名称
|
||||
* @param array $func_name_arr 方法名称数组 eg:['getData'=>'获取数据','function_aaa'=>'function_注释aaa']
|
||||
*/
|
||||
function buildApi(string $tablename, array $func_name_arr){
|
||||
//deal table name
|
||||
$tablename = $this->replaceTablePrefix($tablename);
|
||||
|
||||
//基础 start
|
||||
//create base controller
|
||||
$this->buildBaseApiPublicController();//开放控制器
|
||||
$this->buildBaseApiAuthController();//权限控制器
|
||||
$this->errController();//错误控制器
|
||||
//基础 end
|
||||
|
||||
//接口类名
|
||||
$classname = ucfirst(Tools::convertUnderLine($tablename));
|
||||
//接口注释
|
||||
$comment = $this->table_obj->getTableComment($tablename);
|
||||
|
||||
//批量构建方法代码
|
||||
$build_functions_code = $this->syncCreateFunction($func_name_arr);
|
||||
|
||||
//PHP文件名,不含物理路径
|
||||
$file_name = $classname.$this->ext();
|
||||
|
||||
//PHP文件路径和文件名
|
||||
$php_file = $this->apidir.$file_name;
|
||||
|
||||
if(file_exists($php_file)){
|
||||
//追加代码
|
||||
//读取并删除最后的“}”
|
||||
$php_code_str = file_get_contents($php_file);
|
||||
$sub_php_code_str = mb_substr($php_code_str,0,mb_strlen($php_code_str)-2);
|
||||
//追加新的代码
|
||||
$sub_php_code_str .= $build_functions_code ."\n }";
|
||||
//清空代码
|
||||
file_put_contents($php_file,'');
|
||||
//追加
|
||||
$this->createFileExists($php_file,$sub_php_code_str);
|
||||
}else{
|
||||
//创建代码文件
|
||||
$use_tpl = $this->useTpl();
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
{$use_tpl}
|
||||
|
||||
/**
|
||||
* {$comment}
|
||||
* Class {$classname}
|
||||
* @package {$this->namespace}
|
||||
*/
|
||||
class {$classname} extends BaseApiPublicController
|
||||
{
|
||||
|
||||
|
||||
|
||||
{$build_functions_code}
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:公共方法模块
|
||||
*
|
||||
* author:wh
|
||||
* @param $comment
|
||||
* @return string
|
||||
*/
|
||||
private function commonFunctionCodeModule($comment){
|
||||
$php = <<<EOF
|
||||
try {
|
||||
Tools::log_to_write_txt(['title'=>'{$comment},__IN:','INPUT'=>input()]);
|
||||
//region 校验区 start
|
||||
|
||||
//endregion 校验区 end
|
||||
|
||||
|
||||
|
||||
|
||||
//region 业务逻辑区 start
|
||||
|
||||
//endregion 业务逻辑区 end
|
||||
|
||||
|
||||
|
||||
|
||||
//响应结果处理
|
||||
Tools::log_to_write_txt(['title'=>'{$comment},__OUT:','OUTPUT'=>[]]);
|
||||
return json(Tools::set_res(200,'ok'));
|
||||
}catch (\Exception \$e){
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'{$comment},API异常。'.\$e->getMessage(),
|
||||
'入参'=>input(),
|
||||
'error_info'=>\$e->getTraceAsString()
|
||||
]);
|
||||
return json(Tools::set_res(500,'系统繁忙'));
|
||||
}
|
||||
EOF;
|
||||
|
||||
return $php;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api基础开放控制器
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function buildBaseApiPublicController(){
|
||||
$file_name = 'BaseApiPublicController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api基础开放架构
|
||||
*
|
||||
* 所有开放接口继承此父类
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api基础权限控制器
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
private function buildBaseApiAuthController(){
|
||||
$file_name = 'BaseApiAuthController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api基础权限架构
|
||||
*
|
||||
* 所有权限接口继承此父类
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:api底层基础控制器架构
|
||||
*
|
||||
* [按需创建][可单独调用]
|
||||
*
|
||||
* 如果存在则不创建
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function buildBaseApiController(){
|
||||
$file_name = 'BaseApiController';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
use think\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* desc:api底层基础控制器架构
|
||||
*
|
||||
* author:
|
||||
*/
|
||||
class {$file_name} extends Controller
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:use模块
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
private function useTpl(){
|
||||
$php = <<<EOF
|
||||
use wanghua\general_utility_tools_php\\tool\Tools;
|
||||
EOF;
|
||||
return $php;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误控制器
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function errController(){
|
||||
$file_name = 'Err';
|
||||
$php = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace {$this->namespace};
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\\framework\\base\PublicController;
|
||||
use wanghua\general_utility_tools_php\\tool\Tools;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 错误(异常)中转架构
|
||||
*
|
||||
* Class Err
|
||||
* @package app\index\controller
|
||||
*/
|
||||
class {$file_name} extends BaseApiPublicController
|
||||
{
|
||||
/**
|
||||
* desc:校验失败中转
|
||||
*
|
||||
* 场景:内网端口验证未通过时跳转;
|
||||
*
|
||||
* author:wh
|
||||
* @return \\think\\response\\Json
|
||||
*/
|
||||
function checkfailed(){
|
||||
|
||||
return json(Tools::set_res(500,'Permission denied',input()));
|
||||
}
|
||||
}
|
||||
EOF;
|
||||
|
||||
$php_file = $this->apidir.$file_name.$this->ext();
|
||||
|
||||
$this->createDir($this->apidir);
|
||||
|
||||
$this->createFile($php_file,$php);
|
||||
}
|
||||
}
|
||||
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/ApiDocument.php
vendored
Normal file
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/ApiDocument.php
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/5/15} {21:40}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\phpmailer\Exception;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* desc:接口文档构建器
|
||||
*
|
||||
* 使用步骤:
|
||||
* (new ApiDocument())->buildDoc();
|
||||
* Class ApiDocument
|
||||
*/
|
||||
class ApiDocument
|
||||
{
|
||||
private $api_cache_arr = [];//缓存所有接口
|
||||
public $api_domain = 'http://127.0.0.1:8080/';//接口域名/ip
|
||||
/**
|
||||
* @var string 接口控制器命名空间
|
||||
*/
|
||||
public $namespace = 'app\\api\\controller';
|
||||
/**
|
||||
* @var string 接口控制器基类,精确到类名,如:app\\common\\controller\\Api
|
||||
* 注意:如果同级目录存在多个基类,则设置直接基类,如果同级目录没有基类,则设置底层基类
|
||||
*/
|
||||
public $extends_base_class = '';
|
||||
//控制器目录物理路径
|
||||
public $controllerDirectory = '';
|
||||
/**
|
||||
* @var string 接口文档保存路径
|
||||
*/
|
||||
public $api_docs_save_dir = 'public/api_docs/';
|
||||
//设置过滤类
|
||||
private $filterClassArr = [];
|
||||
//设置过滤方法
|
||||
private $filterFunctionArr = [];
|
||||
|
||||
public function __construct($api_domain='',$controllerDirectory='')
|
||||
{
|
||||
//默认,如果是tp6,那application就要改为app了,自行传参吧
|
||||
$this->controllerDirectory = Tools::get_root_path().'application/api/controller';
|
||||
if($api_domain){
|
||||
$this->api_domain = $api_domain;
|
||||
}
|
||||
if($controllerDirectory){
|
||||
$this->controllerDirectory = $controllerDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置过滤类(类名)
|
||||
* 过滤场景:
|
||||
* 1、基类
|
||||
* 2、测试类
|
||||
* 3、定时任务类
|
||||
* 4、其它非必要类
|
||||
* author:wh
|
||||
* @param array $filterClassArr
|
||||
*/
|
||||
function setFilterClass(array $filterClassArr=[]){
|
||||
$this->filterClassArr = $filterClassArr;
|
||||
}
|
||||
function setFilterFunction(array $filterArr=[]){
|
||||
$this->filterFunctionArr = $filterArr;
|
||||
}
|
||||
/**
|
||||
* desc:构建接口文档,支持同步到在线文档
|
||||
* author:wh
|
||||
*/
|
||||
function buildDoc(){
|
||||
if(empty($this->extends_base_class)){
|
||||
throw new Exception('请设置接口控制器基类,精确到类名,如:app\\common\\controller\\Api');
|
||||
}
|
||||
$out_path = Tools::get_root_path().$this->api_docs_save_dir;
|
||||
if(!file_exists($out_path)){
|
||||
mkdir($out_path,0777,true);
|
||||
}
|
||||
$outputFile = $out_path.'api_list.md';
|
||||
$controllerClasses = [];
|
||||
|
||||
// 搜索控制器目录下的所有PHP文件
|
||||
foreach (glob($this->controllerDirectory . '/*.php') as $filename) {
|
||||
// 获取文件中的类名
|
||||
$class = basename($filename, '.php');
|
||||
if(in_array($class,$this->filterClassArr)){
|
||||
continue;
|
||||
}
|
||||
// 构建完整的命名空间类名
|
||||
$fullClassName = $this->namespace . '\\' . $class;
|
||||
foreach (explode(',',$this->extends_base_class) as $base_class){
|
||||
// 检查类是否有效并且是think\Controller的子类
|
||||
if (class_exists($fullClassName) && is_subclass_of($fullClassName, $base_class)) {
|
||||
$controllerClasses[] = $fullClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Markdown文件
|
||||
$file = fopen($outputFile, 'w') or die('无法创建文件');
|
||||
|
||||
$head_text = <<<EOF
|
||||
# API 文档
|
||||
## 接口列表
|
||||
###### (ctrl+f 搜索)(如果更改了路由,请根据路由规则定位)
|
||||
##### 请求域名:{$this->api_domain}
|
||||
##### 请求方式:POST(默认)
|
||||
|
||||
EOF;
|
||||
// 写入Markdown文件头部
|
||||
fwrite($file, $head_text);
|
||||
|
||||
foreach ($controllerClasses as $controllerClass) {
|
||||
$reflector = new \ReflectionClass($controllerClass);
|
||||
// 遍历控制器中的公共方法
|
||||
$methods = $reflector->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method) {
|
||||
//过滤方法
|
||||
if(in_array($method->name, $this->filterFunctionArr)){
|
||||
continue;
|
||||
}
|
||||
$exp_class = explode('\\',$controllerClass);
|
||||
//过滤类
|
||||
if(in_array($exp_class[count($exp_class)-1],$this->filterClassArr)){
|
||||
continue;
|
||||
}
|
||||
$comments = $method->getDocComment();
|
||||
if ($comments) {
|
||||
$this->processMethodComment($comments, $controllerClass, $method->name, $outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($file);
|
||||
|
||||
//缓存所有接口
|
||||
cache('api_doc_cache_arr',$this->api_cache_arr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:解析方法注释并写入Markdown文件
|
||||
* author:wh
|
||||
* @param $comments
|
||||
* @param $className
|
||||
* @param $methodName
|
||||
* @param $savepath
|
||||
*/
|
||||
private function processMethodComment($comments, $className, $methodName, $savepath) {
|
||||
if($methodName == '__construct'){
|
||||
return '';
|
||||
}
|
||||
$api_url = "/api/{$className}/{$methodName}";
|
||||
$js_api_func_name = "api_{$className}_{$methodName}";
|
||||
$str = <<<EOF
|
||||
|
||||
***
|
||||
```
|
||||
|
||||
EOF;
|
||||
|
||||
$comments_str = mb_substr($comments,0,-2);
|
||||
$class_arr = explode('\\',$className);
|
||||
$className = $class_arr[count($class_arr)-1];
|
||||
$className = $this->camelCaseToUnderscore($className);
|
||||
|
||||
|
||||
$api_name = "api/{$className}/{$methodName}";
|
||||
$doc_txt = <<<EOF
|
||||
* $api_name
|
||||
*/
|
||||
```
|
||||
EOF;
|
||||
$doc_txt= $str.$comments_str.$doc_txt." \r\n";
|
||||
$this->api_cache_arr[] = ['api_name'=>$api_name,'doc_txt'=>$doc_txt];
|
||||
file_put_contents($savepath,$doc_txt, FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:驼峰转下划线
|
||||
* author:wh
|
||||
* @param $string
|
||||
* @return string
|
||||
*/
|
||||
private function camelCaseToUnderscore($string) {
|
||||
$str = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $string));
|
||||
return strpos($str,'_')===0?substr($str,1):$str;
|
||||
}
|
||||
|
||||
function buildApiDocHtml(){
|
||||
$api_doc_cache_arr = cache('api_doc_cache_arr');
|
||||
$htm_str = "";
|
||||
$script_str = "";
|
||||
foreach ($api_doc_cache_arr as $item){
|
||||
$api_name = $item['api_name'];
|
||||
$doc_txt = $item['doc_txt'];
|
||||
|
||||
$function_name = str_replace('/','_',$api_name);
|
||||
$htm_str .= <<<EOF
|
||||
<div id="{$function_name}">
|
||||
<div class="markdown_content">{$doc_txt}</div>
|
||||
<div>
|
||||
按需填写其它接口参数:
|
||||
<textarea name="" id="{$function_name}_textarea" cols="100" rows="3">/{$api_name}</textarea>
|
||||
<a href='JavaScript:;' onclick="DocObject.{$function_name}()">测试</a>
|
||||
</div>
|
||||
<div class="{$function_name}_response_result"></div>
|
||||
|
||||
</div>
|
||||
EOF;
|
||||
$script_str.=<<<EOF
|
||||
{$function_name}(){
|
||||
let url = $('#{$function_name}_textarea').val();
|
||||
$.post(url,{},function(res) {
|
||||
$('.{$function_name}_response_result').html(JSON.stringify(res, null, "\\t"));
|
||||
$('.{$function_name}_response_result').attr('style','color:green');
|
||||
},'json');
|
||||
},
|
||||
EOF;
|
||||
|
||||
|
||||
}
|
||||
$html = <<<EOF
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>接口文档</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
{$htm_str}
|
||||
</div>
|
||||
</body>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="/static/common/js/marked.min.js"></script>
|
||||
<script>
|
||||
|
||||
$(function() {
|
||||
//加载markdown
|
||||
DocObject.markdown_content();
|
||||
});
|
||||
|
||||
let DocObject = {
|
||||
markdown_content(){
|
||||
$('.markdown_content').each(function(k,ele) {
|
||||
$(ele).html(marked.parse($(ele).html()));
|
||||
});
|
||||
},
|
||||
$script_str
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
||||
EOF;
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
230
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseApi.php
vendored
Normal file
230
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseApi.php
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/11} {16:14}
|
||||
*/
|
||||
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\api\ApiException;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃
|
||||
* desc:api交互
|
||||
*
|
||||
* author:wh
|
||||
* Class BaseApi
|
||||
* @package app\apidata
|
||||
*/
|
||||
class BaseApi
|
||||
{
|
||||
protected $post_url = '';
|
||||
private $prefix = 'api_';
|
||||
protected $log_file_name = 'log';
|
||||
protected $__sit__ = '';
|
||||
function __construct(string $url)
|
||||
{
|
||||
$this->post_url = $url;
|
||||
if(empty($this->post_url)) {
|
||||
Tools::log_to_write_txt(['error'=>'API OPERATE: '.ApiException::EMPTY_URL_ERROR], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::EMPTY_URL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置api请求日志文件名称
|
||||
*
|
||||
* 日志保存在runtime中
|
||||
*
|
||||
* author:wh
|
||||
* @param string $log_file_name
|
||||
*/
|
||||
function setLogFileName(string $log_file_name=''){
|
||||
if($log_file_name)$this->log_file_name = $log_file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc 获取记录日志的文件名
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getLogFileName(){
|
||||
return $this->prefix.$this->log_file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置调用位置
|
||||
* author:wh
|
||||
* @param $__file__
|
||||
* @param $__line__
|
||||
*/
|
||||
function setFileDir($__file__, $__line__){
|
||||
$this->__sit__ = $__file__.' > '.$__line__;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:错误位置
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function getErrorSit(){
|
||||
return $this->__sit__;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
*
|
||||
* author:wh
|
||||
* @param array $params
|
||||
*/
|
||||
private function mergeAuthParams(array &$params){
|
||||
$params['nonce'] = Tools::rand_str(10);
|
||||
$params['timestamp'] = time();
|
||||
$token = config('service_framework_config.sign_token');
|
||||
$params['sign'] = Tools::signature($params, $token);
|
||||
}
|
||||
/**
|
||||
* desc:执行post请求, 带权限参数
|
||||
*
|
||||
* 同框架、内部系统推荐
|
||||
*
|
||||
* 返回结果由code 错误码和msg 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以表单格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function apiPost($param){
|
||||
$this->mergeAuthParams($param);
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, $param);
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行post请求
|
||||
*
|
||||
* 返回结果由code 错误码和msg 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以json格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function do($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, json_encode($param));
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR.$this->post_url);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行请求
|
||||
*
|
||||
* do 方法的改版,返回结果由state 错误码和err 错误信息组成
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以json格式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function apiDo($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, json_encode($param));
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
|
||||
if(is_null($data['state'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
$data['code'] = isset($data['state'])&&$data['state']==0?200:$data['state'];
|
||||
$data['msg'] = isset($data['err'])?$data['err']:'api接口错误';
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* desc:执行请求
|
||||
*
|
||||
* 同框架、内部系统推荐
|
||||
*
|
||||
* author:wh
|
||||
* @param $param 以表单方式提交数据
|
||||
* @return array|bool|int|mixed|string
|
||||
* @throws ApiException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function doPost($param){
|
||||
|
||||
Tools::log_to_write_txt(['API OPERATE, IN',$this->post_url,$param], $this->getLogFileName());
|
||||
$res = Tools::curl_post($this->post_url, $param);
|
||||
Tools::log_to_write_txt(['API OPERATE, OUT',$this->post_url, $res], $this->getLogFileName());
|
||||
|
||||
if(empty($res['data'])) return $res;
|
||||
|
||||
$data = json_decode($res['data'], true);
|
||||
if(empty($data['code'])) {
|
||||
Tools::log_to_write_txt([
|
||||
'error: api操作,错误',
|
||||
'post_url'=>$this->post_url,
|
||||
'error_info'=>ApiException::API_RESPONSE_FORMAT_ERROR,
|
||||
'error_sit'=>$this->getErrorSit(),
|
||||
'result'=>$res,
|
||||
], $this->getLogFileName());
|
||||
throw new \Exception(ApiException::API_RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
54
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseLibApi.php
vendored
Normal file
54
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseLibApi.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {15:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
class BaseLibApi
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:创建目录
|
||||
*
|
||||
* author:wh
|
||||
* @param $apidir
|
||||
*/
|
||||
function createDir($apidir){
|
||||
if(!is_dir($apidir)){
|
||||
mkdir($apidir,0777,true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:文件存在不写入
|
||||
*
|
||||
* author:wh
|
||||
* @param $php_file
|
||||
* @param $php
|
||||
*/
|
||||
function createFile($php_file,$php){
|
||||
if(!file_exists($php_file)){
|
||||
file_put_contents($php_file,$php);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:追加文本
|
||||
*
|
||||
* author:wh
|
||||
* @param $php_file
|
||||
* @param $php
|
||||
*/
|
||||
function createFileExists($php_file,$php){
|
||||
file_put_contents($php_file,$php,FILE_APPEND);
|
||||
}
|
||||
|
||||
function ext(){
|
||||
return '.php';
|
||||
}
|
||||
}
|
||||
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseUserLogic.php
vendored
Normal file
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/api/BaseUserLogic.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/2/26} {10:54}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\api;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class BaseUserLogic
|
||||
{
|
||||
public $user_table = 'fa_users';
|
||||
|
||||
/**
|
||||
* desc:【通用】用户登录逻辑
|
||||
*
|
||||
* 请求端加密,服务端校验
|
||||
*
|
||||
* 签名规则
|
||||
* 请求参数:
|
||||
username //用户名
|
||||
password //密码 md5(md5('a123456')) d477887b0636e5d87f79cc25c99d7dc9
|
||||
timestamp //请求时间戳 2020-01-01 12:34:07
|
||||
noncestr //随机字符串8位
|
||||
sign //签名串,参考全站签名规则
|
||||
|
||||
other_params //其它接口的其它参数
|
||||
* 全站sign规则:
|
||||
1. 对关联数组按照键升序排序
|
||||
2. 拼接成字符串 keyvalkey2val2key3val3
|
||||
3. 再2次md5生成32位小写串
|
||||
4. 与请求参数一起发送到服务器
|
||||
*
|
||||
* author:wh
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
function tologin(){
|
||||
if(!request()->isPost()){
|
||||
return Tools::set_fail('错误');
|
||||
}
|
||||
Tools::log_to_write_txt(['登录入参:'=>input()]);
|
||||
$input_data = input();
|
||||
if(empty($input_data)){
|
||||
return Tools::set_fail('请求参数错误');
|
||||
}
|
||||
if(empty($input_data['username'])){
|
||||
return Tools::set_fail('用户名或密码错误');
|
||||
}
|
||||
if(empty($input_data['password'])){
|
||||
return Tools::set_fail('用户名或密码错误.');
|
||||
}
|
||||
// start 这段代码可放在请求合法性里面校验 Tools::signature
|
||||
if(empty($input_data['timestamp'])){
|
||||
return Tools::set_fail('请求错误..');
|
||||
}
|
||||
if(empty($input_data['noncestr'])){
|
||||
return Tools::set_fail('请求错误...');
|
||||
}
|
||||
if(empty($input_data['sign'])){
|
||||
return Tools::set_fail('请求错误。');
|
||||
}
|
||||
|
||||
$sign = $input_data['sign'];//md5后的字符串
|
||||
unset($input_data['sign']);
|
||||
//验签
|
||||
$signstr = Tools::signature($input_data);
|
||||
//Tools::log_to_write_txt([
|
||||
// '签名日志:',
|
||||
// $signstr,
|
||||
// $sign,
|
||||
// 'input'=>input(),
|
||||
//]);
|
||||
if($signstr != $sign){
|
||||
return Tools::set_fail('非法请求');
|
||||
}
|
||||
|
||||
//请求时间超过有效期 N分钟内有效
|
||||
if(time()-5*60 > strtotime($input_data['timestamp'])){
|
||||
return Tools::set_fail('请求失效');
|
||||
}
|
||||
// end 这段代码可放在请求合法性里面校验 Tools::signature
|
||||
|
||||
$username = $input_data['username'];
|
||||
$user = Db::table($this->user_table)->where('username',$username)->find();
|
||||
if(empty($user)){
|
||||
return Tools::set_fail('账号密码错误!');
|
||||
}
|
||||
//校验密码
|
||||
if($user['password'] != $input_data['password']){
|
||||
return Tools::set_fail('账号密码错误!!');
|
||||
}
|
||||
|
||||
$expires = time()+12*60*60;
|
||||
|
||||
|
||||
|
||||
//返回票据
|
||||
$ticketstr = md5($user['username'].$user['expires']);
|
||||
//保存ticket
|
||||
$user[$ticketstr] = $expires;//N秒后过期
|
||||
//修改有效期
|
||||
Db::table($this->user_table)
|
||||
->data([
|
||||
'ticket'=>$ticketstr,
|
||||
'expires'=>7*86400+time(),//7天
|
||||
])
|
||||
->where('username',$username)
|
||||
->update();
|
||||
session('api_user',$user);//备用(跨环境情况下session不生效)
|
||||
|
||||
return Tools::set_ok('登录成功',['ticket'=>$ticketstr]);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:验证登录,根据提交的ticket来校验是否登录,适用于跨环境登录
|
||||
*
|
||||
* author:wh
|
||||
* @return bool
|
||||
*/
|
||||
function isLogin(){
|
||||
|
||||
$ticket = input('ticket');
|
||||
if(empty($ticket)){
|
||||
Tools::log_to_write_txt(['title'=>'业务ticket字段不存在','input'=>input()]);
|
||||
return false;
|
||||
}
|
||||
$user = Db::table(TabConf::$fa_users)
|
||||
->where('ticket',$ticket)
|
||||
->find();
|
||||
if(empty($user)){
|
||||
Tools::log_to_write_txt(['title'=>'用户未登录']);
|
||||
return false;
|
||||
}
|
||||
//无效票据
|
||||
//if(empty($user[$ticket])){
|
||||
// Tools::log_to_write_txt(['title'=>'未获取到用户ticket',$ticket=>$user]);
|
||||
//
|
||||
// return false;
|
||||
//}
|
||||
//已过期
|
||||
if(time() > $user['expires']){
|
||||
Tools::log_to_write_txt(['title'=>'ticket已过期',$ticket=>$user]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* desc:用户注册
|
||||
*
|
||||
* 此模块通用性不高,按需使用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function reg($input_data){
|
||||
try {
|
||||
if(empty($input_data['username'])){
|
||||
return Tools::set_fail('用户名错误');
|
||||
}
|
||||
if(empty($input_data['password'])){
|
||||
return Tools::set_fail('密码错误.');
|
||||
}
|
||||
if(empty($input_data['password2'])){
|
||||
return Tools::set_fail('密码错误!');
|
||||
}
|
||||
if($input_data['password'] != $input_data['password2']){
|
||||
return Tools::set_fail('密码不一致!');
|
||||
}
|
||||
$insert_data = [
|
||||
'username'=>$input_data['username'],
|
||||
'password'=>$input_data['password'],
|
||||
];
|
||||
if(!empty($input_data['phone'])){
|
||||
$insert_data['phone'] = $input_data['phone'];
|
||||
}
|
||||
Db::table($this->user_table)
|
||||
->data($insert_data)
|
||||
->insert();
|
||||
return Tools::set_ok();
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/Apk.php
vendored
Normal file
79
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/Apk.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/*
|
||||
* description: apk应用安装包信息读取
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {17:16}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\apk;
|
||||
|
||||
|
||||
class Apk
|
||||
{
|
||||
|
||||
/**
|
||||
* 前提:安装PHP ZIP扩展
|
||||
* 扩展下载:https://windows.php.net/downloads/pecl/releases/zip/
|
||||
* desc:读取APK
|
||||
* author:wh
|
||||
* @param string $path 文件地址
|
||||
* @param bool $isRemote 是否远程文件
|
||||
* @param string $proxy 代理
|
||||
* @return array
|
||||
*/
|
||||
function read(string $path, $filename, bool $isRemote=false, $proxy=''){
|
||||
/*解析安卓apk包中的压缩XML文件,还原和读取XML内容
|
||||
|
||||
依赖功能:需要PHP的ZIP包函数支持。*/
|
||||
|
||||
$appObj = new ApkParser();
|
||||
|
||||
$targetFile = $path;//a.apk; apk所在的路径地址
|
||||
// 如果是远程文件,先下载到本地
|
||||
if ($isRemote) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $path);
|
||||
if ($proxy != '') {
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxy);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 50);
|
||||
$fileContent = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// 写入临时文件
|
||||
$sys_tmp_path = tempnam(sys_get_temp_dir(), 'DL');
|
||||
$fp = @fopen($sys_tmp_path, 'w+');
|
||||
fwrite($fp, $fileContent);
|
||||
|
||||
$tmp_path = config('app.ROOT_PATH_PRO').'runtime/temp_file';
|
||||
if(!file_exists($tmp_path)){
|
||||
mkdir($tmp_path, 0777, true);
|
||||
}
|
||||
$targetFile = $tmp_path. '/' .time().$filename;
|
||||
$res = move_uploaded_file($sys_tmp_path, $targetFile);
|
||||
dump($res);die;
|
||||
}
|
||||
$result = [
|
||||
'app_name'=>'',// 应用名称
|
||||
'package'=>'',// 应用包名
|
||||
'version_name'=>'',// 版本名称
|
||||
'version_code'=>'',// 版本代码
|
||||
];
|
||||
|
||||
dump($targetFile);die;
|
||||
if(!is_file($targetFile)){
|
||||
return $result;
|
||||
}
|
||||
$appObj->open($targetFile);//$res
|
||||
|
||||
$result = [
|
||||
'app_name'=>$appObj->getAppName(),// 应用名称
|
||||
'package'=>$appObj->getPackage(),// 应用包名
|
||||
'version_name'=>$appObj->getVersionName(),// 版本名称
|
||||
'version_code'=>$appObj->getVersionCode(),// 版本代码
|
||||
];
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
421
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/ApkParser.php
vendored
Normal file
421
digital_doctor/vendor/wanghua/general-utility-tools-php/src/apk/ApkParser.php
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {17:12}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\apk;
|
||||
|
||||
|
||||
use Exception;
|
||||
|
||||
class ApkParser{
|
||||
//----------------------
|
||||
// 公共函数,供外部调用
|
||||
//----------------------
|
||||
public function open($apk_file, $xml_file='AndroidManifest.xml'){
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($apk_file) === TRUE) {
|
||||
$xml = $zip->getFromName($xml_file);
|
||||
$zip->close();
|
||||
if ($xml){
|
||||
try {
|
||||
return $this->parseString($xml);
|
||||
}catch (Exception $e){
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function parseString($xml){
|
||||
$this->xml = $xml;
|
||||
$this->length = strlen($xml);
|
||||
|
||||
$this->root = $this->parseBlock(self::AXML_FILE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getXML($node=NULL, $lv=-1){
|
||||
if ($lv == -1) $node = $this->root;
|
||||
if (!$node) return '';
|
||||
|
||||
if ($node['type'] == self::END_TAG) $lv--;
|
||||
$xml = @($node['line'] == 0 || $node['line'] == $this->line) ? '' : "\n".str_repeat(' ', $lv);
|
||||
$xml .= $node['tag'];
|
||||
$this->line = @$node['line'];
|
||||
foreach ($node['child'] as $c){
|
||||
$xml .= $this->getXML($c, $lv+1);
|
||||
}
|
||||
return $xml;
|
||||
}
|
||||
|
||||
public function getPackage(){
|
||||
return $this->getAttribute('manifest', 'package');
|
||||
}
|
||||
|
||||
public function getVersionName(){
|
||||
return $this->getAttribute('manifest', 'android:versionName');
|
||||
}
|
||||
|
||||
public function getVersionCode(){
|
||||
return $this->getAttribute('manifest', 'android:versionCode');
|
||||
}
|
||||
|
||||
public function getAppName(){
|
||||
return $this->getAttribute('manifest/application', 'android:name');
|
||||
}
|
||||
|
||||
public function getMainActivity(){
|
||||
for ($id=0; true; $id++){
|
||||
$act = $this->getAttribute("manifest/application/activity[{$id}]/intent-filter/action", 'android:name');
|
||||
if (!$act) break;
|
||||
if ($act == 'android.intent.action.MAIN') return $this->getActivity($id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function getActivity($idx=0){
|
||||
$idx = intval($idx);
|
||||
return $this->getAttribute("manifest/application/activity[{$idx}]", 'android:name');
|
||||
}
|
||||
|
||||
public function getAttribute($path, $name){
|
||||
$r = $this->getElement($path);
|
||||
if (is_null($r)) return NULL;
|
||||
|
||||
if (isset($r['attrs'])){
|
||||
foreach ($r['attrs'] as $a){
|
||||
if ($a['ns_name'] == $name) return $this->getAttributeValue($a);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//----------------------
|
||||
// 类型常量定义
|
||||
//----------------------
|
||||
const AXML_FILE = 0x00080003;
|
||||
const STRING_BLOCK = 0x001C0001;
|
||||
const RESOURCEIDS = 0x00080180;
|
||||
const START_NAMESPACE = 0x00100100;
|
||||
const END_NAMESPACE = 0x00100101;
|
||||
const START_TAG = 0x00100102;
|
||||
const END_TAG = 0x00100103;
|
||||
const TEXT = 0x00100104;
|
||||
|
||||
const TYPE_NULL =0;
|
||||
const TYPE_REFERENCE =1;
|
||||
const TYPE_ATTRIBUTE =2;
|
||||
const TYPE_STRING =3;
|
||||
const TYPE_FLOAT =4;
|
||||
const TYPE_DIMENSION =5;
|
||||
const TYPE_FRACTION =6;
|
||||
const TYPE_INT_DEC =16;
|
||||
const TYPE_INT_HEX =17;
|
||||
const TYPE_INT_BOOLEAN =18;
|
||||
const TYPE_INT_COLOR_ARGB8 =28;
|
||||
const TYPE_INT_COLOR_RGB8 =29;
|
||||
const TYPE_INT_COLOR_ARGB4 =30;
|
||||
const TYPE_INT_COLOR_RGB4 =31;
|
||||
|
||||
const UNIT_MASK = 15;
|
||||
private static $RADIX_MULTS = array(0.00390625, 3.051758E-005, 1.192093E-007, 4.656613E-010);
|
||||
private static $DIMENSION_UNITS = array("px","dip","sp","pt","in","mm","","");
|
||||
private static $FRACTION_UNITS = array("%","%p","","","","","","");
|
||||
|
||||
private $xml='';
|
||||
private $length = 0;
|
||||
private $stringCount = 0;
|
||||
private $styleCount = 0;
|
||||
private $stringTab = array();
|
||||
private $styleTab = array();
|
||||
private $resourceIDs = array();
|
||||
private $ns = array();
|
||||
private $cur_ns = NULL;
|
||||
private $root = NULL;
|
||||
private $line = 0;
|
||||
|
||||
//----------------------
|
||||
// 内部私有函数
|
||||
//----------------------
|
||||
private function getElement($path){
|
||||
if (!$this->root) return NULL;
|
||||
$ps = explode('/', $path);
|
||||
$r = $this->root;
|
||||
foreach ($ps as $v){
|
||||
if (preg_match('/([^\[]+)\[([0-9]+)\]$/', $v, $ms)){
|
||||
$v = $ms[1];
|
||||
$off = $ms[2];
|
||||
}else {
|
||||
$off = 0;
|
||||
}
|
||||
foreach ($r['child'] as $c){
|
||||
if ($c['type'] == self::START_TAG && $c['ns_name'] == $v){
|
||||
if ($off == 0){
|
||||
$r = $c; continue 2;
|
||||
}else {
|
||||
$off--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 没有找到节点
|
||||
return NULL;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
private function parseBlock($need = 0){
|
||||
$o = 0;
|
||||
$type = $this->get32($o);
|
||||
if ($need && $type != $need) throw new Exception('Block Type Error', 1);
|
||||
$size = $this->get32($o);
|
||||
if ($size < 8 || $size > $this->length) throw new Exception('Block Size Error', 2);
|
||||
$left = $this->length - $size;
|
||||
|
||||
$props = false;
|
||||
switch ($type){
|
||||
case self::AXML_FILE:
|
||||
$props = array(
|
||||
'line' => 0,
|
||||
'tag' => '<?xml version="1.0" encoding="utf-8"?>'
|
||||
);
|
||||
break;
|
||||
case self::STRING_BLOCK:
|
||||
$this->stringCount = $this->get32($o);
|
||||
$this->styleCount = $this->get32($o);
|
||||
$o += 4;
|
||||
$strOffset = $this->get32($o);
|
||||
$styOffset = $this->get32($o);
|
||||
$strListOffset = $this->get32array($o, $this->stringCount);
|
||||
$styListOffset = $this->get32array($o, $this->styleCount);
|
||||
$this->stringTab = $this->stringCount > 0 ? $this->getStringTab($strOffset, $strListOffset) : array();
|
||||
$this->styleTab = $this->styleCount > 0 ? $this->getStringTab($styOffset, $styListOffset) : array();
|
||||
$o = $size;
|
||||
break;
|
||||
case self::RESOURCEIDS:
|
||||
$count = $size / 4 - 2;
|
||||
$this->resourceIDs = $this->get32array($o, $count);
|
||||
break;
|
||||
case self::START_NAMESPACE:
|
||||
$o += 8;
|
||||
$prefix = $this->get32($o);
|
||||
$uri = $this->get32($o);
|
||||
|
||||
if (empty($this->cur_ns)){
|
||||
$this->cur_ns = array();
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
}
|
||||
$this->cur_ns[$uri] = $prefix;
|
||||
break;
|
||||
case self::END_NAMESPACE:
|
||||
$o += 8;
|
||||
$prefix = $this->get32($o);
|
||||
$uri = $this->get32($o);
|
||||
|
||||
if (empty($this->cur_ns)) break;
|
||||
unset($this->cur_ns[$uri]);
|
||||
break;
|
||||
case self::START_TAG:
|
||||
$line = $this->get32($o);
|
||||
|
||||
$o += 4;
|
||||
$attrs = array();
|
||||
$props = array(
|
||||
'line' => $line,
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o)),
|
||||
'flag' => $this->get32($o),
|
||||
'count' => $this->get16($o),
|
||||
'id' => $this->get16($o)-1,
|
||||
'class' => $this->get16($o)-1,
|
||||
'style' => $this->get16($o)-1,
|
||||
'attrs' => &$attrs
|
||||
);
|
||||
$props['ns_name'] = $props['ns'].$props['name'];
|
||||
for ($i=0; $i < $props['count']; $i++){
|
||||
$a = array(
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o)),
|
||||
'val_str' => $this->get32($o),
|
||||
'val_type' => $this->get32($o),
|
||||
'val_data' => $this->get32($o)
|
||||
);
|
||||
$a['ns_name'] = $a['ns'].$a['name'];
|
||||
$a['val_type'] >>= 24;
|
||||
$attrs[] = $a;
|
||||
}
|
||||
// 处理TAG字符串
|
||||
$tag = "<{$props['ns_name']}";
|
||||
foreach ($this->cur_ns as $uri => $prefix){
|
||||
$uri = $this->getString($uri);
|
||||
$prefix = $this->getString($prefix);
|
||||
$tag .= " xmlns:{$prefix}=\"{$uri}\"";
|
||||
}
|
||||
foreach ($props['attrs'] as $a){
|
||||
$tag .= " {$a['ns_name']}=\"".
|
||||
$this->getAttributeValue($a).
|
||||
'"';
|
||||
}
|
||||
$tag .= '>';
|
||||
$props['tag'] = $tag;
|
||||
|
||||
unset($this->cur_ns);
|
||||
$this->cur_ns = array();
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
$left = -1;
|
||||
break;
|
||||
case self::END_TAG:
|
||||
$line = $this->get32($o);
|
||||
$o += 4;
|
||||
$props = array(
|
||||
'line' => $line,
|
||||
'ns' => $this->getNameSpace($this->get32($o)),
|
||||
'name' => $this->getString($this->get32($o))
|
||||
);
|
||||
$props['ns_name'] = $props['ns'].$props['name'];
|
||||
$props['tag'] = "</{$props['ns_name']}>";
|
||||
if (count($this->ns) > 1){
|
||||
array_pop($this->ns);
|
||||
unset($this->cur_ns);
|
||||
$this->cur_ns = array_pop($this->ns);
|
||||
$this->ns[] = &$this->cur_ns;
|
||||
}
|
||||
break;
|
||||
case self::TEXT:
|
||||
$o += 8;
|
||||
$props = array(
|
||||
'tag' => $this->getString($this->get32($o))
|
||||
);
|
||||
$o += 8;
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Block Type Error', 3);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->skip($o);
|
||||
$child = array();
|
||||
while ($this->length > $left){
|
||||
$c = $this->parseBlock();
|
||||
if ($props && $c) $child[] = $c;
|
||||
if ($left == -1 && $c['type'] == self::END_TAG){
|
||||
$left = $this->length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this->length != $left) throw new Exception('Block Overflow Error', 4);
|
||||
if ($props){
|
||||
$props['type'] = $type;
|
||||
$props['size'] = $size;
|
||||
$props['child'] = $child;
|
||||
return $props;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getAttributeValue($a){
|
||||
$type = &$a['val_type'];
|
||||
$data = &$a['val_data'];
|
||||
switch ($type){
|
||||
case self::TYPE_STRING:
|
||||
return $this->getString($a['val_str']);
|
||||
case self::TYPE_ATTRIBUTE:
|
||||
return sprintf('?%s%08X', self::_getPackage($data), $data);
|
||||
case self::TYPE_REFERENCE:
|
||||
return sprintf('@%s%08X', self::_getPackage($data), $data);
|
||||
case self::TYPE_INT_HEX:
|
||||
return sprintf('0x%08X', $data);
|
||||
case self::TYPE_INT_BOOLEAN:
|
||||
return ($data != 0 ? 'true' : 'false');
|
||||
case self::TYPE_INT_COLOR_ARGB8:
|
||||
case self::TYPE_INT_COLOR_RGB8:
|
||||
case self::TYPE_INT_COLOR_ARGB4:
|
||||
case self::TYPE_INT_COLOR_RGB4:
|
||||
return sprintf('#%08X', $data);
|
||||
case self::TYPE_DIMENSION:
|
||||
return $this->_complexToFloat($data).self::$DIMENSION_UNITS[$data & self::UNIT_MASK];
|
||||
case self::TYPE_FRACTION:
|
||||
return $this->_complexToFloat($data).self::$FRACTION_UNITS[$data & self::UNIT_MASK];
|
||||
case self::TYPE_FLOAT:
|
||||
return $this->_int2float($data);
|
||||
}
|
||||
if ($type >=self::TYPE_INT_DEC && $type < self::TYPE_INT_COLOR_ARGB8){
|
||||
return (string)$data;
|
||||
}
|
||||
return sprintf('<0x%X, type 0x%02X>', $data, $type);
|
||||
}
|
||||
|
||||
private function _complexToFloat($data){
|
||||
return (float)($data & 0xFFFFFF00) * self::$RADIX_MULTS[($data>>4) & 3];
|
||||
}
|
||||
private function _int2float($v) {
|
||||
$x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
|
||||
$exp = ($v >> 23 & 0xFF) - 127;
|
||||
return $x * pow(2, $exp - 23);
|
||||
}
|
||||
private static function _getPackage($data){
|
||||
return ($data >> 24 == 1) ? 'android:' : '';
|
||||
}
|
||||
|
||||
private function getStringTab($base, $list){
|
||||
$tab = array();
|
||||
foreach ($list as $off){
|
||||
$off += $base;
|
||||
$len = $this->get16($off);
|
||||
$mask = ($len >> 0x8) & 0xFF;
|
||||
$len = $len & 0xFF;
|
||||
if ($len == $mask){
|
||||
if ($off + $len > $this->length) throw new Exception('String Table Overflow', 11);
|
||||
$tab[] = substr($this->xml, $off, $len);
|
||||
}else {
|
||||
if ($off + $len * 2 > $this->length) throw new Exception('String Table Overflow', 11);
|
||||
$str = substr($this->xml, $off, $len * 2);
|
||||
$tab[] = mb_convert_encoding($str, 'UTF-8', 'UCS-2LE');
|
||||
}
|
||||
}
|
||||
return $tab;
|
||||
}
|
||||
private function getString($id){
|
||||
if ($id > -1 && $id < $this->stringCount){
|
||||
return $this->stringTab[$id];
|
||||
}else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
private function getNameSpace($uri){
|
||||
for ($i=count($this->ns); $i > 0; ){
|
||||
$ns = $this->ns[--$i];
|
||||
if (isset($ns[$uri])){
|
||||
$ns = $this->getString($ns[$uri]);
|
||||
if (!empty($ns)) $ns .= ':';
|
||||
return $ns;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
private function get32(&$off){
|
||||
$int = unpack('V', substr($this->xml, $off, 4));
|
||||
$off += 4;
|
||||
return array_shift($int);
|
||||
}
|
||||
private function get32array(&$off, $size){
|
||||
if ($size <= 0) return NULL;
|
||||
$arr = unpack('V*', substr($this->xml, $off, 4 * $size));
|
||||
if (count($arr) != $size) throw new Exception('Array Size Error', 10);
|
||||
$off += 4 * $size;
|
||||
return $arr;
|
||||
}
|
||||
private function get16(&$off){
|
||||
$int = unpack('v', substr($this->xml, $off, 2));
|
||||
$off += 2;
|
||||
return array_shift($int);
|
||||
}
|
||||
private function skip($size){
|
||||
$this->xml = substr($this->xml, $size);
|
||||
$this->length -= $size;
|
||||
}
|
||||
}
|
||||
103
digital_doctor/vendor/wanghua/general-utility-tools-php/src/coin/Coin.php
vendored
Normal file
103
digital_doctor/vendor/wanghua/general-utility-tools-php/src/coin/Coin.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/3/19} {13:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\coin;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
|
||||
class Coin
|
||||
{
|
||||
|
||||
public $apiKey = 'f94a2a9c-28be-47c3aaa-9c29-1e83b309d076';
|
||||
public $url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest';
|
||||
|
||||
|
||||
/**
|
||||
* desc:
|
||||
'limit'=>'1000',
|
||||
'sort'=>'market_cap',
|
||||
'sort_dir'=>'desc',
|
||||
* @param array $params
|
||||
* @return array|bool|int|string
|
||||
*/
|
||||
function getAll(array $params){
|
||||
$params_str = http_build_query($params);
|
||||
$url = $this->url.'?'.$params_str;
|
||||
|
||||
$header = [
|
||||
'X-CMC_PRO_API_KEY:'.$this->apiKey,
|
||||
'accept: application/json',
|
||||
];
|
||||
|
||||
return Curl::curl_get($url,10,$header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:
|
||||
*
|
||||
*https://coinmarketcap.com/api/documentation/v1/#section/Introduction
|
||||
* 'https://pro-api.coinmarketcap.com/v2/cryptocurrency/ohlcv/historical'
|
||||
* author:wh
|
||||
*/
|
||||
function k(){
|
||||
$url = $this->url;
|
||||
$time_start = input('time_start');
|
||||
$time_end = input('time_end');
|
||||
$type = input('type');
|
||||
|
||||
$header = [
|
||||
'X-CMC_PRO_API_KEY:'.$this->apiKey,
|
||||
];
|
||||
|
||||
$arr = explode('=',$type);
|
||||
$params = [
|
||||
$arr[0]=>$arr[1],//币种
|
||||
'time_start'=>$time_start,
|
||||
'time_end'=>$time_end,
|
||||
'count'=>7,
|
||||
];
|
||||
|
||||
$url = $url.'?'.http_build_query($params);
|
||||
|
||||
return Curl::curl_get($url,10,$header);
|
||||
}
|
||||
|
||||
private function curl_request($url, $method = 'GET',$data=null,$header=array(),$call_back=null)
|
||||
{
|
||||
set_time_limit(30);
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
if($header){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
}
|
||||
if($method == 'POST'){
|
||||
if($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
if($call_back){
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, $call_back);
|
||||
}
|
||||
$result = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
return [
|
||||
'status' => 'error',
|
||||
'message' => 'curl 错误信息: ' . curl_error($ch)
|
||||
];
|
||||
}
|
||||
curl_close($ch);
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
390
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/DbCacheUtility.php
vendored
Normal file
390
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/DbCacheUtility.php
vendored
Normal file
@@ -0,0 +1,390 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/12/17} {14:30}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
use wanghua\db\general_utility_tools_php\SqlOperateLog;
|
||||
use think\Container;
|
||||
use think\Db;
|
||||
use think\Paginator;
|
||||
|
||||
/**
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
*
|
||||
* 查询缓存器、监控器
|
||||
* 【使用框架链式操作时,配合此类才能发挥完美效果】
|
||||
* 举例
|
||||
* function getMemberInIds(string $ids){
|
||||
$obj = Db::name($this->table)->whereIn("id",$ids)->where(["is_deleted"=>0]);
|
||||
return DbCacheUtility::getAll($obj);
|
||||
}
|
||||
* Class DbCacheUtility
|
||||
* @package libraries
|
||||
*/
|
||||
class DbCacheUtility
|
||||
{
|
||||
const NoCacheTime = 0;
|
||||
const LowCacheTime = 60 * 1;
|
||||
const NormalCacheTime = 60 * 10;
|
||||
const HighCacheTime = 60 * 60;
|
||||
const LongCacheTime = 60 * 60 * 24;
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object 查询对象
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getOne($object, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->fetchSql(true)->find();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'get_one:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->find();
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'get_one', $is_cache);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object 查询对象
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getAll($object, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->fetchSql(true)->select();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'get_all:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->select();
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'get_all', $is_cache);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $object
|
||||
* @param int $page
|
||||
* @param int $listRows
|
||||
* @param bool $simple
|
||||
* @param array $config
|
||||
* @param int $cacheDuration
|
||||
* @param bool $is_log
|
||||
* @return mixed
|
||||
*/
|
||||
static function paginates($object, $page=1, $listRows = null, $simple = false, $config = [], $cacheDuration = self::NoCacheTime, $is_log = true){
|
||||
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = $object->limit(abs(1*$page-1) * $listRows, $listRows)->fetchSql(true)->select();
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'paginates:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = $object->fetchSql(false)->paginate($listRows, $simple, $config);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'paginates', $is_cache);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryScalar($sql, $bind = [], $field, $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_scalar:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_scalar', $is_cache);
|
||||
}
|
||||
|
||||
return $result ? $result[0][$field] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryOne($sql, $bind = [], $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_one:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_one', $is_cache);
|
||||
}
|
||||
|
||||
return $result ? $result[0] : [];
|
||||
}
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function queryAll($sql, $bind = [], $cacheDuration = self::NoCacheTime, $is_log = true)
|
||||
{
|
||||
$begin_time = Tools::getMillisecond();
|
||||
|
||||
$is_cache = 0;
|
||||
|
||||
$last_sql = self::presetBind($sql, $bind);
|
||||
//echo $last_sql;die;
|
||||
$md5_name = md5($last_sql);
|
||||
|
||||
$key = 'query_all:' . $md5_name;
|
||||
|
||||
if ($cacheDuration == 0) {
|
||||
if(cache($key)){
|
||||
cache($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cache($key))) {
|
||||
$result = Db::query($sql, $bind);
|
||||
if ($cacheDuration != 0) {
|
||||
cache($key, $result, $cacheDuration);
|
||||
}
|
||||
} else {
|
||||
$is_cache = 1;
|
||||
$result = cache($key);
|
||||
}
|
||||
|
||||
$end_time = Tools::getMillisecond();
|
||||
|
||||
if($is_log){
|
||||
SqlOperateLog::add($last_sql, $end_time, $begin_time, $md5_name, 'query_all', $is_cache);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return int
|
||||
* @throws \think\db\exception\BindParamException
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
static function execute($sql, $bind = []){
|
||||
return Db::execute($sql, $bind);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $sql
|
||||
* @param array $bind
|
||||
* @return mixed
|
||||
*/
|
||||
static function presetBind($sql, $bind = []){
|
||||
if($bind){
|
||||
foreach ($bind as $key=>$val){
|
||||
$sql = str_replace(':'.$key, $val, $sql);
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
static function paginate($sql, $bind, $total, $listRows = null, $simple = false, $config = [])
|
||||
{
|
||||
//if (is_int($simple)) {
|
||||
// $total = $simple;
|
||||
// $simple = false;
|
||||
//}
|
||||
|
||||
$paginate = Container::get('config')->pull('paginate');
|
||||
|
||||
if (is_array($listRows)) {
|
||||
$config = array_merge($paginate, $listRows);
|
||||
$listRows = $config['list_rows'];
|
||||
} else {
|
||||
$config = array_merge($paginate, $config);
|
||||
$listRows = $listRows ?: $config['list_rows'];
|
||||
}
|
||||
|
||||
/** @var Paginator $class */
|
||||
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\paginator\\driver\\' . ucwords($config['type']);
|
||||
$page = isset($config['page']) ? (int) $config['page'] : call_user_func([
|
||||
$class,
|
||||
'getCurrentPage',
|
||||
], $config['var_page']);
|
||||
|
||||
$page = $page < 1 ? 1 : $page;
|
||||
|
||||
$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);
|
||||
|
||||
//if (!isset($total) && !$simple) {
|
||||
//
|
||||
//
|
||||
// unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
||||
//
|
||||
// $bind = $this->bind;
|
||||
// $total = $this->count();
|
||||
// $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
|
||||
//} elseif ($simple) {
|
||||
// $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
|
||||
// $total = null;
|
||||
//} else {
|
||||
// $results = $this->page($page, $listRows)->select();
|
||||
//}
|
||||
|
||||
$results = DbCacheUtility::queryAll($sql, $bind);
|
||||
|
||||
return $class::make($results, $listRows, $page, $total, $simple, $config);
|
||||
}
|
||||
}
|
||||
109
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/RedisUtility.php
vendored
Normal file
109
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/RedisUtility.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/5/22} {16:43}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\cache\driver\Redis as RedisDriver;
|
||||
use think\Db;
|
||||
use think\facade\Cache;
|
||||
|
||||
/**
|
||||
* Redis操作工具
|
||||
*
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
*
|
||||
* Class RedisUtility
|
||||
* @package libraries
|
||||
*/
|
||||
class RedisUtility
|
||||
{
|
||||
protected static $redisHandle = null;
|
||||
|
||||
/**
|
||||
* desc:初始化Redis对象
|
||||
* author:wh
|
||||
* @return object|null
|
||||
*/
|
||||
static function redisObject(){
|
||||
if(empty(self::$redisHandle)){
|
||||
//初始化驱动拿到句柄
|
||||
self::$redisHandle = (new RedisDriver(config('cache.redis')))->handler();
|
||||
}
|
||||
return self::$redisHandle;
|
||||
}
|
||||
/**
|
||||
* desc:设置 0 永久有效
|
||||
* author:wh
|
||||
* @param $key_name 键名
|
||||
* @param $value 值 json数据
|
||||
* @return bool
|
||||
*/
|
||||
static function set($key_name, $value){
|
||||
return Cache::store('redis')->set($key_name, json_encode($value, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:重置
|
||||
* author:wh
|
||||
* @param $key_name
|
||||
* @return bool
|
||||
*/
|
||||
static function reset($key_name){
|
||||
return Cache::store('redis')->set($key_name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置过期时间
|
||||
* author:wh
|
||||
* @param $key_name 键名
|
||||
* @param $value 值 json数据
|
||||
* @param int $expire 过期时间 0 永久有效
|
||||
* @return bool
|
||||
*/
|
||||
static function setExpire($key_name, $value, $expire=0){
|
||||
return Cache::store('redis')->set($key_name, json_encode($value), $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:存储hash类型
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @param $field
|
||||
* @param $value
|
||||
*/
|
||||
static function hSet($key, $field, $value){
|
||||
return self::redisObject()->hSet($key, $field, json_encode($value, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除指定的键。
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
static function delete($key){
|
||||
return self::redisObject()->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:从存储在键上的哈希中移除一个值。
|
||||
* 如果哈希表不存在,或者键不存在,则返回 FALSE 。
|
||||
* author:wh
|
||||
* @param $key
|
||||
* @param $hashKey1
|
||||
* @return mixed
|
||||
*/
|
||||
static function hDel($key, $hashKey1){
|
||||
return self::redisObject()->hDel($key, $hashKey1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
55
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/SqlOperateLog.php
vendored
Normal file
55
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/SqlOperateLog.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/10/31} {9:25}
|
||||
*/
|
||||
|
||||
namespace wanghua\db\general_utility_tools_php;
|
||||
|
||||
|
||||
use think\Db;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 环境要求:
|
||||
* ThinkPHP5.1+,PHP7.0+,MySQL8.0+
|
||||
*
|
||||
* 日志操作类,配合DbCacheUtility.php使用。
|
||||
* 使用前先在系统config.php文件中添加配置:
|
||||
* 1、is_sql_slow_log:是否记录sql慢日志,true or false
|
||||
* 2、新建表(log_sql_operate)字段:action,is_cache,duration_time,type,is_cache,sql,md5_name
|
||||
* 3、如果什么错都没有报,但是程序就是没反应,则去runtime目录中找错误。
|
||||
*
|
||||
* Class SqlOperateLog
|
||||
* @package wanghua\general_utility_tools_php
|
||||
*/
|
||||
class SqlOperateLog
|
||||
{
|
||||
|
||||
static function add($sql,$end_time,$begin_time,$md5_name,$type,$is_cache){
|
||||
$data = [
|
||||
'action'=>request()->baseUrl(),
|
||||
'duration_time'=>$end_time - $begin_time,
|
||||
'type'=>$type,
|
||||
'is_cache'=>$is_cache?1:0,
|
||||
'sql'=>$sql,
|
||||
'md5_name'=>$md5_name,
|
||||
];
|
||||
try{
|
||||
if(config('app.is_sql_slow_log') && ($end_time - $begin_time) >= config('app.is_sql_slow_log')){
|
||||
Db::table('log_sql_operate')->insert($data);
|
||||
}
|
||||
}catch (\Exception $e){
|
||||
//DATABASE BOOM
|
||||
//tp6
|
||||
//Log::error('========[数据库异常:DATABASE BOOM]========'.$e->getTraceAsString());
|
||||
//Log::close();
|
||||
//tp5.1
|
||||
Log::write('========[DATABASE ERROR:DATABASE BOOM]========【'.$e->getMessage().'】'.$e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
262
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/Elasticsearch.php
vendored
Normal file
262
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/Elasticsearch.php
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/26} {9:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\es;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Date;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 【es原生操作库】
|
||||
* 【仅支持框架ThinkPHP5+、 PHP7.2+】
|
||||
*
|
||||
* BaseElasticsearch.php类库的替代库
|
||||
*
|
||||
* 使用步骤:
|
||||
* 初始化(设置ip、索引前缀-普通索引请设置为空字符串)
|
||||
* 设置索引范围(例如查询本月,如果索引不是按日期规律设置,请使用普通索引设置方法setIndexNormal,并设置前缀为空字符串)
|
||||
* 设置查询方法(eg: _search)
|
||||
* 设置查询参数(查询条件)
|
||||
* 执行
|
||||
* 返回结果
|
||||
* Class ElasticsearchUtility
|
||||
* @package app\admin\logic
|
||||
*/
|
||||
class Elasticsearch
|
||||
{
|
||||
protected $es_log_file = 'es_log';
|
||||
//最终拼装的请求地址
|
||||
protected $post_url = ''; //eg: $url = 'http://49.4.3.4:9111/qa-item-2021.04/_search';
|
||||
//查询参数
|
||||
protected $query_param = [];
|
||||
//查询方法
|
||||
protected $query_method = '_search';
|
||||
//文档索引
|
||||
protected $index = '';
|
||||
//服务器ip
|
||||
protected $ip = '';
|
||||
//索引前缀(优先设置)
|
||||
protected $index_sign = '';//eg: qa-stat-
|
||||
//设置查询日期格式符号
|
||||
protected $doc_date_sign = '.';
|
||||
//设置是哪个方法调用本es库,用于日志记录
|
||||
protected $exe_func = '';
|
||||
|
||||
|
||||
/**
|
||||
* ElasticsearchUtility constructor.
|
||||
* @param string $ip_port 协议+服务器ip+端口号,必须
|
||||
* @param string $index_sign 当es索引为有规律的日期索引时,可使用前缀并配合日期索引设置方法,体验更佳
|
||||
*/
|
||||
public function __construct(string $ip_port, string $index_sign='')
|
||||
{
|
||||
$this->ip = false===strpos($ip_port,'http')?'http://'.$ip_port:$ip_port;
|
||||
$this->index_sign = $index_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置查询方法,默认_search
|
||||
* author:wh
|
||||
* @param $method_name
|
||||
*/
|
||||
function setQueryMethod($method_name){
|
||||
$this->query_method = $method_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:根据日期索引查询文档
|
||||
* 注:默认一个月
|
||||
*
|
||||
* eg:'qa-stat-2021.01';
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
* author:wh
|
||||
*/
|
||||
function setIndexDefault(){
|
||||
$this->setRequestIndex(date('Y'.$this->doc_date_sign.'m'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置要查询的日期文档索引
|
||||
*
|
||||
* 1、按年检索文档[建议5年左右]
|
||||
*
|
||||
* eg: qa-stat-2018.*,qa-stat-2019.*,qa-stat-2020.*,qa-stat-2021.*
|
||||
*
|
||||
* 注意:当索引过长,es会抛出索引太长异常
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间 eg:2010-01-01 08:05:55
|
||||
* @param string $end_time 结束时间 eg:2021-12-31 12:05:00
|
||||
* @return string
|
||||
*/
|
||||
function setIndexYearDate(string $start_time, string $end_time){
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'*', strtotime($start_time));
|
||||
|
||||
$sign = ',';//分隔符
|
||||
|
||||
$m = date('Y', strtotime($end_time)) - date('Y', strtotime($start_time));
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
|
||||
$index .= $sign.($this->index_sign.(date('Y', strtotime($start_time))+$i).$this->doc_date_sign.'*');
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日期索引
|
||||
*
|
||||
* 检索全部日期索引文档
|
||||
*
|
||||
* 例如es设置的索引为:
|
||||
* qa-stat-2021.01
|
||||
qa-stat-2021.02
|
||||
qa-stat-2021.03
|
||||
qa-stat-2021.04
|
||||
*
|
||||
* 实际查询自动设置为:qa-stat-*
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function setIndexAllDate(){
|
||||
|
||||
$this->setRequestIndex('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置普通索引
|
||||
*
|
||||
* 调用此方法,请在初始化时,设置索引前缀index_sign为""空字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
function setIndexNormal(string $index){
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置跨月份索引
|
||||
*
|
||||
* eg: qa-stat-2021.01,qa-stat-2021.02
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time eg:'2020-11'
|
||||
* @param string $end_time eg:'2021-01'
|
||||
* @return string eg: qa-stat-2020.11,qa-stat-2020.12,qa-stat-2021.01
|
||||
*/
|
||||
function setIndexDate(string $start_time, string $end_time){
|
||||
$date = new Date();
|
||||
|
||||
//计算月份
|
||||
$m = $date->dateCutMonth($start_time, $end_time);
|
||||
////解决跨年且不足1个月时,索引设置错误问题
|
||||
//if($m == 0 && (date('Y', strtotime($end_time)) > date('Y', strtotime($start_time)))){
|
||||
// $m = 1;
|
||||
//}
|
||||
//格式
|
||||
$date->date_format = 'Y-m';
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'m', strtotime($start_time));
|
||||
|
||||
$tmp_time = $start_time;
|
||||
$sign = ',';//分隔符
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
$tmp_time = $date->addTime(1, 'M', strtotime($tmp_time));
|
||||
$index .= $sign.$this->index_sign.(date('Y'.$this->doc_date_sign.'m', strtotime($tmp_time)));
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:设置查询参数
|
||||
* author:wh
|
||||
* @param string $query_param_json
|
||||
*/
|
||||
function setQueryParam(string $query_param_json){
|
||||
$this->query_param = $query_param_json;
|
||||
$this->post_url = $this->ip.'/'.$this->index.'/'.$this->query_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取查询参数,用于调试
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getQueryParam(){
|
||||
return [
|
||||
'ip'=>$this->ip,
|
||||
'index_sign'=>$this->index_sign,
|
||||
'index'=>$this->index,
|
||||
'query_method'=>$this->query_method,
|
||||
'post_url'=>$this->post_url,
|
||||
'query_param'=>$this->query_param,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:执行es查询
|
||||
* author:wh
|
||||
* @return array|bool|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function execute(){
|
||||
if(empty($this->ip)) throw new \Exception('请设置ip');
|
||||
//if(empty($this->index_sign)) throw new \Exception('请设置索引前缀');
|
||||
if(empty($this->index)) throw new \Exception('请设置索引');
|
||||
if(empty($this->query_method)) throw new \Exception('请设置查询方法');
|
||||
if(empty($this->query_param)) throw new \Exception('请设置查询参数');
|
||||
|
||||
|
||||
|
||||
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'request_url'=>$this->post_url,'IN'=>" | IN: ",'query_params'=>$this->query_param, 'input'=>input()], $this->es_log_file);
|
||||
$result = Tools::curl_post($this->post_url, $this->query_param);
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'OUT'=>" | OUT: ", 'result'=>$result], $this->es_log_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置是哪个方法调用本es库,用于日志记录
|
||||
* author:wh
|
||||
* @param string $function
|
||||
*/
|
||||
function setExecuteFunction(string $function){
|
||||
$this->exe_func = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置请求文档索引
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
protected function setRequestIndex(string $index){
|
||||
$this->index = $this->index_sign.$index;
|
||||
}
|
||||
|
||||
}
|
||||
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/README.md
vendored
Normal file
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/es/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/README.MD
vendored
Normal file
6
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/README.MD
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
## 仅适用于tp5+, php7+
|
||||
|
||||
|
||||
## 表管理
|
||||
|
||||
## 字段管理
|
||||
304
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Field.php
vendored
Normal file
304
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Field.php
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:57}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\mysql\lib;
|
||||
|
||||
|
||||
use think\Db;
|
||||
|
||||
class Field
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:创建字段,存在则修改字段
|
||||
* author:wh
|
||||
* @param array $table
|
||||
*/
|
||||
function createfield(array $table){
|
||||
$table_name = $table['tablename'];
|
||||
//新增字段
|
||||
$dec_num = '';
|
||||
|
||||
if(in_array(strtoupper($table['type']), ['TINYINT','SMALLINT','MEDIUMINT','INT','BIGINT','FLOAT','DOUBLE','DECIMAL'])){
|
||||
$table['default'] = '0';//整型默认值 浮点类型自动转为0.00
|
||||
if(in_array(strtoupper($table['type']), ['FLOAT','DOUBLE','DECIMAL'])){
|
||||
$dec_num = ','.$table['decimals_size'];//浮点类型小数位位数
|
||||
}
|
||||
}elseif ($table['type'] == 'enum'){
|
||||
//枚举值不转换
|
||||
}else{
|
||||
$table['default'] = '""';
|
||||
}
|
||||
|
||||
if(in_array(strtolower($table['type']), ['timestamp','datetime','date','time','text','mediumtext','longtext'])){
|
||||
$table['size'] = 0;//重写 默认0
|
||||
$table['default'] = 'null';//重写
|
||||
}
|
||||
//是否可以负数
|
||||
if(in_array(strtolower($table['type']), ['int','tinyint','bigint','smallint', 'double', 'float', 'decimal']) && !empty($post['is_unsigned'])){//不是
|
||||
$is_unsigned = 'unsigned';
|
||||
}else{//是 表单可选值
|
||||
$is_unsigned = '';
|
||||
}
|
||||
|
||||
if (in_array($table['fields_name'], ['create_time', 'update_time'])){
|
||||
if($table['fields_name'] == 'create_time'){
|
||||
$table['default'] = 'CURRENT_TIMESTAMP';
|
||||
}
|
||||
if($table['fields_name'] == 'update_time'){
|
||||
$table['default'] = 'NULL ON UPDATE CURRENT_TIMESTAMP';
|
||||
}
|
||||
}
|
||||
//验证字段是否存在
|
||||
$f = DB::table($table_name)->getTableFields();
|
||||
if(in_array($table['fields_name'], $f)){
|
||||
//枚举类型
|
||||
if ($table['type'] == 'enum'){
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}';";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} MODIFY COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}';";
|
||||
}
|
||||
}else{
|
||||
|
||||
if(in_array($table['type'], ['text','longtext'])){
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}elseif ($table['type'] == 'enum'){//枚举类型
|
||||
$enum_str = '';
|
||||
$enum_default = '';
|
||||
//组合枚举值
|
||||
if($table['default']){
|
||||
$enum_str.='ENUM('.$table['default'].')';
|
||||
$enum_default = explode(',', $table['default'])[0];
|
||||
}
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD {$table['fields_name']} {$enum_str} NOT NULL DEFAULT {$enum_default} COMMENT '{$table['title']}' AFTER id;";
|
||||
}else{
|
||||
$sql2 = "ALTER TABLE {$table_name} ADD COLUMN {$table['fields_name']} {$table['type']}(".$table['size'].$dec_num.") {$is_unsigned} DEFAULT {$table['default']} COMMENT '{$table['title']}' AFTER id;";
|
||||
}
|
||||
}
|
||||
|
||||
DB::execute($sql2);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:删除字段
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $fieldname
|
||||
*/
|
||||
function dropFieldName($tablename, $fieldname){
|
||||
$sql = "ALTER TABLE {$tablename} DROP COLUMN {$fieldname};";
|
||||
DB::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename,$field, $comment){
|
||||
|
||||
$sql = "ALTER TABLE {$tablename} MODIFY COLUMN {$field} INT COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中所有字段的数据类型(含其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldsDataType(string $dbname,string $tablename){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'";
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型(含这个字段的其它属性)
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataType(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的数据类型
|
||||
*
|
||||
* 不含这个字段的其它属性
|
||||
*
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldDataTypeVal(string $dbname,string $tablename,string $fieldname){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0]['F_DATATYPE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表中某个字段的属性
|
||||
*
|
||||
* 查询结果字段名说明
|
||||
*
|
||||
* F_FIELD:字段名称
|
||||
* F_DATATYPE:数据类型
|
||||
* F_DATALENGTH:数据长度(int类型默认为null,业务处理时默认为10即可)
|
||||
* F_PRECISION:精度
|
||||
* F_DECIMAL_DIGITS:小数位数
|
||||
* F_ALLOWNULL:是否允许为null值(1是,0否)
|
||||
* F_FIELDNAME:字段名称
|
||||
* F_PRIMARYKEY:是否主键(1是,0否)
|
||||
* F_DEFAULTS:字段默认值
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @param string $fieldname
|
||||
* @return mixed
|
||||
*/
|
||||
function getFieldAttrVal(string $dbname,string $tablename,string $fieldname,string $attr){
|
||||
$sql = "SELECT
|
||||
COLUMN_NAME F_FIELD,
|
||||
data_type F_DATATYPE,
|
||||
CHARACTER_MAXIMUM_LENGTH F_DATALENGTH,
|
||||
NUMERIC_PRECISION F_PRECISION,
|
||||
NUMERIC_SCALE F_DECIMAL_DIGITS,
|
||||
IF
|
||||
( IS_NULLABLE = 'YES', '1', '0' ) F_ALLOWNULL,
|
||||
COLUMN_COMMENT F_FIELDNAME,
|
||||
IF
|
||||
( COLUMN_KEY = 'PRI', '1', '0' ) F_PRIMARYKEY,
|
||||
column_default F_DEFAULTS,
|
||||
CONCAT( upper( COLUMN_NAME ), '(', COLUMN_COMMENT, ')' ) AS 'F_DESCRIPTION'
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_NAME = '$tablename'
|
||||
AND TABLE_SCHEMA = '$dbname'
|
||||
AND COLUMN_NAME='$fieldname'
|
||||
";
|
||||
$ar = Db::query($sql);
|
||||
return $ar[0][$attr];
|
||||
}
|
||||
}
|
||||
162
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Table.php
vendored
Normal file
162
digital_doctor/vendor/wanghua/general-utility-tools-php/src/db/mysql/lib/Table.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/24} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\db\mysql\lib;
|
||||
use think\Db;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class Table
|
||||
{
|
||||
/**
|
||||
* desc:创建表,初始化默认字段
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
function createTable($data){
|
||||
$tablename = $data['tablename'];
|
||||
$title = $data['title'];
|
||||
//创建表
|
||||
$sql = "CREATE TABLE IF NOT EXISTS {$tablename}(
|
||||
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
update_time timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY key(id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='{$title}' ;";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:改注释
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $comment
|
||||
* @return bool
|
||||
*/
|
||||
function updateComment($tablename, $comment){
|
||||
$sql = "ALTER TABLE {$tablename} COMMENT '{$comment}';";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:改表名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @param $new_table_name
|
||||
* @return bool
|
||||
*/
|
||||
function updateTableName($tablename, $new_table_name){
|
||||
$sql = "ALTER TABLE {$tablename} RENAME TO {$new_table_name}";
|
||||
Db::execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:查询当前数据库所有的表名
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTables(){
|
||||
return array_column(Db::query('SHOW TABLES;'), 'Tables_in_'.config('database.database'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取数据表字所有段名
|
||||
* author:wh
|
||||
* @param $tablename
|
||||
* @return array
|
||||
*/
|
||||
function getTableFields($tablename){
|
||||
$dbname = config('database.database');
|
||||
$sql = "SELECT COLUMN_NAME column_name,COLUMN_COMMENT column_comment,DATA_TYPE data_type
|
||||
FROM information_schema.columns WHERE TABLE_NAME='{$tablename}' AND table_schema='{$dbname}'";
|
||||
return array_column(Db::query($sql), 'column_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表的属性
|
||||
* Name:
|
||||
表名称
|
||||
Engine:
|
||||
表的存储引擎
|
||||
Version:
|
||||
版本
|
||||
Row_format:
|
||||
行格式。对于MyISAM引擎,这可能是Dynamic,Fixed或Compressed。动态行的行长度可变,例如Varchar或Blob类型字段。固定行是指行长度不变,例如Char和Integer类型字段
|
||||
Rows:
|
||||
表中的行数。对于MyISAM和其他存储引擎,这个值是精确的,对于innoDB存储引擎,这个值通常是估算的
|
||||
Avg_row_length:
|
||||
平均每行包括的字节数
|
||||
Data_length:
|
||||
整个表的数据量(以字节为单位)
|
||||
Max_data_length:
|
||||
表可以容纳的最大数据量,该值和存储引擎相关
|
||||
Index_length:
|
||||
索引占用磁盘的空间大小(以字节为单位)
|
||||
Data_free:
|
||||
对于MyISAM引擎,表示已经分配,但目前没有使用的空间。这部分空间包含之前被删除的行,以及后续可以被insert利用到的空间
|
||||
Auto_increment:
|
||||
下一个Auto_increment的值
|
||||
Create_time:
|
||||
表的创建时间
|
||||
Update_time:
|
||||
表的最近更新时间
|
||||
Check_time:
|
||||
使用 check table 或myisamchk工具最后一次检查表的时间
|
||||
Collation:
|
||||
表的默认字符集和字符排序规则
|
||||
Checksum:
|
||||
如果启用,保存的是整个表的实时校验和
|
||||
Create_options:
|
||||
创建表时指定的其他选项
|
||||
Comment:
|
||||
包含了其他额外信息,对于MyISAM引擎,保存的是表在创建时带的注释。如果表使用的是innodb引擎 ,保存的是InnoDB表空间的剩余空间。如果是一个视图,注释里面包含了VIEW字样。
|
||||
*
|
||||
* @param $tablename 表名(无表名则查询所有表)
|
||||
*
|
||||
* author:wh
|
||||
* @return mixed
|
||||
*/
|
||||
function getTableInfo(string $tablename=''){
|
||||
if($tablename){
|
||||
$sql = "SHOW TABLE STATUS WHERE Name = 'fa_agent';";
|
||||
return Db::query($sql);
|
||||
}
|
||||
$sql = 'show table status;';
|
||||
return Db::query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:检查某个表是否存在
|
||||
*
|
||||
* author:wh
|
||||
* @param string $dbname
|
||||
* @param string $tablename
|
||||
* @return bool
|
||||
*/
|
||||
function isExistTable(string $dbname,string $tablename){
|
||||
$sql = "SELECT TABLE_SCHEMA,TABLE_NAME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA ='$dbname'
|
||||
AND TABLE_NAME = '$tablename';";
|
||||
return empty(Db::query($sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取表注释
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getTableComment($table){
|
||||
$prefix = config('database.prefix');
|
||||
$table = $prefix.$table;
|
||||
$sql = 'show table status;';
|
||||
$arr = Db::query($sql);
|
||||
$tmp = Tools::key_val_arr($arr,'Name','Comment');
|
||||
return empty($tmp[$table])?'':$tmp[$table];
|
||||
}
|
||||
}
|
||||
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/BaseDouYin.php
vendored
Normal file
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/BaseDouYin.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/4/5} {10:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\douyin;
|
||||
|
||||
|
||||
class BaseDouYin
|
||||
{
|
||||
|
||||
}
|
||||
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/DouYinMiniGame.php
vendored
Normal file
193
digital_doctor/vendor/wanghua/general-utility-tools-php/src/douyin/DouYinMiniGame.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/4/4} {12:36}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\douyin;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\http\Curl;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class DouYinMiniGame extends BaseDouYin
|
||||
{
|
||||
public $appid = 'tt3c974a2aa3a6ee7c02';
|
||||
public $secret = '5c2414e47a18b9655a164b14ef31ac7cb58179ca';
|
||||
|
||||
|
||||
/**
|
||||
* desc:每2小时更新一次
|
||||
*
|
||||
* https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/server/interface-request-credential/get-access-token
|
||||
*
|
||||
* {"err_no":0,"err_tips":"success","data":{"access_token":"0801121846384c316e52536e5a76396769565145696f597742673d3d","expires_in":7200,"expiresAt":1712208063,"expires_at":1712208063}}
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function getAccessToken(){
|
||||
$url = "https://minigame.zijieapi.com/mgplatform/api/apps/v2/token";
|
||||
$method = 'POST';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
|
||||
$params = [
|
||||
|
||||
'appid'=>$this->appid,
|
||||
'secret'=>$this->secret,
|
||||
'grant_type'=>'client_credential',
|
||||
];
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
$res = Curl::curl_request($url,$method,json_encode($params),$header);
|
||||
|
||||
$json_arr = json_decode($res, true);
|
||||
if($json_arr['err_no']){
|
||||
return Tools::set_res($json_arr['err_no'],$json_arr['err_tips']);
|
||||
}
|
||||
//保存
|
||||
session('ses_dou_yin_access_token',$json_arr['data']);
|
||||
return Tools::set_ok('ok',$json_arr['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:实时获取token
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function realTimeGetAccessToken(){
|
||||
$json_arr = session('ses_dou_yin_access_token');
|
||||
if(empty($json_arr)){
|
||||
return $this->getAccessToken();
|
||||
}
|
||||
if(time() >= $json_arr['expiresAt']){
|
||||
//过期
|
||||
return $this->getAccessToken();
|
||||
}
|
||||
return Tools::set_ok('ok',$json_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:前端tt.login触发调用
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function jscode2session($code='',$anonymous_code=''){
|
||||
$url = 'https://minigame.zijieapi.com/mgplatform/api/apps/jscode2session';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
$method = 'GET';
|
||||
|
||||
if(empty($code) && empty($anonymous_code)){
|
||||
return Tools::set_fail('tt.login 接口返回的匿名登录凭证(code 和 anonymous_code 至少要有一个)');
|
||||
}
|
||||
$params = [
|
||||
'appid'=>$this->appid,
|
||||
'secret'=>$this->secret,
|
||||
];
|
||||
if($code){
|
||||
$params['code'] = $code;
|
||||
}
|
||||
if($anonymous_code){
|
||||
$params['anonymous_code'] = $anonymous_code;
|
||||
}
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
$url .= '?'.http_build_query($params);
|
||||
//dump($url);
|
||||
Tools::log_to_write_txt(['input'=>$url]);
|
||||
$res = Curl::curl_request($url,$method,[],$header);
|
||||
Tools::log_to_write_txt(['output'=>$res]);
|
||||
//dump($res);
|
||||
$json_arr = json_decode($res, true);
|
||||
//dump($json_arr);die;
|
||||
if($json_arr['error']){
|
||||
return Tools::set_res($json_arr['errcode'],$json_arr['errmsg']);
|
||||
}
|
||||
//保存
|
||||
session('ses_dou_yin_js_code_2_session',$json_arr);
|
||||
return Tools::set_ok('ok',$json_arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:创建二维码
|
||||
* 接口说明
|
||||
* 获取小程序/小游戏的二维码。该二维码可通过任意 app 扫码打开,
|
||||
* 能跳转到开发者指定的对应字节系 app 内拉起小程序/小游戏,并传入开发者指定的参数。
|
||||
* 通过该接口生成的二维码,永久有效,暂无数量限制。
|
||||
*
|
||||
* ⚠ Tip:在使用该功能之前请记得先配置您的默认分享文案和图片,配置方式可参考论坛。
|
||||
* ⚠ Tip:小程序的 path 要 encode 一次,如 pages%3fparam%3dtrue,小游戏的 path 为 JSON 字符串,
|
||||
* 如{"param":true},否则会导致取不到。
|
||||
*
|
||||
* 参数:
|
||||
* code和anonymous_code二选一 必须
|
||||
* appname 可选,目标打开应用名称 默认douyin
|
||||
* background 可选,背景色,rgb格式,英文逗号隔开,默认透明色
|
||||
* path 可选,小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
|
||||
* width 宽度 可选,二维码宽度,单位 px,最小 280px,最大 1280px,默认为 430px
|
||||
* line_color 可选,二维码线条颜色,默认为黑色,rgb格式,英文逗号隔开,默认黑色
|
||||
* set_icon 可选,是否展示小程序/小游戏 icon,默认不展示,传yes展示,no不展示,默认no
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function createQRCode($path='',$appname='',$width='',$background='',$line_color='',$set_icon='no'){
|
||||
try {
|
||||
$url = 'https://minigame.zijieapi.com/mgplatform/api/apps/qrcode';
|
||||
//$Scope = 'open.ttgame.mgplatform';
|
||||
$method = 'POST';
|
||||
|
||||
$json_arr = $this->realTimeGetAccessToken();
|
||||
if(empty($json_arr)){
|
||||
return Tools::set_fail('请重新授权');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'access_token'=>$json_arr['data']['access_token'],
|
||||
];
|
||||
if($appname){
|
||||
$params['appname'] = $appname;
|
||||
}
|
||||
if($width){
|
||||
$params['width'] = $width;
|
||||
}
|
||||
//if($path){
|
||||
//小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
|
||||
$params['path'] = $path;
|
||||
//}
|
||||
//英文逗号隔开,r,g,b格式
|
||||
if($background){
|
||||
$background_rgb = explode(',',$background);
|
||||
$params['r'] = $background_rgb[0];
|
||||
$params['g'] = $background_rgb[1];
|
||||
$params['b'] = $background_rgb[2];
|
||||
}
|
||||
if($line_color){
|
||||
$line_color_rgb = explode(',',$line_color);
|
||||
$params['r'] = $line_color_rgb[0];
|
||||
$params['g'] = $line_color_rgb[1];
|
||||
$params['b'] = $line_color_rgb[2];
|
||||
}
|
||||
$params['set_icon'] = $set_icon=='yes';
|
||||
|
||||
$header = [
|
||||
'Accept: application/json',
|
||||
'content-type: application/json'
|
||||
];
|
||||
|
||||
Tools::log_to_write_txt(['input'=>input(),'$params'=>$params]);
|
||||
$res = Curl::curl_request($url,$method,json_encode($params),$header);
|
||||
Tools::log_to_write_txt(['output'=>$res]);
|
||||
|
||||
//流
|
||||
return $res;
|
||||
}catch (\Exception $e){
|
||||
Tools::error_txt_log($e);
|
||||
return Tools::set_fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
88
digital_doctor/vendor/wanghua/general-utility-tools-php/src/encrypt/TripleDES.php
vendored
Normal file
88
digital_doctor/vendor/wanghua/general-utility-tools-php/src/encrypt/TripleDES.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/02/10} {15:51}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\encrypt;
|
||||
|
||||
|
||||
/**
|
||||
* 3DES,三重数据加密算法
|
||||
*
|
||||
* Class TripleDES
|
||||
* @package wanghua\general_utility_tools_php\encrypt
|
||||
*/
|
||||
class TripleDES
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* desc:加密
|
||||
*
|
||||
* author:wh
|
||||
* @param string $value
|
||||
* @param $key
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt(string $value, $key)
|
||||
{
|
||||
$value = self::PaddingPKCS7($value);
|
||||
//AES-128-ECB|不能用 AES-256-CBC|16 AES-128-CBC|16 BF-CBC|8 aes-128-gcm|需要加$tag DES-EDE3-CBC|8
|
||||
$cipher = "DES-EDE3";
|
||||
// if (in_array($cipher, openssl_get_cipher_methods())) {}
|
||||
$result = openssl_encrypt($value, $cipher, $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, "");
|
||||
return base64_encode($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title 解密
|
||||
*
|
||||
* @param string $str 要传的参数
|
||||
* @param $key
|
||||
* @return bool|false|string
|
||||
*
|
||||
*/
|
||||
public function decrypt(string $str, $key)
|
||||
{
|
||||
$decrypted = openssl_decrypt(base64_decode($str), 'DES-EDE3', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, "");
|
||||
$ret = self::UnPaddingPKCS7($decrypted);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
private function PaddingPKCS7($data)
|
||||
{
|
||||
//$block_size = mcrypt_get_block_size('tripledes', 'cbc');//获取长度
|
||||
//$block_size = openssl_cipher_iv_length('tripledes', 'cbc');//获取长度
|
||||
$block_size = 8;
|
||||
$padding_char = $block_size - (strlen($data) % $block_size);
|
||||
$data .= str_repeat(chr($padding_char), $padding_char);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:
|
||||
* author:wh
|
||||
* @param $text
|
||||
* @return false|string
|
||||
*/
|
||||
private function UnPaddingPKCS7($text)
|
||||
{
|
||||
$pad = ord($text{strlen($text) - 1});
|
||||
if ($pad > strlen($text)) {
|
||||
return false;
|
||||
}
|
||||
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) {
|
||||
return false;
|
||||
}
|
||||
return substr($text, 0, -1 * $pad);
|
||||
}
|
||||
}
|
||||
20
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/AuthError.php
vendored
Normal file
20
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/AuthError.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {19:05}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class AuthError
|
||||
{
|
||||
|
||||
const PERMISSION_DENIED = [60000, '权限拒绝'];
|
||||
|
||||
const ACCESS_REFUSE_ERROR = [60100, '访问被拒绝'];//请求不合法资源
|
||||
|
||||
const ACCESS_TIMES_ERROR = [60200, '访问次数限制'];
|
||||
}
|
||||
84
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/Code.php
vendored
Normal file
84
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/Code.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2019/11/12} {21:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
/**
|
||||
* 系统级错误, 业务错误代码放在业务层,不要放在此处
|
||||
* Class SystemError
|
||||
* @package errorcode
|
||||
*/
|
||||
class Code
|
||||
{
|
||||
//region 系统级别错误
|
||||
const SUCCESS = [200, 'SUCCESS'];
|
||||
|
||||
const REQUEST_ERROR = [10000, '请求错误'];//一般url资源错误;url错误、敏感参数错误等
|
||||
|
||||
const REQUEST_TYPE_ERROR = [10001, '请求类型错误'];//ajax get post
|
||||
|
||||
const FAILED = [10002, '操作失败'];
|
||||
|
||||
const SOURCE_NOT_FIND = [10003, '资源找不到'];
|
||||
|
||||
const SYSTEM_ERROR = [500, '系统错误'];
|
||||
|
||||
const PERMISSION_DENIED = [10005, '权限拒绝'];
|
||||
|
||||
const ACCESS_REFUSE_ERROR = [10006, '访问被拒绝'];//请求不合法资源
|
||||
|
||||
const ACCESS_TIMES_ERROR = [10007, '访问次数限制'];
|
||||
//endregion 系统级别错误
|
||||
|
||||
|
||||
|
||||
//region 短信错误
|
||||
|
||||
const MESSAGE_SEND_ERROR = [13500, '短信发送失败'];
|
||||
|
||||
const MESSAGE_SEND_ULTRALIMIT = [13600, '短信发送超限'];
|
||||
|
||||
const MESSAGE_VERIFY_FAILED = [13700, '短信验证失败'];
|
||||
|
||||
const MESSAGE_NUM_LITTLE = [13800, '短信余额不足'];
|
||||
|
||||
const MESSAGE_SEND_EXCEPTION = [13900, '短信发送异常'];
|
||||
//endregion
|
||||
|
||||
//region 文件上传
|
||||
const UPLOAD_FAILED = [14000, '上传失败'];
|
||||
|
||||
const UPLOAD_FILE_IS_EMPTY = [14000, '无文件上传'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_EMPTY = [14100, '文件内容为空'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_ERROR = [14200, '文件大小超过限制'];
|
||||
|
||||
const UPLOAD_FILE_MIME_ERROR = [14300, '文件类型错误'];
|
||||
|
||||
const UPLOAD_FILE_EXT_ERROR = [14500, '文件扩展名错误'];
|
||||
|
||||
const FILE_FROM_ERROR = [14520, '来源错误'];
|
||||
//endregion
|
||||
|
||||
|
||||
//region 数据库错误
|
||||
const DATA_IS_EMPTY = [50000, '未获取到相关数据'];
|
||||
|
||||
const UPDATE_ERROR = [50001, '修改异常'];
|
||||
|
||||
const INSERT_ERROR = [50002, '数据保存异常'];
|
||||
|
||||
const SELECT_ERROR = [50003, '查询异常'];
|
||||
|
||||
const DATA_REPEAT_ERROR = [50005, '数据重复'];
|
||||
|
||||
const DATA_INSERT_ERROR = [50006, '数据入库异常'];
|
||||
|
||||
//endregion
|
||||
}
|
||||
30
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/DbError.php
vendored
Normal file
30
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/DbError.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class DbError
|
||||
{
|
||||
|
||||
|
||||
//region 数据库错误
|
||||
const DATA_IS_EMPTY = [16000, '未获取到相关数据'];
|
||||
|
||||
const UPDATE_ERROR = [16100, '修改异常'];
|
||||
|
||||
const INSERT_ERROR = [16200, '数据保存异常'];
|
||||
|
||||
const SELECT_ERROR = [16300, '查询异常'];
|
||||
|
||||
const DATA_REPEAT_ERROR = [16400, '数据重复'];
|
||||
|
||||
const DATA_INSERT_ERROR = [16500, '数据入库异常'];
|
||||
|
||||
//endregion
|
||||
}
|
||||
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/EmailError.php
vendored
Normal file
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/EmailError.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:47}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class EmailError
|
||||
{
|
||||
//region 邮件错误
|
||||
const EMAIL_RECEIVER_IS_EMPTY = [23100, '未设置收信人'];
|
||||
|
||||
const EMAIL_SEND_FAILED = [23200, '邮件发送失败'];
|
||||
//endregion
|
||||
}
|
||||
29
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/FileUploadError.php
vendored
Normal file
29
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/FileUploadError.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class FileUploadError
|
||||
{
|
||||
//region 文件上传
|
||||
const UPLOAD_FAILED = [24000, '上传失败'];
|
||||
|
||||
const UPLOAD_FILE_IS_EMPTY = [24100, '无文件上传'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_EMPTY = [24200, '文件内容为空'];
|
||||
|
||||
const UPLOAD_FILE_SIZE_ERROR = [24300, '文件大小超过限制'];
|
||||
|
||||
const UPLOAD_FILE_MIME_ERROR = [24400, '文件类型错误'];
|
||||
|
||||
const UPLOAD_FILE_EXT_ERROR = [24500, '文件扩展名错误'];
|
||||
|
||||
const FILE_SOURCE_ERROR = [24600, '文件来源错误'];
|
||||
//endregion
|
||||
}
|
||||
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/LoginError.php
vendored
Normal file
19
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/LoginError.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class LoginError
|
||||
{
|
||||
|
||||
const OFF_LINE_ERROR = [30100, '未登录'];
|
||||
|
||||
const LOGIN_SESSION_INVALID = [30200, '登录已过期,请重新登录'];
|
||||
|
||||
}
|
||||
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/RequestError.php
vendored
Normal file
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/RequestError.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/3} {14:14}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class RequestError
|
||||
{
|
||||
//region 请求错误
|
||||
const SUCCESS = [200, 'SUCCESS'];
|
||||
|
||||
const REQUEST_TYPE_ERROR = [50601, '请求类型错误'];//ajax get post
|
||||
|
||||
const SOURCE_NOT_FIND = [50400, '资源找不到'];
|
||||
|
||||
const SYSTEM_ERROR = [50500, '系统错误'];
|
||||
|
||||
const REQUEST_ERROR = [50600, '请求错误'];//一般url资源错误;url错误、敏感参数错误等
|
||||
|
||||
const FAILED = [50602, '请求失败'];
|
||||
//endregion 请求错误
|
||||
}
|
||||
26
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SmsError.php
vendored
Normal file
26
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SmsError.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:49}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class SmsError
|
||||
{
|
||||
//region 短信错误
|
||||
|
||||
const MESSAGE_SEND_ERROR = [43500, '短信发送失败'];
|
||||
|
||||
const MESSAGE_SEND_ULTRALIMIT = [43600, '短信发送超限'];
|
||||
|
||||
const MESSAGE_VERIFY_FAILED = [43700, '短信验证失败'];
|
||||
|
||||
const MESSAGE_NUM_LITTLE = [43800, '短信余额不足'];
|
||||
|
||||
const MESSAGE_SEND_EXCEPTION = [43900, '短信发送异常'];
|
||||
//endregion
|
||||
}
|
||||
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SystemError.php
vendored
Normal file
15
digital_doctor/vendor/wanghua/general-utility-tools-php/src/errorcode/SystemError.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/7/1} {18:50}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\errorcode;
|
||||
|
||||
|
||||
class SystemError
|
||||
{
|
||||
|
||||
}
|
||||
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/Elasticsearch.php
vendored
Normal file
264
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/Elasticsearch.php
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2021/4/26} {9:45}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\es;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\Date;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,即将删除
|
||||
*
|
||||
* 【es原生操作库】
|
||||
* 【仅支持框架ThinkPHP5+、 PHP7.2+】
|
||||
*
|
||||
* BaseElasticsearch.php类库的替代库
|
||||
*
|
||||
* 使用步骤:
|
||||
* 初始化(设置ip、索引前缀-普通索引请设置为空字符串)
|
||||
* 设置索引范围(例如查询本月,如果索引不是按日期规律设置,请使用普通索引设置方法setIndexNormal,并设置前缀为空字符串)
|
||||
* 设置查询方法(eg: _search)
|
||||
* 设置查询参数(查询条件)
|
||||
* 执行
|
||||
* 返回结果
|
||||
* Class ElasticsearchUtility
|
||||
* @package app\admin\logic
|
||||
*/
|
||||
class Elasticsearch
|
||||
{
|
||||
protected $es_log_file = 'es_log';
|
||||
//最终拼装的请求地址
|
||||
protected $post_url = ''; //eg: $url = 'http://49.4.3.4:9111/qa-item-2021.04/_search';
|
||||
//查询参数
|
||||
protected $query_param = [];
|
||||
//查询方法
|
||||
protected $query_method = '_search';
|
||||
//文档索引
|
||||
protected $index = '';
|
||||
//服务器ip
|
||||
protected $ip = '';
|
||||
//索引前缀(优先设置)
|
||||
protected $index_sign = '';//eg: qa-stat-
|
||||
//设置查询日期格式符号
|
||||
protected $doc_date_sign = '.';
|
||||
//设置是哪个方法调用本es库,用于日志记录
|
||||
protected $exe_func = '';
|
||||
|
||||
|
||||
/**
|
||||
* ElasticsearchUtility constructor.
|
||||
* @param string $ip_port 协议+服务器ip+端口号,必须
|
||||
* @param string $index_sign 当es索引为有规律的日期索引时,可使用前缀并配合日期索引设置方法,体验更佳
|
||||
*/
|
||||
public function __construct(string $ip_port, string $index_sign='')
|
||||
{
|
||||
$this->ip = false===strpos($ip_port,'http')?'http://'.$ip_port:$ip_port;
|
||||
$this->index_sign = $index_sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置查询方法,默认_search
|
||||
* author:wh
|
||||
* @param $method_name
|
||||
*/
|
||||
function setQueryMethod($method_name){
|
||||
$this->query_method = $method_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:根据日期索引查询文档
|
||||
* 注:默认一个月
|
||||
*
|
||||
* eg:'qa-stat-2021.01';
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
* author:wh
|
||||
*/
|
||||
function setIndexDefault(){
|
||||
$this->setRequestIndex(date('Y'.$this->doc_date_sign.'m'));
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置要查询的日期文档索引
|
||||
*
|
||||
* 1、按年检索文档[建议5年左右]
|
||||
*
|
||||
* eg: qa-stat-2018.*,qa-stat-2019.*,qa-stat-2020.*,qa-stat-2021.*
|
||||
*
|
||||
* 注意:当索引过长,es会抛出索引太长异常
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time 开始时间 eg:2010-01-01 08:05:55
|
||||
* @param string $end_time 结束时间 eg:2021-12-31 12:05:00
|
||||
* @return string
|
||||
*/
|
||||
function setIndexYearDate(string $start_time, string $end_time){
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'*', strtotime($start_time));
|
||||
|
||||
$sign = ',';//分隔符
|
||||
|
||||
$m = date('Y', strtotime($end_time)) - date('Y', strtotime($start_time));
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
|
||||
$index .= $sign.($this->index_sign.(date('Y', strtotime($start_time))+$i).$this->doc_date_sign.'*');
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置日期索引
|
||||
*
|
||||
* 检索全部日期索引文档
|
||||
*
|
||||
* 例如es设置的索引为:
|
||||
* qa-stat-2021.01
|
||||
qa-stat-2021.02
|
||||
qa-stat-2021.03
|
||||
qa-stat-2021.04
|
||||
*
|
||||
* 实际查询自动设置为:qa-stat-*
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @return string
|
||||
*/
|
||||
function setIndexAllDate(){
|
||||
|
||||
$this->setRequestIndex('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置普通索引
|
||||
*
|
||||
* 调用此方法,请在初始化时,设置索引前缀index_sign为""空字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
function setIndexNormal(string $index){
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置跨月份索引
|
||||
*
|
||||
* eg: qa-stat-2021.01,qa-stat-2021.02
|
||||
*
|
||||
* 注:如果es设置的索引没有规律也不是日期作为索引,请设置普通索引setIndexNormal,且请在初始化时,设置索引前缀index_sign为""字符串
|
||||
*
|
||||
* author:wh
|
||||
* @param string $start_time eg:'2020-11'
|
||||
* @param string $end_time eg:'2021-01'
|
||||
* @return string eg: qa-stat-2020.11,qa-stat-2020.12,qa-stat-2021.01
|
||||
*/
|
||||
function setIndexDate(string $start_time, string $end_time){
|
||||
$date = new Date();
|
||||
|
||||
//计算月份
|
||||
$m = $date->dateCutMonth($start_time, $end_time);
|
||||
////解决跨年且不足1个月时,索引设置错误问题
|
||||
//if($m == 0 && (date('Y', strtotime($end_time)) > date('Y', strtotime($start_time)))){
|
||||
// $m = 1;
|
||||
//}
|
||||
//格式
|
||||
$date->date_format = 'Y-m';
|
||||
|
||||
//默认查询索引
|
||||
$index = date('Y'.$this->doc_date_sign.'m', strtotime($start_time));
|
||||
|
||||
$tmp_time = $start_time;
|
||||
$sign = ',';//分隔符
|
||||
|
||||
//拼装查询索引
|
||||
for ($i=0; $i<$m; $i++){
|
||||
$tmp_time = $date->addTime(1, 'M', strtotime($tmp_time));
|
||||
$index .= $sign.$this->index_sign.(date('Y'.$this->doc_date_sign.'m', strtotime($tmp_time)));
|
||||
}
|
||||
|
||||
$this->setRequestIndex($index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:设置查询参数
|
||||
* author:wh
|
||||
* @param string $query_param_json
|
||||
*/
|
||||
function setQueryParam(string $query_param_json){
|
||||
$this->query_param = $query_param_json;
|
||||
$this->post_url = $this->ip.'/'.$this->index.'/'.$this->query_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取查询参数,用于调试
|
||||
* author:wh
|
||||
* @return array
|
||||
*/
|
||||
function getQueryParam(){
|
||||
return [
|
||||
'ip'=>$this->ip,
|
||||
'index_sign'=>$this->index_sign,
|
||||
'index'=>$this->index,
|
||||
'query_method'=>$this->query_method,
|
||||
'post_url'=>$this->post_url,
|
||||
'query_param'=>$this->query_param,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:执行es查询
|
||||
* author:wh
|
||||
* @return array|bool|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
function execute(){
|
||||
if(empty($this->ip)) throw new \Exception('请设置ip');
|
||||
//if(empty($this->index_sign)) throw new \Exception('请设置索引前缀');
|
||||
if(empty($this->index)) throw new \Exception('请设置索引');
|
||||
if(empty($this->query_method)) throw new \Exception('请设置查询方法');
|
||||
if(empty($this->query_param)) throw new \Exception('请设置查询参数');
|
||||
|
||||
|
||||
|
||||
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'request_url'=>$this->post_url,'IN'=>" | IN: ",'query_params'=>$this->query_param, 'input'=>input()], $this->es_log_file);
|
||||
$result = Tools::curl_post($this->post_url, $this->query_param);
|
||||
Tools::log_to_write_txt(['exe_func'=>$this->exe_func,'OUT'=>" | OUT: ", 'result'=>$result], $this->es_log_file);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置是哪个方法调用本es库,用于日志记录
|
||||
* author:wh
|
||||
* @param string $function
|
||||
*/
|
||||
function setExecuteFunction(string $function){
|
||||
$this->exe_func = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置请求文档索引
|
||||
* author:wh
|
||||
* @param string $index
|
||||
*/
|
||||
protected function setRequestIndex(string $index){
|
||||
$this->index = $this->index_sign.$index;
|
||||
}
|
||||
|
||||
}
|
||||
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/README.md
vendored
Normal file
1340
digital_doctor/vendor/wanghua/general-utility-tools-php/src/es/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/BaseException.php
vendored
Normal file
16
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/BaseException.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:01}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception;
|
||||
|
||||
use think\Exception;
|
||||
|
||||
class BaseException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/README.md
vendored
Normal file
27
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/README.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# 系统业务级异常类
|
||||
1. api异常
|
||||
2. 请求异常
|
||||
3. api异常
|
||||
4. 响应异常
|
||||
5. 待扩展......
|
||||
|
||||
|
||||
|
||||
##使用说明
|
||||
例1:
|
||||
|
||||
if(empty($params)){
|
||||
//参数错误,抛出空参数异常
|
||||
throw new RequestException(RequestException::EMPTY_PARAM_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
例2:
|
||||
|
||||
//假设返回结果格式为:['code'=>200, 'msg'=>'操作成功', 'data'=>[]]
|
||||
if(is_null($result['code'])){
|
||||
//无code字段,抛出响应格式错误
|
||||
throw new ResponseException(ResponseException::RESPONSE_FORMAT_ERROR);
|
||||
}
|
||||
60
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/SystemException.php
vendored
Normal file
60
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/SystemException.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2022/03/08} {14:17}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception;
|
||||
|
||||
|
||||
use think\exception\Handle;
|
||||
use think\Request;
|
||||
use wanghua\general_utility_tools_php\SundryConfig;
|
||||
use wanghua\general_utility_tools_php\tool\EmailTool;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
class SystemException extends Handle
|
||||
{
|
||||
public function render(\Exception $e)
|
||||
{
|
||||
// 参数验证错误
|
||||
//if ($e instanceof ValidateException) {
|
||||
// return json($e->getError(), 422);
|
||||
//}
|
||||
|
||||
// 请求异常
|
||||
//if ($e instanceof HttpException && request()->isAjax()) {
|
||||
// return response($e->getMessage(), $e->getStatusCode());
|
||||
//}
|
||||
|
||||
Tools::log_to_write_txt([
|
||||
'error'=>'系统错误.'.$e->getMessage(),
|
||||
'input'=>Request::instance()->input(),
|
||||
'error_info'=>$e->getTraceAsString()
|
||||
]);
|
||||
|
||||
$title = '新的【系统异常】,请立即处理';
|
||||
//邮件通知管理员
|
||||
$mail_content = '<p>error:'.$e->getMessage().'</p>';
|
||||
$mail_content .= '<p>url:'.request()->url(true).'</p>';
|
||||
$mail_content .= '<p>ip:'.request()->ip().'</p>';
|
||||
$mail_content .= '<p>详情请登录宝塔查看日志</p>';
|
||||
|
||||
$emails = SundryConfig::val('admin_error_log_email');
|
||||
if(config('sys_env') == 'PROD'){//线上环境才发错误邮件
|
||||
EmailTool::email_to_person($title,$mail_content,$emails);
|
||||
}
|
||||
|
||||
if(request()->LogObj){
|
||||
request()->LogObj->flush();
|
||||
}
|
||||
if(request()->ServeLogObj){
|
||||
request()->ServeLogObj->flush();
|
||||
}
|
||||
|
||||
//可以在此交由系统处理
|
||||
return parent::render($e);
|
||||
}
|
||||
}
|
||||
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/api/ApiException.php
vendored
Normal file
21
digital_doctor/vendor/wanghua/general-utility-tools-php/src/exception/api/ApiException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:04}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\api;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class ApiException extends BaseException
|
||||
{
|
||||
const API_RESPONSE_FORMAT_ERROR='The api response result is incorrectly formatted: code is not exist.';
|
||||
|
||||
|
||||
const EMPTY_PARAM_ERROR ='param is empty.';
|
||||
const EMPTY_URL_ERROR ='url of param is empty.';
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:13}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\request;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class RequestException extends BaseException
|
||||
{
|
||||
const EMPTY_PARAM_ERROR ='param is empty.';
|
||||
const EMPTY_URL_ERROR ='url of param is empty.';
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/11/14} {10:48}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\exception\response;
|
||||
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\exception\BaseException;
|
||||
|
||||
class ResponseException extends BaseException
|
||||
{
|
||||
const RESPONSE_FORMAT_ERROR='The response result is incorrectly formatted.';
|
||||
|
||||
}
|
||||
53
digital_doctor/vendor/wanghua/general-utility-tools-php/src/fastadmin/FastadminTools.php
vendored
Normal file
53
digital_doctor/vendor/wanghua/general-utility-tools-php/src/fastadmin/FastadminTools.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/1/16} {17:15}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\fastadmin;
|
||||
|
||||
|
||||
use app\common\model\TabConf;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 为fastadmin框架定制的功能
|
||||
*
|
||||
* Class FastadminTools
|
||||
* @package wanghua\general_utility_tools_php\fastadmin
|
||||
*/
|
||||
class FastadminTools
|
||||
{
|
||||
|
||||
/**
|
||||
* desc:线上需要自动隐藏的菜单
|
||||
*
|
||||
* 当你有这种需求:
|
||||
* 我的菜单只需要本地显示,线上或非本地环境不需要显示时,就可以使用此方法。
|
||||
* 为什么需要此方法?
|
||||
* 因为,我每次在本地增加功能并新增菜单之后,都需要把本地的菜单同步到线上,但是命令管理菜单,或者有些只需要开发者才能
|
||||
* 动的菜单,需要在线上隐藏。我又不想每次同步之后去改菜单表。
|
||||
* 手动去菜单表改也是可以,但是次数多了就很麻烦,有时候会忘记。
|
||||
*
|
||||
* 如:命令管理菜单、开发者相关配置
|
||||
*
|
||||
* author:wh
|
||||
* @param array $menu_arr 需要隐藏的菜单数组
|
||||
* @param string $sys_env
|
||||
* @return bool
|
||||
*/
|
||||
static function auto_hidden_menu_online(array $menu_arr, string $sys_env){
|
||||
|
||||
foreach ($menu_arr as $menu_name){
|
||||
if($sys_env == 'LOCAL'){
|
||||
//本地显示
|
||||
Db::table('fa_auth_rule')->where('name',$menu_name)->data(['status'=>'normal'])->update();
|
||||
}else{
|
||||
Db::table('fa_auth_rule')->where('name',$menu_name)->data(['status'=>'hidden'])->update();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
236
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/File.php
vendored
Normal file
236
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/File.php
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2024/2/4} {16:59}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\file;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 文件、文件夹操作类
|
||||
*
|
||||
* eg:读取文件夹、复制文件等
|
||||
*
|
||||
* Class FileOperate
|
||||
* @package wanghua\general_utility_tools_php\file
|
||||
*/
|
||||
class File
|
||||
{
|
||||
|
||||
public $file_ext = '*.*';//扩展名
|
||||
public $unzip_path = '';//解压路径
|
||||
|
||||
/**
|
||||
* desc:读取文件和文件夹
|
||||
*
|
||||
* author:wh
|
||||
* @param $folderPath 读取目标路径下的文件夹和文件
|
||||
*
|
||||
* @param $dirs 存储文件路径 eg:D:\wanghua\old_files
|
||||
*
|
||||
//array(3) {
|
||||
// [0] => array(1) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// }
|
||||
// [1] => array(1) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/222"
|
||||
// }
|
||||
//}
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param $file_name_arr 存储文件路径、文件名称
|
||||
*
|
||||
//array(64) {
|
||||
// [0] => array(3) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// ["path_file"] => string(33) "D:\wanghua\test_files/111/111.txt"
|
||||
// ["filename"] => string(7) "111.txt"
|
||||
// }
|
||||
// [1] => array(3) {
|
||||
// ["path"] => string(25) "D:\wanghua\test_files/111"
|
||||
// ["path_file"] => string(37) "D:\wanghua\test_files/111/1111111.txt"
|
||||
// ["filename"] => string(11) "1111111.txt"
|
||||
// }
|
||||
//}
|
||||
*/
|
||||
function read_folder($folderPath,&$dirs,&$file_name_arr) {
|
||||
// 获取指定目录下所有文件和文件夹
|
||||
$files = scandir($folderPath);
|
||||
foreach ($files as $file) {
|
||||
// 如果当前项为文件夹且不是"."或者".."
|
||||
if (is_dir("$folderPath/$file") && !in_array($file, array('.', '..'))) {
|
||||
$dirs[] = ['path'=>$folderPath.'/'.$file];//此时的$file是文件夹名称
|
||||
// 调用自身进行递归操作
|
||||
$this->read_folder("$folderPath/$file",$dirs,$file_name_arr);
|
||||
} elseif (!in_array($file, array('.', '..'))){ // 如果当前项为文件而非"."或者".."
|
||||
$file_name_arr[] = ['path'=>$folderPath,'path_file'=>"$folderPath/$file",'filename'=>$file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:复制文件
|
||||
*
|
||||
* author:wh
|
||||
* @param array $sourceFileArr 源文件路径数组 path,path_file,filename
|
||||
*
|
||||
* @param string $destination_path 目标存放路径 D:\wanghua\test_files\new_files
|
||||
*
|
||||
* @param array $cp_type_arr 允许复制的文件后缀 eg:['jpg','png,'spine']
|
||||
*
|
||||
* @param bool $is_cover 是否覆盖 默认false,不覆盖会以源文件名+微秒时间戳格式作为新的文件名
|
||||
*
|
||||
* @param bool $is_continue 相同文件是否跳过复制 默认 true
|
||||
*
|
||||
* 实战案例:
|
||||
*
|
||||
function testcopy(){
|
||||
$source_dir = 'D:\wanghua\test_files';//源文件路径
|
||||
$destination_path = 'D:\wanghua\test_files\new_files';//目标文件路径
|
||||
|
||||
$dirs = [];//存储文件路径
|
||||
$file_name_arr = [];//含文件路径、名称
|
||||
$file_obj = new File();
|
||||
$file_obj->read_folder($source_dir,$dirs,$file_name_arr);
|
||||
//dump($dirs);
|
||||
//dump($file_name_arr);die;
|
||||
$file_obj->copy($file_name_arr,$destination_path,['jpg','png,'spine']);
|
||||
}
|
||||
*
|
||||
*/
|
||||
function copy(array $sourceFileArr, string $destination_path, $cp_type_arr=['jpg','png'], $is_cover=false, $is_continue=false){
|
||||
//设置不超时
|
||||
set_time_limit(0);
|
||||
//源文件路径 => 目标文件路径
|
||||
foreach ($sourceFileArr as $key=>$file_arr){
|
||||
if(!file_exists($file_arr['path_file'])){
|
||||
continue;
|
||||
}
|
||||
//验证目标文件夹路径
|
||||
if(!file_exists($destination_path)){
|
||||
mkdir($destination_path,0777,true);
|
||||
}
|
||||
$name_arr = explode('.',$file_arr['filename']);
|
||||
//验证符合条件的文件类型
|
||||
if(!in_array($name_arr[1],$cp_type_arr)){
|
||||
continue;
|
||||
}
|
||||
if(file_exists($destination_path.'/'.$file_arr['filename'])){
|
||||
if($is_continue){
|
||||
continue;//相同文件跳过复制
|
||||
}
|
||||
//覆盖
|
||||
if($is_cover){
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
|
||||
}else{
|
||||
//不覆盖,名称区分
|
||||
$microsecond = Tools::getMicrosecond();
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$name_arr[0].'('.$microsecond.').'.$name_arr[1]);
|
||||
}
|
||||
}else{
|
||||
copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:递归删除目录
|
||||
*
|
||||
* $dir 物理路径
|
||||
*
|
||||
* author:wh
|
||||
*/
|
||||
function recursive_delete($dir) {
|
||||
if (!is_dir($dir)) {
|
||||
return unlink($dir);
|
||||
}
|
||||
|
||||
$handle = opendir($dir);
|
||||
while (($file = readdir($handle)) !== false) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
$path = $dir . DIRECTORY_SEPARATOR . $file;
|
||||
if (is_dir($path)) {
|
||||
$this->recursive_delete($path);
|
||||
} else {
|
||||
unlink($path);
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
rmdir($dir);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:解压ZIP文件并存储在本地
|
||||
* author:wh
|
||||
* @param resource $file_stream 文件流
|
||||
* 例如:$response = $client->request('POST', $url, [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
]);
|
||||
// 处理响应
|
||||
//$file_stream = $response->getBody();
|
||||
* @param string $save_path 存储路径
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function unzip($file_stream,$save_path){
|
||||
$zpi_file_name = 'zip_tmp_file_'.Tools::rand_str(20).'.zip';
|
||||
//这个目录将会在结束时删除
|
||||
$zipTempPath = $save_path.'/tmp_zip_files/'; // 临时存放ZIP文件的路径
|
||||
//压缩文件保存目录
|
||||
if(!file_exists($zipTempPath)){
|
||||
mkdir($zipTempPath,0777,true);
|
||||
}
|
||||
$zpi_file = $zipTempPath.$zpi_file_name;
|
||||
// 保存ZIP文件到临时路径
|
||||
file_put_contents($zpi_file, $file_stream);
|
||||
|
||||
$this->unzip_path = $zipTempPath.'unzip_files/';
|
||||
//解压目录
|
||||
if(!file_exists( $this->unzip_path)){
|
||||
mkdir( $this->unzip_path,0777,true);
|
||||
}
|
||||
// 解压ZIP文件
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($zpi_file) === TRUE) {
|
||||
$zip->extractTo( $this->unzip_path);//移动到临时解压目录
|
||||
$zip->close();
|
||||
//遍历所有文件(file_ext后缀自行指定),遍历部分文件,如:*.json,*.zip,*.mp4,*.mp3等
|
||||
$wavFiles = $this->glob_by_ext( $this->unzip_path.$this->file_ext);
|
||||
|
||||
//$urls = [];
|
||||
//// 遍历解压后的文件,生成URL
|
||||
//foreach ($wavFiles as $wavFilePath) {
|
||||
// // 生成外部访问的URL
|
||||
// $downloadUrl = request()->domain() . explode('public',$wavFilePath)[1];
|
||||
// $urls[] = $downloadUrl;
|
||||
//}
|
||||
//// 返回所有WAV文件的URL
|
||||
//return ['wav_urls' => $urls];
|
||||
return $wavFiles;
|
||||
} else {
|
||||
throw new \Exception('Failed to open ZIP file.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取指定扩展类型的文件列表
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_ext 如: wav,pm4,mp3,json,zip
|
||||
* @return array|false
|
||||
*/
|
||||
function glob_by_ext($file_ext='*'){
|
||||
return glob( $this->unzip_path.'*.'.$file_ext);
|
||||
}
|
||||
}
|
||||
5
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/README.MD
vendored
Normal file
5
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/README.MD
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
## 文件处理
|
||||
|
||||
#### 文件夹读取,文件复制
|
||||
|
||||
#### 文件上传
|
||||
764
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/FileUpload.php
vendored
Normal file
764
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/FileUpload.php
vendored
Normal file
@@ -0,0 +1,764 @@
|
||||
<?php
|
||||
/*
|
||||
* description:
|
||||
* author:wh
|
||||
* email:
|
||||
* createTime:{2020/4/3} {9:23}
|
||||
*/
|
||||
|
||||
namespace wanghua\general_utility_tools_php\file\upload;
|
||||
|
||||
|
||||
use wanghua\general_utility_tools_php\oss\alicloud\Objects;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use wanghua\general_utility_tools_php\huawei\obs\InitObs;
|
||||
use wanghua\general_utility_tools_php\Mmodel;
|
||||
use wanghua\general_utility_tools_php\oss\huawei\obs\Config;
|
||||
use wanghua\general_utility_tools_php\tool\Tools;
|
||||
|
||||
/**
|
||||
* 上传组件
|
||||
* 支持单图,多图,单文件,多文件
|
||||
* Class FileUpload
|
||||
* @package libraries
|
||||
*/
|
||||
class FileUpload
|
||||
{
|
||||
//文件扩展
|
||||
protected $file_ext = 'ico,jpg,jpeg,png,gif,pdf,zip,rar,xls,xlsx,doc,docx';
|
||||
//图片扩展
|
||||
protected $img_ext = 'ico,jpg,jpeg,png,gif';
|
||||
|
||||
public $unique_key = '';//唯一key,临时文件会存储至该目录,推荐使用用户id
|
||||
|
||||
public $file_lists_urls = [];//要读取的文件地址列表
|
||||
/**
|
||||
* 文件存放目录
|
||||
*
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* @var string
|
||||
*/
|
||||
private $file_dir = '/uploads';
|
||||
|
||||
/**
|
||||
* desc:默认目录/uploads
|
||||
*
|
||||
* eg:/uploads/user/head_image 或 /files_manage/goods/images
|
||||
*
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
* 注意:后面不要“/”
|
||||
*
|
||||
* author:wh
|
||||
* @param $file_dir
|
||||
*/
|
||||
function setFileDir($file_dir){
|
||||
$this->file_dir = $file_dir;
|
||||
}
|
||||
/**
|
||||
* desc:单图
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认2M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function image($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件 例如上传了001.jpg
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$outer_req_url = $this->file_dir.'/image';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '上传文件不存在');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->img_ext;
|
||||
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}else{
|
||||
// 上传失败获取错误信息
|
||||
return Tools::set_res(1, $file->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:多图
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认2M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function images($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
$outer_req_url = $this->file_dir.'/image';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->img_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach($files as $file){
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result[] = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
}else{
|
||||
//忽略错误
|
||||
// 上传失败获取错误信息
|
||||
$error[] = $file->getError();
|
||||
}
|
||||
}
|
||||
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:单文件
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 大小,默认10M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function file($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
// 获取表单上传文件 例如上传了001.jpg
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$outer_req_url = $this->file_dir.'/file';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
if(empty($file)){
|
||||
return Tools::set_res(1, '上传文件不存在');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}else{
|
||||
// 上传失败获取错误信息
|
||||
return Tools::set_res(1, $file->getError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:多文件
|
||||
*
|
||||
* 【!!!必须确认php.ini中upload_max_filesize的配置足够大,否则上传失败但不会报错!!!】
|
||||
*
|
||||
* author:wh
|
||||
* @param string $file_upload_name 表单文件元素name值
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的扩展
|
||||
* @return array
|
||||
*/
|
||||
function files($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
if(!$this->uploadMaxFilesizeCheck($size)){
|
||||
return Tools::set_res(1, '上传文件受限');
|
||||
}
|
||||
|
||||
$root_path = explode('vendor',__DIR__)[0];
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
$outer_req_url = $this->file_dir.'/file';
|
||||
$physics_path = 'public'.$outer_req_url;
|
||||
$upload_dir = $root_path.$physics_path;
|
||||
if(!is_dir($upload_dir)){
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach($files as $file){
|
||||
// 移动到框架应用根目录/uploads/ 目录下
|
||||
$info = $file->validate(['size'=>$size * 1024 * 1024, 'ext'=>$ext])->move($upload_dir);
|
||||
if($info){
|
||||
//原文件名
|
||||
$source_file_name = $info->getInfo('name');
|
||||
|
||||
//文件类型
|
||||
$file_type = $info->getInfo('type');
|
||||
|
||||
// 输出扩展名 jpg
|
||||
$extension = $info->getExtension();
|
||||
|
||||
// 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg
|
||||
$save_name = $info->getSaveName();
|
||||
|
||||
// 输出 42a79759f284b767dfcb2a0197904287.jpg
|
||||
$new_filename = $info->getFilename();
|
||||
|
||||
$relative_url = $outer_req_url.'/'.str_replace('\\', '/', $save_name);
|
||||
$result[] = [
|
||||
'prefix'=>request()->domain().$outer_req_url,//访问前缀
|
||||
'source_file_name'=>$source_file_name,
|
||||
'file_type'=>$file_type,
|
||||
'extension'=>$extension,
|
||||
'save_name'=>str_replace('\\', '/', $save_name),
|
||||
'new_filename'=>$new_filename,
|
||||
'real_path'=>$this->dealPath($root_path.'public'.$relative_url),//物理路径
|
||||
'outer_req_url'=>request()->domain().$relative_url,
|
||||
'outer_req_relative_url'=>$relative_url,
|
||||
'size'=>$info->getSize(),
|
||||
];
|
||||
}else{
|
||||
//忽略错误
|
||||
// 上传失败获取错误信息
|
||||
$error[] = $file->getError();
|
||||
}
|
||||
}
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:单文件或多文件上传至阿里云OSS服务
|
||||
*
|
||||
* author:wh
|
||||
* @param array $config 配置
|
||||
* //阿里云oss配置
|
||||
'aliyun_oss_config' => [
|
||||
//项目应用名称
|
||||
'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀,代表这个bucket属于哪个项目
|
||||
'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
|
||||
'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
|
||||
'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
|
||||
'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
|
||||
//https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
|
||||
'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀,否则提示:Invalid signing region in Authorization header
|
||||
//西南1(成都)
|
||||
//oss-cn-chengdu
|
||||
//oss-cn-chengdu.aliyuncs.com
|
||||
//oss-cn-chengdu-internal.aliyuncs.com
|
||||
'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
|
||||
'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
|
||||
]
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识,默认存放在(项目名称/控制器/方法/(唯一标识,可为空)/年月日/*.jpg)
|
||||
* @param string $file_upload_name 文件上传控件的name值,必须带[],例如:file_upload[]
|
||||
* @param string $oss_type oss类型,可选值:ali_cloud 阿里云,hua_wei 华为云(待扩展)
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的文件扩展名
|
||||
* @return array
|
||||
*/
|
||||
function filesUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
|
||||
return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
if(($size > $ini_upload_max_filesize)){
|
||||
return Tools::set_res(1, '上传文件size受限,不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$files = request()->file($file_upload_name);
|
||||
if(empty($files)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
//扩展
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
//初始化阿里云OSS客户端
|
||||
$oss_obj= new Objects($config);
|
||||
//默认存储地址
|
||||
$file_save_dir = $this->setFileSaveDir($unique_id);
|
||||
$urls = [];
|
||||
foreach($files as $file){
|
||||
if(!$file->isValid()){
|
||||
return Tools::set_fail('文件不合法');
|
||||
}
|
||||
$check_size = $file->checkSize($size*1024*1024);
|
||||
if(!$check_size){
|
||||
return Tools::set_fail('文件大小超限');
|
||||
}
|
||||
$check_res = $file->checkExt($ext);
|
||||
if(!$check_res){
|
||||
return Tools::set_fail('请上传合法文件');
|
||||
}
|
||||
$extension = explode('.',$file->getInfo('name'))[1];
|
||||
$new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
|
||||
//必须加后缀
|
||||
$filename = $file_save_dir.$new_filename;
|
||||
|
||||
// 从文件流上传
|
||||
$res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
|
||||
$urls[] = [
|
||||
'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
|
||||
'source_file_name'=>$file->getInfo('name'),//源文件名
|
||||
'size'=>$file->getInfo('size'),//大小(b)
|
||||
'extension'=>$extension,//扩展名
|
||||
'file_type'=>$file->getInfo('type'),//文件后缀
|
||||
'save_name'=>$filename,//保存文件名
|
||||
'new_filename'=>$new_filename,//新文件名
|
||||
'real_path'=>$res['info']['url'],//实际路径
|
||||
'outer_req_url'=>$res['info']['url'],//外部访问地址
|
||||
'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
|
||||
];
|
||||
}
|
||||
return Tools::set_ok('ok', $urls);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:单文件上传至阿里云OSS
|
||||
*
|
||||
* author:wh
|
||||
* @param array $config 配置
|
||||
* //阿里云oss配置
|
||||
'aliyun_oss_config' => [
|
||||
//项目应用名称
|
||||
'bucket'=>'wanlliuyinli-adm',//每创建一个bucket必须标明前缀,代表这个bucket属于哪个项目
|
||||
'UserPrincipalName'=>'wanghua@1113242774600735.onaliyun.com',
|
||||
'Password'=>'0osE4cGo%tllnP1|uOQADPhM}Y?obR4U',
|
||||
'AccessKeyId'=>'LTAI5tPqn1n7jugviVoGqFfa',
|
||||
'AccessKeySecret'=>'BRoB5TdcUAFEuIR11BbN3R47Cm4Yep',
|
||||
//https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.41ae2effA6oZar
|
||||
'region_id'=>'cn-chengdu',//这里配置不能包含oss-前缀,否则提示:Invalid signing region in Authorization header
|
||||
//西南1(成都)
|
||||
//oss-cn-chengdu
|
||||
//oss-cn-chengdu.aliyuncs.com
|
||||
//oss-cn-chengdu-internal.aliyuncs.com
|
||||
'endpoint'=>'oss-cn-chengdu.aliyuncs.com',//成都节点
|
||||
'sts_endpoint'=>'sts.cn-chengdu.aliyuncs.com',//sts服务节点
|
||||
]
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识,默认存放在(项目名称/控制器/方法/(唯一标识,可为空)/年月日/*.jpg)
|
||||
* @param string $file_upload_name 文件上传控件的name值,例如:file_upload
|
||||
* @param string $oss_type oss类型,可选值:ali_cloud 阿里云,hua_wei 华为云(待扩展)
|
||||
* @param int $size 单文件大小,默认10M
|
||||
* @param string $ext 允许的文件扩展名
|
||||
* @return array
|
||||
*/
|
||||
function fileUploadToAliCloudOss($config,$unique_id='',$file_upload_name = 'file_upload',$size=10, $ext=''){
|
||||
return Mmodel::catch(function ()use ($config,$unique_id,$file_upload_name,$size,$ext){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
if(($size > $ini_upload_max_filesize)){
|
||||
return Tools::set_res(1, '上传文件size受限,不能超过upload_max_filesize='.ini_get('upload_max_filesize').'M');
|
||||
}
|
||||
// 获取表单上传文件
|
||||
$file = request()->file($file_upload_name);
|
||||
if(empty($file)){
|
||||
return Tools::set_fail('请上传文件');
|
||||
}
|
||||
//扩展
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
//初始化阿里云OSS客户端
|
||||
$oss_obj= new Objects($config);
|
||||
//默认存储地址
|
||||
$file_save_dir = $this->setFileSaveDir($unique_id);
|
||||
$urls = [];
|
||||
if(!$file->isValid()){
|
||||
return Tools::set_fail('文件不合法');
|
||||
}
|
||||
$check_size = $file->checkSize($size*1024*1024);
|
||||
if(!$check_size){
|
||||
return Tools::set_fail('文件大小超限');
|
||||
}
|
||||
$check_res = $file->checkExt($ext);
|
||||
if(!$check_res){
|
||||
return Tools::set_fail('请上传合法文件');
|
||||
}
|
||||
$extension = explode('.',$file->getInfo('name'))[1];
|
||||
$new_filename = 'file_'.Tools::rand_str(18).'.'.explode('.',$file->getInfo('name'))[1];
|
||||
//必须加后缀
|
||||
$filename = $file_save_dir.$new_filename;
|
||||
|
||||
// 从文件流上传
|
||||
$res = $oss_obj->fileUpload($filename, $file->getInfo('tmp_name'));//上传之前的临时文件物理地址
|
||||
$urls[] = [
|
||||
'prefix'=>explode('.com',$res['info']['url'])[0].'.com',//访问前缀
|
||||
'source_file_name'=>$file->getInfo('name'),//源文件名
|
||||
'size'=>$file->getInfo('size'),//大小(b)
|
||||
'extension'=>$extension,//扩展名
|
||||
'file_type'=>$file->getInfo('type'),//文件后缀
|
||||
'save_name'=>$filename,//保存文件名
|
||||
'new_filename'=>$new_filename,//新文件名
|
||||
'real_path'=>$res['info']['url'],//实际路径
|
||||
'outer_req_url'=>$res['info']['url'],//外部访问地址
|
||||
'outer_req_relative_url'=>$res['info']['url'],//外部访问相对地址
|
||||
];
|
||||
return Tools::set_ok('ok', $urls);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:设置文件保存目录
|
||||
* author:wh
|
||||
* @param string $unique_id 唯一id,可以是用户id,可以是其它用于区分的标识
|
||||
* @return string
|
||||
*/
|
||||
function setFileSaveDir($unique_id=''){
|
||||
if($unique_id){
|
||||
$unique_id = $unique_id.'/';
|
||||
}
|
||||
//项目名称
|
||||
$project_name = Tools::get_project_name();
|
||||
//控制器方法路径
|
||||
$ctl = strtolower(request()->controller().'/'.request()->action());
|
||||
return $project_name.'/'.$ctl.'/'.$unique_id.date('Ymd').'/';//日期
|
||||
}
|
||||
/**
|
||||
* desc:检测size是否在ini配置范围
|
||||
*
|
||||
* author:wh
|
||||
* @param $size
|
||||
* @return bool
|
||||
*/
|
||||
private function uploadMaxFilesizeCheck($size){
|
||||
$ini_upload_max_filesize = str_replace('M','',ini_get('upload_max_filesize'));
|
||||
return $size<=$ini_upload_max_filesize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:上传base64格式图片【文件不用base64传输】
|
||||
* author:wh
|
||||
* @param string $file_upload_name
|
||||
* @param int $size
|
||||
* @param array $ext
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function uploadBase64Img($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
$source = input($file_upload_name, 'file_upload');
|
||||
$file_size = strlen($source);
|
||||
if($file_size > $size * 1024 * 1024){
|
||||
return Tools::set_res(1, '上传失败,大小限制');
|
||||
}
|
||||
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $result) < 1){
|
||||
return Tools::set_res(1, '上传文件不合法');
|
||||
}
|
||||
$type = $result[2];
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
if(!in_array($type, explode($ext))){
|
||||
return Tools::set_res(1, '上传失败,类型限制');
|
||||
}
|
||||
$result = base64_image_content($source);
|
||||
if(false === $result){
|
||||
return Tools::set_res(1, '上传失败');
|
||||
}
|
||||
return Tools::set_res(0, '上传成功', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:批量上传base64格式图片【文件不用base64传输】
|
||||
* author:wh
|
||||
* @param string $file_upload_name
|
||||
* @param int $size
|
||||
* @param array $ext
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
function uploadBase64Imgs($file_upload_name = 'file_upload', $size=10, $ext=''){
|
||||
$source_list = input($file_upload_name, 'file_upload');
|
||||
if(!is_array($source_list)){
|
||||
return Tools::set_res(1, '参数错误');
|
||||
}
|
||||
|
||||
if(empty($ext)) $ext = $this->file_ext;
|
||||
|
||||
$result = [];
|
||||
$error = [];
|
||||
foreach ($source_list as $source){
|
||||
$file_size = strlen($source);
|
||||
if($file_size > $size * 1024 * 1024){
|
||||
$error[] = '上传失败,大小限制';
|
||||
continue;
|
||||
}
|
||||
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $source, $temp) < 1){
|
||||
$error[] = '上传文件不合法';
|
||||
continue;
|
||||
}
|
||||
$type = $temp[2];
|
||||
if(!in_array($type, explode(',', $ext))){
|
||||
$error[] = '类型限制';
|
||||
continue;
|
||||
}
|
||||
$up_result = base64_image_content($source);
|
||||
if(false === $up_result){
|
||||
$error[] = '上传失败';
|
||||
continue;
|
||||
}
|
||||
$result[] = $up_result;
|
||||
}
|
||||
|
||||
$msg = '上传成功';
|
||||
$code = 0;
|
||||
if(count($error) > 0){
|
||||
$msg = '上传失败;提示:'.implode(',', $error);//顺带返回错误信息
|
||||
$code = 1;
|
||||
}
|
||||
return Tools::set_res($code, $msg, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:优化路径格式
|
||||
* author:wh
|
||||
*/
|
||||
private function dealPath(string $path){
|
||||
$str = str_replace('\\','/',$path);
|
||||
|
||||
return str_replace('//','/',$str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* desc:curl上传文件,php上传文件到远程服务器地址
|
||||
*
|
||||
* [php curl模拟文件上传]
|
||||
*
|
||||
* 依赖库:"guzzlehttp/guzzle": "^7.8",
|
||||
*
|
||||
* author:wh
|
||||
* @param $url
|
||||
* @param $params
|
||||
* @param false[] $config
|
||||
*/
|
||||
function uploadCurlFiles($url,$params, $config=['verify' => false]){
|
||||
if(empty($this->unique_key)){
|
||||
throw new \Exception('UNIQUE_KEY 不能为空');
|
||||
}
|
||||
if(empty($this->file_lists_urls)){
|
||||
throw new \Exception('文件地址列表不能为空');
|
||||
}
|
||||
// 创建 Guzzle HTTP 客户端实例
|
||||
$client = new Client($config);
|
||||
|
||||
// 定义要上传的文件列表
|
||||
$files = [
|
||||
//[
|
||||
// 'name' => 'file1', // 服务器接收的文件字段名
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\dc1c441d81d48565ac6817b89d0f8bef.mp4', 'r'), // 文件路径
|
||||
// 'filename' => 'dc1c441d81d48565ac6817b89d0f8bef.mp4', // 文件名,可自定义
|
||||
//],
|
||||
//[
|
||||
// 'name' => 'files',
|
||||
// 'contents' => Utils::tryFopen('D:\wanghua\projects\big_world_projects\universal_gravitation\public\uploads\20240506\f80179b23b60619fba8033bfd64f8817.mp4', 'r'),
|
||||
// 'filename' => 'f80179b23b60619fba8033bfd64f8817.mp4',
|
||||
//],
|
||||
//['name'=>'prompt','contents'=>$prompt],
|
||||
//['name'=>'tts_url','contents'=>$tts_url]
|
||||
// 可以继续添加更多文件...
|
||||
];
|
||||
//print_r($params);
|
||||
foreach ($params as $key=>$val){
|
||||
$files[] = ['name'=>$key,'contents'=>$val];
|
||||
}
|
||||
$controller = strtolower(request()->controller());
|
||||
$action = strtolower(request()->action());
|
||||
$save_path = Tools::get_root_path() . "public/uploads/{$controller}/{$action}/".$this->unique_key;
|
||||
if(!file_exists($save_path)){
|
||||
mkdir($save_path,0777,true);
|
||||
}
|
||||
|
||||
//文件远程可访问地址列表
|
||||
foreach ($this->file_lists_urls as $name=>$video_url) {
|
||||
//处理可用地址(可能存储在本地或oss)
|
||||
$video_url = $this->get_usable_url($video_url);
|
||||
$files[] = [
|
||||
'name'=>"files",//服务器接收的文件字段名
|
||||
//读取地址文件流(本地地址或远程地址均可,本地真实物理地址也行)
|
||||
'contents'=>Utils::tryFopen($video_url, 'r'),
|
||||
'filename'=>$name,//可自定义 文件名
|
||||
];
|
||||
}
|
||||
|
||||
// 构建多部分表单数据
|
||||
$multipartStream = new MultipartStream($files);
|
||||
$boundary = $multipartStream->getBoundary();
|
||||
$headers = [
|
||||
'Content-Type' => "multipart/form-data; boundary={$boundary}",
|
||||
];
|
||||
|
||||
// 准备请求体
|
||||
$body = $multipartStream->getContents();
|
||||
|
||||
// 发起 POST 请求
|
||||
try {
|
||||
$postinfo = [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
];
|
||||
//上传
|
||||
$response = $client->request('POST', $url, $postinfo);
|
||||
// 处理响应
|
||||
//$responseBody = (string) $response->getBody();
|
||||
// 检查状态码
|
||||
//if ($response->getStatusCode() !== 200) {
|
||||
// return false;
|
||||
//}
|
||||
return $response;//返回上传结果
|
||||
} catch (\GuzzleHttp\Exception\RequestException $e) {
|
||||
// 错误处理
|
||||
//echo "Error: " . $e->getMessage();
|
||||
Tools::error_txt_log($e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* desc:获取视频可用地址(兼容远程地址或本地地址)
|
||||
* author:wh
|
||||
* @param $video_url
|
||||
* @return string|string[]
|
||||
*/
|
||||
private function get_usable_url($video_url){
|
||||
if(strpos($video_url,'http')!==false){
|
||||
return $video_url;//远程地址
|
||||
}
|
||||
return Tools::get_root_path().$video_url;//本地地址
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
1
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/README.MD
vendored
Normal file
1
digital_doctor/vendor/wanghua/general-utility-tools-php/src/file/upload/README.MD
vendored
Normal file
@@ -0,0 +1 @@
|
||||
## 文件上传类库
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user