panghu 8 сар өмнө
parent
commit
624e124f0f
39 өөрчлөгдсөн 4258 нэмэгдсэн , 138 устгасан
  1. 8 0
      .idea/.gitignore
  2. 116 0
      .idea/blade.xml
  3. 12 0
      .idea/codeception.xml
  4. 1503 0
      .idea/commandlinetools/Laravel_2026_1_30_8_52.xml
  5. 47 0
      .idea/commandlinetools/schemas/frameworkDescriptionVersion1.1.4.xsd
  6. 19 0
      .idea/deployment.xml
  7. 6 0
      .idea/git_toolbox_blame.xml
  8. 22 0
      .idea/laravel-idea.xml
  9. 8 0
      .idea/modules.xml
  10. 150 0
      .idea/php.xml
  11. 16 0
      .idea/phpspec.xml
  12. 11 0
      .idea/phpunit.xml
  13. 8 0
      .idea/sshConfigs.xml
  14. 6 0
      .idea/vcs.xml
  15. 14 0
      .idea/webServers.xml
  16. 137 0
      .idea/zh_food.iml
  17. 21 0
      app/Http/Controllers/Api/MemberController.php
  18. 68 0
      app/Http/Controllers/ApiController.php
  19. 61 0
      app/Http/Controllers/Traits/ApiResponseTrait.php
  20. 5 0
      app/Http/Kernel.php
  21. 86 0
      app/Http/Middleware/MemberAuth.php
  22. 43 0
      app/Models/Config.php
  23. 54 0
      app/Models/ErrorRecord.php
  24. 67 0
      app/Models/Goods.php
  25. 55 0
      app/Models/GoodsCategory.php
  26. 53 0
      app/Models/GoodsSku.php
  27. 53 0
      app/Models/GoodsSpec.php
  28. 53 0
      app/Models/Member.php
  29. 52 0
      app/Models/MemberLog.php
  30. 38 0
      app/Models/Region.php
  31. 43 22
      app/Models/User.php
  32. 20 5
      app/Providers/RouteServiceProvider.php
  33. 507 0
      app/Servers/CommonServer.php
  34. 43 0
      app/Servers/MemberLogsServer.php
  35. 170 0
      app/Servers/RedisDataServer.php
  36. 5 1
      composer.json
  37. 666 110
      composer.lock
  38. 2 0
      config/logging.php
  39. 10 0
      routes/api/member.php

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 116 - 0
.idea/blade.xml

@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="BladeInjectionConfiguration" default="false">
+    <directives>
+      <data directive="@append" />
+      <data directive="@auth" injection="true" prefix="&lt;?php&#10;if(auth()-&gt;guard(" suffix=")-&gt;check()): ?&gt;" />
+      <data directive="@aware" injection="true" prefix="&lt;?php $attributes = $attributes-&gt;exceptProps(" suffix="); ?&gt;" />
+      <data directive="@break" injection="true" prefix="&lt;?php&#10;if(" suffix=") break; ?&gt;" />
+      <data directive="@can" injection="true" prefix="&lt;?php&#10;if (app(\Illuminate\Contracts\Auth\Access\Gate::class)-&gt;check(" suffix=")): ?&gt;" />
+      <data directive="@canany" injection="true" prefix="&lt;?php&#10;if (app(\Illuminate\Contracts\Auth\Access\Gate::class)-&gt;any(" suffix=")): ?&gt;" />
+      <data directive="@cannot" injection="true" prefix="&lt;?php&#10;if (app(\Illuminate\Contracts\Auth\Access\Gate::class)-&gt;denies(" suffix=")): ?&gt;" />
+      <data directive="@case" injection="true" prefix="&lt;?php&#10;case (" suffix="): ?&gt;" />
+      <data directive="@checked" injection="true" prefix="&lt;?php&#10;if(" suffix="): echo 'checked'; endif; ?&gt;" />
+      <data directive="@choice" injection="true" prefix="&lt;?php&#10;echo app('translator')-&gt;choice(" suffix="); ?&gt;" />
+      <data directive="@class" injection="true" prefix="class=&quot;&lt;?php echo \Illuminate\Support\Arr::toCssClasses(" suffix=")?&gt;&quot;" />
+      <data directive="@component" injection="true" prefix="&lt;?php&#10;$__env-&gt;startComponent(" suffix="); ?&gt;" />
+      <data directive="@componentfirst" injection="true" prefix="&lt;?php&#10;$__env-&gt;startComponentFirst(" suffix="); ?&gt;" />
+      <data directive="@continue" injection="true" prefix="&lt;?php&#10;if(" suffix=") continue; ?&gt;" />
+      <data directive="@csrf" />
+      <data directive="@dd" injection="true" prefix="&lt;?php&#10;dd(" suffix="); ?&gt;" />
+      <data directive="@default" />
+      <data directive="@disabled" injection="true" prefix="&lt;?php&#10;if(" suffix="): echo 'disabled'; endif; ?&gt;" />
+      <data directive="@dump" injection="true" prefix="&lt;?php&#10;dump(" suffix="); ?&gt;" />
+      <data directive="@each" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;renderEach(" suffix="); ?&gt;" />
+      <data directive="@else" />
+      <data directive="@elseauth" injection="true" prefix="&lt;?php&#10;elseif(auth()-&gt;guard(" suffix=")-&gt;check()): ?&gt;" />
+      <data directive="@elsecan" injection="true" prefix="&lt;?php&#10;elseif (app(\Illuminate\Contracts\Auth\Access\Gate::class)-&gt;check(" suffix=")): ?&gt;" />
+      <data directive="@elsecanany" injection="true" prefix="&lt;?php&#10;elseif (app(\Illuminate\Contracts\Auth\Access\Gate::class)-&gt;any(" suffix=")): ?&gt;" />
+      <data directive="@elsecannot" injection="true" prefix="&lt;?php&#10;elseif (app(\Illuminate\Contracts\Auth\Access\Gate::class)-&gt;denies(" suffix=")): ?&gt;" />
+      <data directive="@elseguest" injection="true" prefix="&lt;?php&#10;elseif(auth()-&gt;guard(" suffix=")-&gt;guest()): ?&gt;" />
+      <data directive="@elseif" injection="true" prefix="&lt;?php&#10;elseif(" suffix="): ?&gt;" />
+      <data directive="@empty" injection="true" prefix="&lt;?php&#10;if(empty(" suffix=")): ?&gt;" />
+      <data directive="@endauth" />
+      <data directive="@endcan" />
+      <data directive="@endcanany" />
+      <data directive="@endcannot" />
+      <data directive="@endcomponent" />
+      <data directive="@endcomponentClass" />
+      <data directive="@endcomponentfirst" />
+      <data directive="@endempty" />
+      <data directive="@endenv" />
+      <data directive="@enderror" />
+      <data directive="@endfor" />
+      <data directive="@endforeach" />
+      <data directive="@endforelse" />
+      <data directive="@endfragment" />
+      <data directive="@endguest" />
+      <data directive="@endif" />
+      <data directive="@endisset" />
+      <data directive="@endlang" />
+      <data directive="@endonce" />
+      <data directive="@endphp" />
+      <data directive="@endprepend" />
+      <data directive="@endprependonce" />
+      <data directive="@endproduction" />
+      <data directive="@endpush" />
+      <data directive="@endpushif" />
+      <data directive="@endpushonce" />
+      <data directive="@endsection" />
+      <data directive="@endslot" />
+      <data directive="@endswitch" />
+      <data directive="@endunless" />
+      <data directive="@endverbatim" />
+      <data directive="@endwhile" />
+      <data directive="@env" injection="true" prefix="&lt;?php&#10;if(app()-&gt;environment(" suffix=")): ?&gt;" />
+      <data directive="@error" injection="true" prefix="&lt;?php&#10;$__errorArgs = [" suffix="];&#10;$__bag = $errors-&gt;getBag($__errorArgs[1] ?? 'default');&#10;if ($__bag-&gt;has($__errorArgs[0])) :&#10;if (isset($message)) { $__messageOriginal = $message; }&#10;$message = $__bag-&gt;first($__errorArgs[0]); ?&gt;" />
+      <data directive="@extends" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;make(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))-&gt;render(); ?&gt;" />
+      <data directive="@extendsfirst" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;first(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))-&gt;render(); ?&gt;" />
+      <data directive="@for" injection="true" prefix="&lt;?php&#10;for(" suffix="): ?&gt;" />
+      <data directive="@foreach" injection="true" prefix="&lt;?php&#10;foreach(" suffix="): ?&gt;" />
+      <data directive="@forelse" injection="true" prefix="&lt;?php&#10;foreach(" suffix="): ?&gt;" />
+      <data directive="@fragment" injection="true" prefix="&lt;?php&#10;$__env-&gt;startFragment(" suffix="); ?&gt;" />
+      <data directive="@guest" injection="true" prefix="&lt;?php&#10;if(auth()-&gt;guard(" suffix=")-&gt;guest()): ?&gt;" />
+      <data directive="@hasSection" injection="true" prefix="&lt;?php&#10;if (! empty(trim($__env-&gt;yieldContent(" suffix=")))): ?&gt;" />
+      <data directive="@if" injection="true" prefix="&lt;?php&#10;if(" suffix="): ?&gt;" />
+      <data directive="@include" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;make(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))-&gt;render(); ?&gt;" />
+      <data directive="@includeFirst" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;first(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))-&gt;render(); ?&gt;" />
+      <data directive="@includeUnless" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;renderUnless(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path'])); ?&gt;" />
+      <data directive="@includeWhen" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;renderWhen(" suffix=", \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path'])); ?&gt;" />
+      <data directive="@isset" injection="true" prefix="&lt;?php&#10;if(isset(" suffix=")): ?&gt;" />
+      <data directive="@js" injection="true" prefix="&lt;?php _bladeDirective(" suffix="); ?&gt;" />
+      <data directive="@json" injection="true" prefix="&lt;?php&#10;echo json_encode(" suffix=") ?&gt;" />
+      <data directive="@lang" injection="true" prefix="&lt;?php&#10;echo app('translator')-&gt;get(" suffix="); ?&gt;" />
+      <data directive="@method" injection="true" prefix="&lt;?php&#10;echo method_field(" suffix="); ?&gt;" />
+      <data directive="@once" />
+      <data directive="@overwrite" />
+      <data directive="@parent" />
+      <data directive="@php" injection="true" prefix="&lt;?php&#10;(" suffix="); ?&gt;" />
+      <data directive="@prepend" injection="true" prefix="&lt;?php&#10;$__env-&gt;startPrepend(" suffix="); ?&gt;" />
+      <data directive="@prependonce" injection="true" prefix="&lt;?php&#10;$___phpstorm_prepend_once_params = [" suffix="]; if (! $__env-&gt;hasRenderedOnce($___phpstorm_prepend_once_params[1])): $__env-&gt;markAsRenderedOnce($___phpstorm_prepend_once_params); $__env-&gt;startPrepend($___phpstorm_prepend_once_params[0]); ?&gt;" />
+      <data directive="@production" />
+      <data directive="@props" injection="true" prefix="&lt;?php $attributes = $attributes-&gt;exceptProps(" suffix="); ?&gt;" />
+      <data directive="@push" injection="true" prefix="&lt;?php&#10;$__env-&gt;startPush(" suffix="); ?&gt;" />
+      <data directive="@pushif" injection="true" prefix="&lt;?php&#10;$__pushif_args = explode(','," suffix=", 2); if({$__pushif_args[0]}): $__env-&gt;startPush({$__pushif_args[1]}); ?&gt;" />
+      <data directive="@pushonce" injection="true" prefix="&lt;?php&#10;$__php_storm_push_once_params = [" suffix="]; if (!$__env-&gt;hasRenderedOnce($__php_storm_push_once_params[1])): $__env-&gt;markAsRenderedOnce($__php_storm_push_once_params[1]); $__env-&gt;startPush($__php_storm_push_once_params[0]); ?&gt;" />
+      <data directive="@readonly" injection="true" prefix="&lt;?php&#10;if(" suffix="): echo 'readonly'; endif; ?&gt;" />
+      <data directive="@required" injection="true" prefix="&lt;?php&#10;if(" suffix="): echo 'required'; endif; ?&gt;" />
+      <data directive="@section" injection="true" prefix="&lt;?php&#10;$__env-&gt;startSection(" suffix="); ?&gt;" />
+      <data directive="@sectionMissing" injection="true" prefix="&lt;?php&#10;if (empty(trim($__env-&gt;yieldContent(" suffix=")))): ?&gt;" />
+      <data directive="@selected" injection="true" prefix="&lt;?php&#10;if(" suffix="): echo 'selected'; endif; ?&gt;" />
+      <data directive="@show" />
+      <data directive="@slot" injection="true" prefix="&lt;?php&#10;$__env-&gt;slot(" suffix="); ?&gt;" />
+      <data directive="@stack" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;yieldPushContent(" suffix="); ?&gt;" />
+      <data directive="@stop" />
+      <data directive="@style" injection="true" prefix="style=&quot;&lt;?php&#10;echo \Illuminate\Support\Arr::toCssStyles(" suffix=") ?&gt;&quot;" />
+      <data directive="@switch" injection="true" prefix="&lt;?php&#10;switch(" suffix="): ?&gt;" />
+      <data directive="@unless" injection="true" prefix="&lt;?php&#10;if (! (" suffix=")): ?&gt;" />
+      <data directive="@unset" injection="true" prefix="&lt;?php&#10;unset(" suffix="); ?&gt;" />
+      <data directive="@verbatim" />
+      <data directive="@vite" injection="true" prefix="&lt;?php&#10;$__vite_arguments = " suffix=" ?? '()'; echo app(Illuminate\Foundation\Vite::class){$__vite_arguments}; ?&gt;" />
+      <data directive="@vitereactrefresh" />
+      <data directive="@while" injection="true" prefix="&lt;?php&#10;while(" suffix="): ?&gt;" />
+      <data directive="@yield" injection="true" prefix="&lt;?php&#10;echo $__env-&gt;yieldContent(" suffix="); ?&gt;" />
+    </directives>
+  </component>
+</project>

+ 12 - 0
.idea/codeception.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Codeception">
+    <option name="configurations">
+      <list>
+        <Configuration>
+          <option name="path" value="$PROJECT_DIR$/tests" />
+        </Configuration>
+      </list>
+    </option>
+  </component>
+</project>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1503 - 0
.idea/commandlinetools/Laravel_2026_1_30_8_52.xml


+ 47 - 0
.idea/commandlinetools/schemas/frameworkDescriptionVersion1.1.4.xsd

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+  <xs:element name="framework" type="frameworkType"/>
+  <xs:complexType name="commandType">
+    <xs:all>
+      <xs:element type="xs:string" name="name" minOccurs="1" maxOccurs="1"/>
+      <xs:element type="xs:string" name="params" minOccurs="0" maxOccurs="1"/>
+      <xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
+      <xs:element type="optionsBeforeType" name="optionsBefore" minOccurs="0" maxOccurs="1"/>
+    </xs:all>
+  </xs:complexType>
+  <xs:complexType name="frameworkType">
+    <xs:sequence>
+      <xs:element type="xs:string" name="extraData" minOccurs="0" maxOccurs="1"/>
+      <xs:element type="commandType" name="command" maxOccurs="unbounded" minOccurs="0"/>
+      <xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
+    </xs:sequence>
+    <xs:attribute type="xs:string" name="name" use="required"/>
+    <xs:attribute type="xs:string" name="invoke" use="required"/>
+    <xs:attribute type="xs:string" name="alias" use="required"/>
+    <xs:attribute type="xs:boolean" name="enabled" use="required"/>
+    <xs:attribute type="xs:integer" name="version" use="required"/>
+    <xs:attribute type="xs:string" name="frameworkId" use="optional"/>
+  </xs:complexType>
+  <xs:complexType name="optionsBeforeType">
+    <xs:sequence>
+      <xs:element type="optionType" name="option" maxOccurs="unbounded" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="optionType">
+    <xs:sequence>
+      <xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
+    </xs:sequence>
+    <xs:attribute type="xs:string" name="name" use="required"/>
+    <xs:attribute type="xs:string" name="shortcut" use="optional"/>
+    <xs:attribute name="pattern" use="optional">
+      <xs:simpleType>
+        <xs:restriction base="xs:string">
+             <xs:enumeration value="space"/>
+             <xs:enumeration value="equals"/>
+             <xs:enumeration value="unknown"/>
+           </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
+  </xs:complexType>
+</xs:schema>

+ 19 - 0
.idea/deployment.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PublishConfigData" autoUpload="Always" serverName="zh_test_food" remoteFilesAllowedToDisappearOnAutoupload="false" confirmBeforeUploading="false">
+    <option name="confirmBeforeUploading" value="false" />
+    <serverData>
+      <paths name="zh_test_food">
+        <serverdata>
+          <mappings>
+            <mapping deploy="/" local="$PROJECT_DIR$" web="/" />
+          </mappings>
+          <excludedPaths>
+            <excludedPath local="true" path="$PROJECT_DIR$/.env" />
+          </excludedPaths>
+        </serverdata>
+      </paths>
+    </serverData>
+    <option name="myAutoUpload" value="ALWAYS" />
+  </component>
+</project>

+ 6 - 0
.idea/git_toolbox_blame.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GitToolBoxBlameSettings">
+    <option name="version" value="2" />
+  </component>
+</project>

+ 22 - 0
.idea/laravel-idea.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="InertiaPackage">
+    <option name="directoryPaths">
+      <list />
+    </option>
+  </component>
+  <component name="LaravelIdeaMainSettings">
+    <option name="codeGeneration">
+      <LaravelCodeGeneration>
+        <option name="generationStringSettings">
+          <map>
+            <entry key="createEloquentScope:namespace" value="Models\Scopes" />
+            <entry key="createModel:namespace" value="Models" />
+          </map>
+        </option>
+      </LaravelCodeGeneration>
+    </option>
+    <option name="frameworkFound" value="true" />
+    <option name="userClassName" value="\App\Models\User" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/zh_food.iml" filepath="$PROJECT_DIR$/.idea/zh_food.iml" />
+    </modules>
+  </component>
+</project>

+ 150 - 0
.idea/php.xml

@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MessDetectorOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PHPCSFixerOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PHPCodeSnifferOptionsConfiguration">
+    <option name="highlightLevel" value="WARNING" />
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PhpIncludePathManager">
+    <include_path>
+      <path value="$PROJECT_DIR$/vendor/symfony/process" />
+      <path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
+      <path value="$PROJECT_DIR$/vendor/fruitcake/laravel-cors" />
+      <path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
+      <path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/type" />
+      <path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
+      <path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
+      <path value="$PROJECT_DIR$/vendor/carbonphp/carbon-doctrine-types" />
+      <path value="$PROJECT_DIR$/vendor/fideloper/proxy" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/version" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/diff" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
+      <path value="$PROJECT_DIR$/vendor/sebastian/environment" />
+      <path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
+      <path value="$PROJECT_DIR$/vendor/swiftmailer/swiftmailer" />
+      <path value="$PROJECT_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
+      <path value="$PROJECT_DIR$/vendor/dragonmantank/cron-expression" />
+      <path value="$PROJECT_DIR$/vendor/fzaninotto/faker" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
+      <path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
+      <path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
+      <path value="$PROJECT_DIR$/vendor/composer" />
+      <path value="$PROJECT_DIR$/vendor/psr/clock" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-factory" />
+      <path value="$PROJECT_DIR$/vendor/psr/container" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-client" />
+      <path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
+      <path value="$PROJECT_DIR$/vendor/filp/whoops" />
+      <path value="$PROJECT_DIR$/vendor/opis/closure" />
+      <path value="$PROJECT_DIR$/vendor/voku/portable-ascii" />
+      <path value="$PROJECT_DIR$/vendor/asm89/stack-cors" />
+      <path value="$PROJECT_DIR$/vendor/psr/http-message" />
+      <path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
+      <path value="$PROJECT_DIR$/vendor/psr/log" />
+      <path value="$PROJECT_DIR$/vendor/psy/psysh" />
+      <path value="$PROJECT_DIR$/vendor/facade/flare-client-php" />
+      <path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" />
+      <path value="$PROJECT_DIR$/vendor/facade/ignition" />
+      <path value="$PROJECT_DIR$/vendor/league/config" />
+      <path value="$PROJECT_DIR$/vendor/brick/math" />
+      <path value="$PROJECT_DIR$/vendor/nette/schema" />
+      <path value="$PROJECT_DIR$/vendor/nette/utils" />
+      <path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
+      <path value="$PROJECT_DIR$/vendor/ramsey/collection" />
+      <path value="$PROJECT_DIR$/vendor/ramsey/uuid" />
+      <path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
+      <path value="$PROJECT_DIR$/vendor/dflydev/dot-access-data" />
+      <path value="$PROJECT_DIR$/vendor/league/commonmark" />
+      <path value="$PROJECT_DIR$/vendor/league/mime-type-detection" />
+      <path value="$PROJECT_DIR$/vendor/league/flysystem" />
+      <path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
+      <path value="$PROJECT_DIR$/vendor/mockery/mockery" />
+      <path value="$PROJECT_DIR$/vendor/monolog/monolog" />
+      <path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
+      <path value="$PROJECT_DIR$/vendor/phar-io/version" />
+      <path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
+      <path value="$PROJECT_DIR$/vendor/laravel/tinker" />
+      <path value="$PROJECT_DIR$/vendor/laravel/serializable-closure" />
+      <path value="$PROJECT_DIR$/vendor/laravel/framework" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
+      <path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
+      <path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
+      <path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
+      <path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
+      <path value="$PROJECT_DIR$/vendor/symfony/mime" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
+      <path value="$PROJECT_DIR$/vendor/symfony/finder" />
+      <path value="$PROJECT_DIR$/vendor/symfony/routing" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <path value="$PROJECT_DIR$/vendor/symfony/console" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-iconv" />
+      <path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
+      <path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
+      <path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
+      <path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
+      <path value="$PROJECT_DIR$/vendor/symfony/string" />
+      <path value="$PROJECT_DIR$/vendor/symfony/translation" />
+      <path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
+      <path value="$PROJECT_DIR$/vendor/symfony/polyfill-php81" />
+      <path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
+      <path value="$PROJECT_DIR$/vendor/adbario/php-dot-notation" />
+      <path value="$PROJECT_DIR$/vendor/clagiordano/weblibs-configmanager" />
+      <path value="$PROJECT_DIR$/vendor/alibabacloud/client" />
+      <path value="$PROJECT_DIR$/vendor/alibabacloud/sts" />
+      <path value="$PROJECT_DIR$/vendor/aliyuncs/oss-sdk-php" />
+      <path value="$PROJECT_DIR$/vendor/mtdowling/jmespath.php" />
+      <path value="$PROJECT_DIR$/vendor/ezyang/htmlpurifier" />
+      <path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
+      <path value="$PROJECT_DIR$/vendor/myclabs/php-enum" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/complex" />
+      <path value="$PROJECT_DIR$/vendor/markbaker/matrix" />
+      <path value="$PROJECT_DIR$/vendor/intervention/image" />
+      <path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" />
+    </include_path>
+  </component>
+  <component name="PhpProjectSharedConfiguration" php_language_level="7.3">
+    <option name="suggestChangeDefaultLanguageLevel" value="false" />
+  </component>
+  <component name="PhpStanOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+  <component name="PhpUnit">
+    <phpunit_settings>
+      <PhpUnitSettings configuration_file_path="$PROJECT_DIR$/phpunit.xml" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
+    </phpunit_settings>
+  </component>
+  <component name="PsalmOptionsConfiguration">
+    <option name="transferred" value="true" />
+  </component>
+</project>

+ 16 - 0
.idea/phpspec.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PHPSpec">
+    <suites>
+      <PhpSpecSuiteConfiguration>
+        <option name="myPath" value="$PROJECT_DIR$" />
+      </PhpSpecSuiteConfiguration>
+      <PhpSpecSuiteConfiguration>
+        <option name="myPath" value="$PROJECT_DIR$" />
+      </PhpSpecSuiteConfiguration>
+      <PhpSpecSuiteConfiguration>
+        <option name="myPath" value="$PROJECT_DIR$" />
+      </PhpSpecSuiteConfiguration>
+    </suites>
+  </component>
+</project>

+ 11 - 0
.idea/phpunit.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="PHPUnit">
+    <option name="directories">
+      <list>
+        <option value="$PROJECT_DIR$/tests/Unit" />
+        <option value="$PROJECT_DIR$/tests/Feature" />
+      </list>
+    </option>
+  </component>
+</project>

+ 8 - 0
.idea/sshConfigs.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="SshConfigs">
+    <configs>
+      <sshConfig authType="PASSWORD" host="139.9.209.98" id="d31b6390-9f92-4eff-a7a8-3b7f25d806ae" port="22" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" />
+    </configs>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 14 - 0
.idea/webServers.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="WebServers">
+    <option name="servers">
+      <webServer id="1e9c4838-0955-4e0a-81c3-01243f4dd75c" name="zh_test_food">
+        <fileTransfer rootFolder="/www/wwwroot/testfood.jhcs888.com/zh_food" accessType="SFTP" host="139.9.209.98" port="22" sshConfigId="d31b6390-9f92-4eff-a7a8-3b7f25d806ae" sshConfig="root@139.9.209.98:22 password">
+          <advancedOptions>
+            <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" />
+          </advancedOptions>
+        </fileTransfer>
+      </webServer>
+    </option>
+  </component>
+</project>

+ 137 - 0
.idea/zh_food.iml

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" packagePrefix="App\" />
+      <sourceFolder url="file://$MODULE_DIR$/database/factories" isTestSource="false" packagePrefix="Database\Factories\" />
+      <sourceFolder url="file://$MODULE_DIR$/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" />
+      <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/Feature" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/Unit" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/storage/app" />
+      <excludeFolder url="file://$MODULE_DIR$/storage/framework" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/asm89/stack-cors" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/brick/math" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/carbonphp/carbon-doctrine-types" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/dflydev/dot-access-data" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/dragonmantank/cron-expression" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/facade/flare-client-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/fideloper/proxy" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/fruitcake/laravel-cors" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/fzaninotto/faker" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/graham-campbell/result-type" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/hamcrest/hamcrest-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/laravel/framework" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/laravel/serializable-closure" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/laravel/tinker" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/league/commonmark" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/league/config" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/league/flysystem" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/league/mime-type-detection" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/mockery/mockery" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/monolog/monolog" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nesbot/carbon" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nette/schema" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nette/utils" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/nunomaduro/collision" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/opis/closure" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpoption/phpoption" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/event-dispatcher" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-client" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-factory" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psr/simple-cache" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/psy/psysh" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ramsey/collection" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ramsey/uuid" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/cli-parser" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/complexity" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/lines-of-code" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/swiftmailer/swiftmailer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/css-selector" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-kernel" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mime" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-iconv" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php73" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php81" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/routing" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/vlucas/phpdotenv" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/voku/portable-ascii" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/adbario/php-dot-notation" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/alibabacloud/client" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/alibabacloud/sts" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/aliyuncs/oss-sdk-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/clagiordano/weblibs-configmanager" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/ezyang/htmlpurifier" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/intervention/image" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/maennchen/zipstream-php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/markbaker/complex" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/markbaker/matrix" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/mtdowling/jmespath.php" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/php-enum" />
+      <excludeFolder url="file://$MODULE_DIR$/vendor/phpoffice/phpspreadsheet" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 21 - 0
app/Http/Controllers/Api/MemberController.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Http\Controllers\ApiController;
+
+/**
+ * 会员信息
+ */
+class MemberController extends ApiController
+{
+
+    /**
+     * 微信小程序注册登录
+     */
+    function appletLogin()
+    {
+        $code = request()->input('code');
+        $invite_code = request()->input('invite_code', '');
+    }
+}

+ 68 - 0
app/Http/Controllers/ApiController.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Controllers\Traits\ApiResponseTrait;
+use Illuminate\Foundation\Bus\DispatchesJobs;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+
+class ApiController
+{
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+    use ApiResponseTrait;
+
+    // 接口响应
+    /**
+     * 会员基本信息
+     * @var array
+     */
+    protected $member = null;
+
+    public function __construct()
+    {
+
+    }
+
+
+    /**
+     * 获取当前用户ID
+     * @return int|mixed
+     */
+    function getMemberId()
+    {
+        $member = request()->member;
+        return empty($member['id'])?0:$member['id'];
+    }
+
+    /**
+     * 获取当前用户昵称
+     * @return int|mixed
+     */
+    function getMemberName()
+    {
+        $member = request()->member;
+        return empty($member['nickname'])?'':$member['nickname'];
+    }
+
+    /**
+     * 获取当前用户头像
+     * @return int|mixed
+     */
+    function getMemberHeadImg()
+    {
+        $member = request()->member;
+        return empty($member['head_img'])?'':$member['head_img'];
+    }
+
+    /**
+     * 获取当前用户手机号
+     * @return mixed|string
+     */
+    function getMemberPhone()
+    {
+        $member = request()->member;
+        return empty($member['phone'])?'':$member['phone'];
+    }
+
+}

+ 61 - 0
app/Http/Controllers/Traits/ApiResponseTrait.php

@@ -0,0 +1,61 @@
+<?php
+
+
+namespace App\Http\Controllers\Traits;
+
+
+
+trait ApiResponseTrait
+{
+    /**
+     * @param array $data                       ## 返回数据
+     * @param string $msg                       ## 返回信息 如:auth.failed
+     * @param int $code                         ## 响应编码 1:成功 0:失败
+     * @param int $status                       ## HTTP响应状态 200:请求成功
+     * @param array $header                     ## 响应头
+     * @param int $options                      ## 其他信息
+     * @return \Illuminate\Http\JsonResponse
+     *
+     * 接口返回格式 | 成功
+     */
+    public function apiResponseSuccess( $msg = '',$data = [], $code = 1, $status = 200, $header = [], $options = 0)
+    {
+        $this->lang();
+        $msg=__($msg);
+        return response()->json([
+            'msg'   => $msg,
+            'data'  => empty($data) ? [] : $data,
+            'code'  => $code,
+        ], $status, $header, $options);
+    }
+
+    /**
+     * @param array $data                       ## 返回数据
+     * @param string $msg                       ## 返回信息 如:auth.failed
+     * @param int $code                         ## 响应编码 1:成功 0:失败
+     * @param int $status                       ## HTTP响应状态 200:请求成功
+     * @param array $header                     ## 响应头
+     * @param int $options                      ## 其他信息
+     * @return \Illuminate\Http\JsonResponse
+     *
+     * 接口返回格式 | 失败
+     */
+    public function apiResponseError( $msg = '',$data = [], $code = 0, $status = 200, $header = [], $options = 0)
+    {
+        $this->lang();
+        $msg=__($msg);
+        return response()->json([
+            'msg'   => $msg,
+            'data'  => empty($data) ? [] : $data,
+            'code'  => $code,
+        ], $status, $header, $options);
+    }
+
+    /**
+     * 双语设置
+     */
+    protected function lang()
+    {
+        app()->setLocale(request()->input('lang', 'zh'));
+    }
+}

+ 5 - 0
app/Http/Kernel.php

@@ -2,6 +2,7 @@
 
 namespace App\Http;
 
+use App\Http\Middleware\MemberAuth;
 use Illuminate\Foundation\Http\Kernel as HttpKernel;
 
 class Kernel extends HttpKernel
@@ -43,6 +44,10 @@ class Kernel extends HttpKernel
             'throttle:api',
             \Illuminate\Routing\Middleware\SubstituteBindings::class,
         ],
+
+        'api_verify'=>[
+            MemberAuth::class
+        ],
     ];
 
     /**

+ 86 - 0
app/Http/Middleware/MemberAuth.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Http\Middleware;
+
+
+use App\Models\Member;
+use App\Servers\MemberLogsServer;
+use App\Servers\RedisDataServer;
+use Closure;
+
+class MemberAuth
+{
+
+    /**
+     * Handle an incoming request.
+     *
+     * @param \Illuminate\Http\Request $request
+     * @param \Closure $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        //不需要验证的路由
+        $noAuth = [
+        ];
+
+//        echo '这里是请求穿越阶段,也就是请求处理前';
+        $clientRoute = request()->route()->getName();//获取当前路由
+        //获取token
+        $m_id = $request->input('m_id',0);
+        $token = $request->input('token');
+        if(empty($token)){
+            $token=$request->header('Authorization');
+        }
+        $redisServer = RedisDataServer::creatServer();
+
+        //该路由不需要验证
+        if (in_array($clientRoute,$noAuth)){
+            if( $token){
+                $member = $redisServer->getData( 'login_' . $m_id, 'json');
+                if (empty($member)) {
+                    $member = Member::where('id', $m_id)->where('is_del',0)->select(['id', 'phone', 'nickname','head_img', 'token_str'])->first();
+                }
+                //用户信息缓存30秒
+                if($member){
+                    $redisServer->setData('login_' . $m_id, $member, 'json', 30);
+                    $request->member = $member;
+                }else{
+                    $request->member = ['id'=>0];
+                }
+            }else{
+                $request->member = ['id'=>0];
+            }
+
+        }else{
+            if(empty($m_id) || empty($token)){
+                return response()->json(['code' => 401, 'msg' => '缺少认证信息']);
+            }
+            //获取当前用户
+            $member = $redisServer->getData( 'login_' . $m_id, 'json');
+            if (empty($member)) {
+                $member = Member::where('id', $m_id)->where('is_del',0)->select(['id', 'phone', 'nickname', 'token_str','head_img'])->first();
+
+                if(empty($member)){
+                    return response()->json(['code' => 401, 'msg' => '认证信息已过期']);
+                }
+                if ($member['token_str'] != $token) {
+                    return response()->json(['code' => 401, 'msg' => '认证信息已过期']);
+                }
+                //用户信息缓存
+                $redisServer->setData('login_' . $m_id, $member, 'json', 600);
+            }else{
+                if ($member['token_str'] != $token) {
+                    return response()->json(['code' => 401, 'msg' => '认证信息已过期']);
+                }
+            }
+
+            $request->member = $member;
+        }
+
+        //记录访问日志
+        MemberLogsServer::write($clientRoute);
+
+        return $next($request);
+    }
+}

+ 43 - 0
app/Models/Config.php

@@ -0,0 +1,43 @@
+<?php
+
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 系统配置表
+ */
+class Config extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'configs';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+}

+ 54 - 0
app/Models/ErrorRecord.php

@@ -0,0 +1,54 @@
+<?php
+
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 错误信息记录表
+ */
+class ErrorRecord extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'error_records';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+}

+ 67 - 0
app/Models/Goods.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 商家商品表
+ */
+class Goods extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'goods';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+    private $statusEnum=[
+        1=>'上架中',
+        2=>'已下架',
+        3=>'已售罄',
+    ];
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+    /**
+     * 序列化数据字典
+     */
+    function initializeModel(){
+        if($this->{'status'}!==null){
+            $this->{'status_str'}=empty($this->statusEnum[$this->{'status'}])?'无':$this->statusEnum[$this->{'status'}];
+        }
+    }
+}

+ 55 - 0
app/Models/GoodsCategory.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 商家商品分类
+ */
+class GoodsCategory extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'goods_category';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+
+}

+ 53 - 0
app/Models/GoodsSku.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 商家商品规格表
+ */
+class GoodsSku extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'goods_sku';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+}

+ 53 - 0
app/Models/GoodsSpec.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 商家商品规格表
+ */
+class GoodsSpec extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'goods_spec';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+}

+ 53 - 0
app/Models/Member.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 用户表
+ */
+class Member extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'member';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = [ 'id', 'updated_at', 'created_at'];
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+}

+ 52 - 0
app/Models/MemberLog.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 会员日志
+ */
+class MemberLog extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'member_logs';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+}

+ 38 - 0
app/Models/Region.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Models;
+
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
+
+class Region extends Model
+{
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'regions';
+
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected $primaryKey = 'id';
+
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public $timestamps = true;
+
+    /**
+     * 不能被批量赋值的属性
+     *
+     * @var array
+     */
+    protected $guarded = ['id', 'updated_at', 'created_at'];
+
+}

+ 43 - 22
app/Models/User.php

@@ -2,42 +2,63 @@
 
 namespace App\Models;
 
-use Illuminate\Contracts\Auth\MustVerifyEmail;
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Foundation\Auth\User as Authenticatable;
-use Illuminate\Notifications\Notifiable;
+use DateTimeInterface;
+use Illuminate\Database\Eloquent\Model;
 
-class User extends Authenticatable
+/**
+ * 系统员工表
+ */
+class User extends Model
 {
-    use HasFactory, Notifiable;
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected $table = 'users';
 
     /**
-     * The attributes that are mass assignable.
+     * The primary key associated with the table.
      *
-     * @var array
+     * @var string
      */
-    protected $fillable = [
-        'name',
-        'email',
-        'password',
-    ];
+    protected $primaryKey = 'id';
 
     /**
-     * The attributes that should be hidden for arrays.
+     * Indicates if the model should be timestamped.
      *
-     * @var array
+     * @var bool
      */
-    protected $hidden = [
-        'password',
-        'remember_token',
-    ];
+    public $timestamps = true;
 
     /**
-     * The attributes that should be cast to native types.
+     * 可以被批量赋值的属性。
      *
      * @var array
      */
-    protected $casts = [
-        'email_verified_at' => 'datetime',
+    protected $fillable = ['id','name','phone','password','encrypt','api_token','roles_id','status','is_del'];
+
+    private $statusEnum=[
+        1=>'正常',
+        2=>'关闭',
     ];
+    /**
+     * 为数组 / JSON 序列化准备日期。
+     *
+     * @param DateTimeInterface $date
+     * @return string
+     */
+    protected function serializeDate(DateTimeInterface $date)
+    {
+        return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
+    }
+
+    /**
+     * 序列化数据字典
+     */
+    function initializeModel(){
+        if($this->{'status'}!==null){
+            $this->{'status_str'}=empty($this->statusEnum[$this->{'status'}])?'无':$this->statusEnum[$this->{'status'}];
+        }
+    }
 }

+ 20 - 5
app/Providers/RouteServiceProvider.php

@@ -26,7 +26,7 @@ class RouteServiceProvider extends ServiceProvider
      *
      * @var string|null
      */
-    // protected $namespace = 'App\\Http\\Controllers';
+     protected $namespace = 'App\\Http\\Controllers';
 
     /**
      * Define your route model bindings, pattern filters, etc.
@@ -37,11 +37,9 @@ class RouteServiceProvider extends ServiceProvider
     {
         $this->configureRateLimiting();
 
+        $this->mapApiRoutes();
+
         $this->routes(function () {
-            Route::prefix('api')
-                ->middleware('api')
-                ->namespace($this->namespace)
-                ->group(base_path('routes/api.php'));
 
             Route::middleware('web')
                 ->namespace($this->namespace)
@@ -60,4 +58,21 @@ class RouteServiceProvider extends ServiceProvider
             return Limit::perMinute(60);
         });
     }
+
+
+    protected function mapApiRoutes()
+    {
+        Route::prefix('api')
+            ->middleware('api')
+            ->namespace($this->namespace)
+            ->group(base_path('routes/api.php'));
+//dd($this->namespace);
+        foreach ( glob(base_path('routes'.DIRECTORY_SEPARATOR.'api'.DIRECTORY_SEPARATOR).'*.php' ) as $fileName ) {
+            $fileName = basename( $fileName );
+            Route::middleware('api_verify')
+                ->namespace( $this->namespace."\\Api" )
+                ->prefix('api')
+                ->group( base_path('routes'.DIRECTORY_SEPARATOR.'api'.DIRECTORY_SEPARATOR."{$fileName}") );
+        }
+    }
 }

+ 507 - 0
app/Servers/CommonServer.php

@@ -0,0 +1,507 @@
+<?php
+
+
+namespace App\Servers;
+
+
+
+use AlibabaCloud\Client\AlibabaCloud;
+use AlibabaCloud\Client\Exception\ClientException;
+use AlibabaCloud\Sts\Sts;
+use App\Models\Config;
+use App\Models\ErrorRecord;
+use App\Models\Region;
+use Illuminate\Support\Facades\Redis;
+use OSS\Core\OssException;
+use OSS\Credentials\EnvironmentVariableCredentialsProvider;
+use OSS\Http\RequestCore_Exception;
+use OSS\OssClient;
+
+/**
+ * 公共服务方法
+ */
+class CommonServer
+{
+
+    /**
+     * 错误信息
+     * @var string
+     */
+    private $errorMsg = '';
+
+    static private $server = null;
+
+
+    private function __construct()
+    {
+
+    }
+
+    /**
+     * 创建对象
+     * @return CommonServer
+     */
+    static function creatServer()
+    {
+        if (empty(self::$server)) self::$server = new CommonServer();
+        return self::$server;
+    }
+
+
+    /**
+     * 创建文件夹
+     * @param $dir
+     * @return bool
+     */
+    function creatDir($dir)
+    {
+        if ($dir == '') return false;
+        if (!file_exists(public_path($dir))) {
+            mkdir(public_path($dir), 0777, true);
+            chmod(public_path($dir), 0777);
+        }
+        return true;
+    }
+
+    /**
+     * redis 滑动窗口节流阀
+     * @param $key
+     * @param $num //允许的请求次数
+     * @param $secs //时间段(秒)
+     * @return bool
+     */
+    function redisThrottler($key ,$num ,$secs){
+        try {
+            //获取当前时间戳
+            $nowTime=time();
+            //获取队列长度
+            $length=Redis::lLen($key);
+            //如果长度没到限制数量就通过
+            if($length<$num){
+                //当前请求的时间入队
+                Redis::lPush($key,$nowTime);
+                Redis::expire($key,$secs);
+                return true;
+            }
+            //队列满了,取出最早访问的时间
+            $startTime= Redis::lIndex($key,$length-1);
+            //计算当前时间和最早一次请求的时间差,如果在规定的时间范围,则不允许通过
+            if ($nowTime-$startTime <= $secs) {
+                return false;
+            } else {
+                //如果不在规定的时间范围,证明最早的请求过期,就去掉最早期的再把当前的请求入队
+                Redis::rPop($key);
+                Redis::lPush($key,$nowTime);
+                Redis::expire($key,$secs);
+            }
+            return true;
+        }catch (\Exception $e){
+            var_dump($e->getMessage());
+            return true;
+        }
+
+    }
+
+    /**
+     * 指定路由加锁
+     * @param $lock_key
+     * @param $lock_value
+     * @param $routeName
+     * @return bool
+     */
+    function lockSpecifyRoutes($lock_key,$lock_value,$routeName){
+        $routeArr=   [
+            'withdraw.withdraw',
+        ];
+        if(in_array($routeName,$routeArr)){
+            $lock = RedisDataServer::creatServer()->lockKey($lock_key,$lock_value,1000);
+            if(!$lock){//拿不到锁
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 获取数据库配置信息
+     * @param $key
+     * @return mixed
+     */
+    function getConfigValue($key)
+    {
+        return Config::where('key', $key)->value('value');
+    }
+
+    /**
+     * 生成订单编号
+     * @param $prefix
+     * @return string
+     */
+    function createOrderNo($prefix='')
+    {
+        return $prefix.date('YmdHi').substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8) . rand(100,999);
+    }
+
+    /**
+     * 生成唯一码
+     * @param $key
+     * @return string
+     */
+    function getOnlyCode($key)
+    {
+        $total_count = RedisDataServer::creatServer()->getData($key);
+        if (empty($total_count)){
+            $total_count = rand(100,300);
+
+            // 获取当前时间戳
+            $now = time();
+            // 获取今天结束的时间戳
+            $endOfDay = strtotime("tomorrow") - 1;
+            // 计算剩余时间(秒)
+            $secondsLeft = bcsub($endOfDay,$now,1);
+            RedisDataServer::creatServer()->setData($key,$total_count,'str',$secondsLeft);
+        }
+
+        RedisDataServer::creatServer()->setIncr($key);
+
+        return date('md') . $total_count;
+    }
+
+
+
+    /**
+     * @param $str
+     * @return array|string|string[]|null
+     */
+    function utf8_filter($str)
+    {
+
+        $pattern = '/[^\x{4e00}-\x{9fa5}\w]/u';
+        // 使用正则表达式替换为空字符串
+        $data = preg_replace($pattern, '', $str);
+        return $data;
+    }
+
+    /**
+     * 字符串去标签过滤及空格过滤
+     * @param $str_name
+     * @param $default
+     * @return string
+     */
+    function filtrationStr($str_name, $default = '')
+    {
+        $str = request()->input($str_name);
+        if (empty($str)) {
+            return $default;
+        };
+        if (is_string($str)){
+            $str = strip_tags($str);
+            $str = trim($str);
+        }elseif (is_array($str)){
+            $data = [];
+            foreach ($str as $value){
+                $value = strip_tags($value);
+                $data[] = trim($value);
+            }
+            $str = $data;
+        }else{
+            $str = json_encode($str);
+            $str = strip_tags($str);
+            $str = trim($str);
+            $str = json_decode($str, true);
+        }
+        return $str;
+    }
+
+    /**
+     * 手机号码验证
+     * @param $phone
+     * @return bool
+     */
+    function verifyPhone($phone)
+    {
+        if (empty($phone)) return false;
+        if (!preg_match('/^1[3-9]\d{9}$/', $phone)){
+            return false;
+        }
+        return true;
+    }
+
+//    /**
+//     * 获取阿里云sts临时权限 旧版alibabacloud/sdk包
+//     */
+//    function getAliSts()
+//    {
+//        $data = RedisDataServer::creatServer()->getData('sts_data');
+//        if ($data) {
+//            $data = json_decode($data, true);
+//        } else {
+//            $accessKeyId = env('ALI_OSS_ACCESS_ID');
+//            $accessSecret = env('ALI_OSS_ACCESS_KEY');
+//            AlibabaCloud::accessKeyClient($accessKeyId, $accessSecret)->regionId('cn-chengdu')->asDefaultClient();
+//            //设置参数,发起请求。
+//            try {
+//                $result = AlibabaCloud::rpc()
+//                    ->product('Sts')
+//                    ->scheme('https') // https | http
+//                    ->version('2015-04-01')
+//                    ->action('AssumeRole')
+//                    ->method('POST')
+//                    ->host('sts.aliyuncs.com')
+//                    ->options([
+//                        'query' => [
+//                            'RegionId' => "cn-chengdu",
+//                            'RoleArn' => "acs:ram::1816998012508375:role/ramosstest",
+//                            'RoleSessionName' => "js-oss-serve",
+//                            'DurationSeconds' => 900,
+//                        ],
+//                    ])
+//                    ->request();
+//                $result = $result->toArray();
+//                if (empty($result['Credentials'])) {
+//                    return ['code' => 0, 'msg' => '获取token信息失败'];
+//                }
+//                $data = $result['Credentials'];
+//                unset($data['Expiration']);
+//                RedisDataServer::creatServer()->setData('sts_data', $data, 'json', 800);
+//            } catch (ClientException $e) {
+//                return ['code' => 0, 'msg' => $e->getErrorMessage()];
+//            }
+//        }
+//        return ['code' => 1, 'msg' => '获取信息成功', 'data' => $data];
+//
+//    }
+
+    /**
+     * 获取阿里云sts临时权限 alibabacloud/sts包
+     */
+    function getAliSts()
+    {
+        $data = RedisDataServer::creatServer()->getData('sts_data');
+        if ($data) {
+            $data = json_decode($data, true);
+        } else {
+
+            // 配置你的AccessKeyId和AccessKeySecret
+            $accessKeyId = config('aliyun.oss.access_id');
+            $accessKeySecret = config('aliyun.oss.access_key');
+
+            AlibabaCloud::accessKeyClient($accessKeyId,$accessKeySecret)
+                ->regionId('cn-chengdu')
+                ->asDefaultClient();
+            try {
+                $request = Sts::v20150401()->assumeRole();
+                $result = $request
+                    ->withRoleArn("acs:ram::1816998012508375:role/ramosstest")
+                    ->withRoleSessionName("js-oss-serve")
+                    ->request();
+
+                $result = $result->toArray();
+                if (empty($result['Credentials'])) {
+                    return ['code' => 0, 'msg' => '获取token信息失败'];
+                }
+                $data = $result['Credentials'];
+                unset($data['Expiration']);
+
+                RedisDataServer::creatServer()->setData('sts_data', $data, 'json', 800);
+            } catch (ClientException $e) {
+                return ['code' => 0, 'msg' => $e->getErrorMessage()];
+            }
+        }
+
+        return ['code' => 1, 'msg' => '获取信息成功', 'data' => $data];
+    }
+
+    /**
+     * oss上传
+     */
+    function uploadAliOss($filePath,$path = 'images')
+    {
+
+        // 配置信息
+        $accessKeyId = config('aliyun.oss.access_id');
+        $accessSecret = config('aliyun.oss.access_key');
+        $endpoint = "oss-cn-chengdu.aliyuncs.com"; // 如 oss-cn-hangzhou.aliyuncs.com
+        $bucket= config('aliyun.oss.bucket'); // OSS中的存储空间名称
+
+        // 初始化
+        try {
+            $ossClient = new OssClient($accessKeyId, $accessSecret, $endpoint);
+
+            $upload_path = "files" . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . date('Ymd', time()) . DIRECTORY_SEPARATOR;
+
+            $extension = pathinfo($filePath, PATHINFO_EXTENSION);
+            $object = $upload_path . md5(uniqid() . time()) . $extension; // OSS中的文件路径和名称
+
+            // 上传文件
+            $ossClient->uploadFile($bucket, $object, $filePath);
+
+            return ['code' => 1, 'msg' => '上传成功','data'=>$object];
+        } catch (OssException $e) {
+            return ['code' => 0, 'msg' => $e->getMessage()];
+        }
+    }
+
+    /**
+     * 删除oss文件
+     * @param $filePath
+     * @return bool
+     * @throws RequestCore_Exception
+     */
+    function delAliOss($filePath)
+    {
+        // 配置信息
+        $accessKeyId = config('aliyun.oss.access_id');
+        $accessSecret = config('aliyun.oss.access_key');
+        $endpoint = "oss-cn-chengdu.aliyuncs.com"; // 如 oss-cn-hangzhou.aliyuncs.com
+        $bucket= config('aliyun.oss.bucket'); // OSS中的存储空间名称
+
+        try {
+            $ossClient = new OssClient($accessKeyId, $accessSecret, $endpoint);
+
+            // 删除文件
+            $ossClient->deleteObject($bucket, urldecode($filePath));
+            return true;
+        } catch (OssException $e) {
+            ErrorRecord::create(['msg' => '阿里云oss删除失败', 'data' => json_encode($filePath,JSON_UNESCAPED_UNICODE)]);
+            return false;
+        }
+    }
+
+    /**
+     * 获取城市名称
+     * @param $province_id
+     * @param $city_id
+     * @param $area_id
+     * @param $street_id
+     * @return string
+     */
+    function getCityName($province_id = 0, $city_id = 0, $area_id = 0, $street_id = 0)
+    {
+        $area_arr = [$province_id, $city_id, $area_id, $street_id];
+        $area_arr = array_filter($area_arr);
+        if ($area_arr) {
+            $region = Region::whereIn('id', $area_arr)->orderBy('id', 'asc')->pluck('name')->toArray();
+            $city_name = implode(' ', $region);
+        } else {
+            $city_name = '';
+        }
+
+        return $city_name;
+    }
+
+    /**
+     * 获取两个经纬度直接距离
+     * @param $lat1
+     * @param $lng1
+     * @param $lat2
+     * @param $lng2
+     * @return float
+     */
+    function getDistance($lat1, $lng1, $lat2, $lng2){
+
+        $lat1 = ($lat1 * pi() ) / 180;
+        $lng1 = ($lng1 * pi() ) / 180;
+
+        $lat2 = ($lat2 * pi() ) / 180;
+        $lng2 = ($lng2 * pi() ) / 180;
+
+        $calcLongitude = $lng2 - $lng1;
+        $calcLatitude = $lat2 - $lat1;
+        $dist = 2 * asin(sqrt(pow(sin($calcLatitude/2),2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude/2),2)));
+        $dist = $dist * 6378.137;
+        return round($dist, 2);
+    }
+
+
+    /**
+     * 获取真实IP
+     * @return mixed
+     */
+    function getClientIp()
+    {
+        $http_x_forwarded_for = request()->header('x-forwarded-for');
+        if (empty($http_x_forwarded_for)) {
+            return request()->getClientIp();
+        } else {
+            $http_x_forwarded_for = explode(',', $http_x_forwarded_for);
+            return $http_x_forwarded_for[0];
+        }
+    }
+
+    /**
+     * 截取字符串
+     * @param $string
+     * @param $limit
+     * @param $suffix
+     * @return mixed|string
+     */
+    function truncateChineseString($string, $limit = 100, $suffix = '...') {
+        if (mb_strlen($string, 'UTF-8') <= $limit) {
+            // 如果字符串长度没有超过限制,直接返回
+            return $string;
+        }
+
+        // 截取前 $limit 个汉字
+        $truncated = mb_substr($string, 0, $limit, 'UTF-8');
+
+        // 确保截取后的字符串是完整的汉字,不会被截断
+        // 如果最后一个字符不是汉字,则需要回溯到上一个汉字的位置
+//        $lastChar = mb_substr($truncated, -1, 1, 'UTF-8');
+//        if (preg_match('/[^\x{4e00}-\x{9fa5}]/u', $lastChar)) {
+//            // 最后一个字符不是汉字,回溯到上一个汉字
+//            $truncated = mb_substr($string, 0, mb_strrpos($truncated, mb_substr($string, 0, mb_strlen($truncated, 'UTF-8') - 1, 'UTF-8'), 'UTF-8'), 'UTF-8');
+//        }
+
+        // 添加省略号
+        return $truncated . $suffix;
+    }
+
+    /**
+     * 处理图片压缩
+     * @param $img
+     * @param $str
+     * @return string
+     */
+    function setImageCompress($img,$str)
+    {
+        //查找链接中?出现的位置
+        $find = strrpos($img ,'?');
+        if (!$find){//没有就直接拼接
+            return $img . '?' . $str;
+        }else{
+            $url = substr($img,0,$find);
+            return $url . '?' . $str;
+        }
+    }
+
+    /**
+     * 获取随机字符串
+     * @param int $length
+     * @param string $strPol
+     * @return string|null
+     */
+    function getRandChar($length = 6, $strPol = '')
+    {
+        if ($length <= 0) $length = 1;
+        $str = null;
+        if (empty($strPol)) $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
+        $max = strlen($strPol) - 1;
+        for ($i = 0; $i < $length; $i++) {
+            $str .= $strPol[rand(0, $max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
+        }
+        return $str;
+    }
+
+    /**
+     * 截取字符串
+     * @param $num
+     * @param $decimals
+     * @return string
+     */
+    function truncateDecimal($num, $decimals = 2) {
+        $factor = pow(10, $decimals);
+        $truncated = (int)($num * $factor) / $factor;
+        return number_format($truncated, $decimals, '.', '');
+    }
+}

+ 43 - 0
app/Servers/MemberLogsServer.php

@@ -0,0 +1,43 @@
+<?php
+
+
+namespace App\Servers;
+
+
+
+
+use App\Models\MemberLog;
+
+class MemberLogsServer
+{
+
+
+    /**
+     * 会员日志
+     */
+    static public function write($clientRoute,$msg='')
+    {
+        $routeAuth = [
+        ];
+
+//        if (!in_array($clientRoute,$routeAuth)){
+//            return true;
+//        }
+        $member = request()->member;
+        $m_id = empty($member['id'])?0:$member['id'];
+
+        $url = request()->url();
+        $data = request()->all();
+        $ip=CommonServer::creatServer()->getClientIp();
+        //广播弹幕-进入队列
+        return MemberLog::create(
+            [
+                'm_id' => $m_id,
+                'url' => $url,
+                'msg' => $msg,
+                'ip' => $ip,
+                'data' => http_build_query($data),
+            ]
+        );
+    }
+}

+ 170 - 0
app/Servers/RedisDataServer.php

@@ -0,0 +1,170 @@
+<?php
+
+
+namespace App\Servers;
+
+
+
+
+use Illuminate\Support\Facades\Redis;
+
+/**
+ * Redis服务
+ */
+class RedisDataServer
+{
+
+    /**
+     * 错误信息
+     * @var string
+     */
+    private $errorMsg = '';
+
+    static private $server = null;
+
+
+    private function __construct()
+    {
+
+    }
+
+    /**
+     * 创建对象
+     * @return RedisDataServer
+     */
+    static function creatServer()
+    {
+        if (empty(self::$server)) self::$server = new RedisDataServer();
+        return self::$server;
+    }
+
+    /**
+     * 获取随机数
+     * @return int
+     */
+    private function getRandom()
+    {
+        return mt_rand(1, 10);
+    }
+
+    /**
+     * 获取缓存数据
+     * @param $key
+     * @param string $type
+     * @return mixed
+     */
+    function getData($key, $type = 'str')
+    {
+
+        $value = Redis::get($key);
+        if (!empty($value) && $type == 'json') {
+            $value = json_decode($value, true);
+        }
+        return $value;
+    }
+
+    /**
+     * 设置缓存数据
+     * @param $key
+     * @param $value
+     * @param string $type
+     * @param int $time
+     * @param $random
+     */
+    function setData($key, $value, $type = 'str', $time = 10, $random = true)
+    {
+        if (!empty($value)) {
+            if ($type == 'json') {
+                $value = json_encode($value);
+            }
+            if ($time > 1 && $random) $time += $this->getRandom();
+            Redis::setex($key, $time, $value);
+        }
+
+    }
+
+    /**
+     * 删除Redis数据
+     * @param $key
+     */
+    function delData($key)
+    {
+        Redis::del($key);
+    }
+
+    /**
+     * 添加序号
+     * @param $key
+     * @param $num
+     * @return false|int
+     */
+    function addQueue($key, $num)
+    {
+        return Redis::lpush($key, ...$num);
+    }
+
+    function addOneQueue($key, $num)
+    {
+        return Redis::lpush($key, $num);
+    }
+
+    /**
+     * 弹出队列数据
+     * @param $key
+     * @return false
+     */
+    function getQueue($key)
+    {
+        $key_num = Redis::rpop($key);
+        if (empty($key_num)) $key_num = false;
+        return $key_num;
+    }
+
+    /**
+     *
+     * 获取队列数据长度
+     * @param $key
+     * @return false|int
+     */
+    function getQueueList($key)
+    {
+        return Redis::llen($key);
+    }
+
+    /**
+     * 设置自增
+     * @param $key
+     * @return void
+     */
+    function setIncr($key)
+    {
+        Redis::incr($key);
+    }
+
+    /**
+     * key加锁
+     * @param $key
+     * @param $value
+     * @param int $time
+     * @return mixed
+     */
+    function lockKey($key,$value,$time = 10){
+        return Redis::set($key, $value, 'px', $time, 'nx');//以毫秒为单位
+//        return Redis::set($key, $value, 'ex', $time, 'nx');//以秒为单位
+    }
+
+    /**
+     * 解锁
+     * @param $key
+     * @param $value
+     * @return mixed
+     */
+    function unLockKey($key, $value)
+    {
+        $res = $this->getData($key);
+
+        if ($res == $value) {
+            return Redis::del($key);
+        }
+    }
+}

+ 5 - 1
composer.json

@@ -13,7 +13,11 @@
         "fruitcake/laravel-cors": "^2.0",
         "guzzlehttp/guzzle": "^7.0.1",
         "laravel/framework": "^8.0",
-        "laravel/tinker": "^2.0"
+        "laravel/tinker": "^2.0",
+        "alibabacloud/sts": "^1.8",
+        "aliyuncs/oss-sdk-php": "^2.7",
+        "intervention/image": "^2.6",
+        "phpoffice/phpspreadsheet": "^1.29"
     },
     "require-dev": {
         "facade/ignition": "^2.3.6",

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 666 - 110
composer.lock


+ 2 - 0
config/logging.php

@@ -45,6 +45,7 @@ return [
             'driver' => 'single',
             'path' => storage_path('logs/laravel.log'),
             'level' => env('LOG_LEVEL', 'debug'),
+            'permission' => 0777, // ⚠️ 这里设置文件创建时的权限
         ],
 
         'daily' => [
@@ -52,6 +53,7 @@ return [
             'path' => storage_path('logs/laravel.log'),
             'level' => env('LOG_LEVEL', 'debug'),
             'days' => 14,
+            'permission' => 0777, // ⚠️ 这里设置文件创建时的权限
         ],
 
         'slack' => [

+ 10 - 0
routes/api/member.php

@@ -0,0 +1,10 @@
+<?php
+
+use Illuminate\Support\Facades\Route;
+
+
+
+Route::group(['domain' => env('APP_HOST_API'), 'prefix' => 'member'],function (){
+    Route::match(['get','post'],'appletLogin', 'MemberController@appletLogin')->name('member.appletLogin');//微信小程序注册登录
+
+});

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно