Przeglądaj źródła

组件添加 image 图片

ajun 4 lat temu
rodzic
commit
07e19b8b80

+ 27 - 9
app/Http/Controllers/PrintPartController.php

@@ -6,21 +6,25 @@ use App\Components\AsyncResponse;
 use App\Order;
 use App\PrintPart;
 use App\PrintTemplate;
+use App\Services\PrintPartService;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Http;
 
 class PrintPartController extends Controller
 {
     use AsyncResponse;
+
     public function index(Request $request)
     {
         $printParts = PrintPart::query()->paginate($request['paginate'] ?? 50);
-        return view('/maintenance/expressPrinting/part/index',compact('printParts'));
+        $imgPrintPart = app(PrintPartService::class)->getImagePart();
+        return view('/maintenance/expressPrinting/part/index', compact('printParts','imgPrintPart'));
     }
 
     public function create(Request $request)
     {
-        return view('/maintenance/expressPrinting/part/create');
+        $imgPrintPart = app(PrintPartService::class)->getImagePart();
+        return view('/maintenance/expressPrinting/part/create',compact('imgPrintPart'));
     }
 
     public function storeApi(Request $request): \Illuminate\Http\RedirectResponse
@@ -38,11 +42,25 @@ class PrintPartController extends Controller
 
     public function print(Request $request)
     {
-        $template = PrintTemplate::query()->where('name','test-快递单号打印')->first();
-        $items = Order::query()->whereIn('code',["SO190628000378","SO190628000347"])->with('packages')->get();
-        return view("maintenance.expressPrinting.print.index",compact("template",'items'));
+        $template = PrintTemplate::query()->where('name', 'test-快递单号打印')->first();
+        $items = Order::query()->whereIn('code', ["SO190628000378", "SO190628000347"])->with('packages')->get();
+        return view("maintenance.expressPrinting.print.index", compact("template", 'items'));
+    }
+
+    public function getImagesPartApi(PrintPartService $service)
+    {
+        return ['success' => true, 'data' => $service->getImagePart()];
     }
 
+    public function pushImagesPartApi(Request $request,PrintPartService $service)
+    {
+        if (is_null($request['name'])) return ['success' => false, 'message' => "文件名未命名"];
+        if (!$request->hasFile('file')) return ['success' => false, 'message' => '未找到上传文件'];
+        if (!$request->has('name')) return ['success' => false, 'message' => "文件名未命名"];
+        return $service->pushImagePart($request->file('file'),$request['name']);
+    }
+
+
     public function printTemplateApi(Request $request)
     {
         $file = $request->file("blob");
@@ -52,15 +70,15 @@ class PrintPartController extends Controller
 
         $content = [
             "type" => "print",
-            "aliasName"=>"admin",
-            "printerName"=>"admin123",
+            "aliasName" => "admin",
+            "printerName" => "admin123",
             "content" => $content
         ];
-        if(!$files)return Http::post("http://127.0.0.1:3000",$content);
+        if (!$files) return Http::post("http://127.0.0.1:3000", $content);
         $contents = [];
         foreach ($files as $item) {
             $contents[] = base64_encode($item->getContent());
         }
-        return Http::post("http://127.0.0.1:3000",['file'=>$content,'files'=>$contents]);
+        return Http::post("http://127.0.0.1:3000", ['file' => $content, 'files' => $contents]);
     }
 }

+ 42 - 0
app/Services/PrintPartService.php

@@ -5,6 +5,7 @@ namespace App\Services;
 use App\Traits\ModelSearchWay;
 use App\Traits\ServiceAppAop;
 use App\PrintPart;
+use Illuminate\Support\Facades\Storage;
 
 class PrintPartService
 {
@@ -12,4 +13,45 @@ class PrintPartService
     use ServiceAppAop;
     protected $modelClass = PrintPart::class;
 
+    public function getImagePart()
+    {
+        $printPart = PrintPart::query()->firstOrCreate(['name' => "PrintPart-Image"],['value' => json_encode(array(), JSON_UNESCAPED_UNICODE)]);
+
+        $printPart['values'] = json_decode($printPart['value'], JSON_UNESCAPED_UNICODE);
+
+        return $printPart;
+    }
+
+    public function pushImagePart($file,$fileName): array
+    {
+        $tempFile = $file->getRealPath();
+        if (!$file->isValid()) return ['success' => false, 'message' => '未找到上传文件'];
+//        if (!is_uploaded_file($tempFile)) return ['success' => false, 'message' => '获取文件错误'];
+        if ($file->getSize() > 5 * 1024 * 1024) return ['success' => false, 'message' => '文件不能大于5MB'];
+
+        $printPart = $this->getImagePart();
+        $is_exists = false;
+        foreach ($printPart['values'] as $values){
+            if ($values['name'] == $fileName){
+                $is_exists = true;
+                break;
+            }
+        }
+        if ($is_exists) return ['success' => true ,'message' => '文件名重复'];
+
+        $fileSuffix = '.'.$file->getClientOriginalExtension();
+
+        $dirPath = storage_path('app\public\files\print');
+
+        if (!file_exists($dirPath)) {
+            mkdir($dirPath);
+        }
+        $filePath = storage_path('app\public\files\print\\' . $fileName.$fileSuffix);
+        $result = move_uploaded_file($tempFile,$filePath);
+        if (!$result) ['success' => false , 'message' => '图片保存异常'];
+        $values = ['name' => $fileName, 'value' => Storage::url("print/".$fileName.$fileSuffix)];
+        PrintPart::query()->where('id',$printPart['id'])->update(['value' => json_encode($values,JSON_UNESCAPED_UNICODE)]);
+        return ['success' => true , 'data' =>  $this->getImagePart()];
+    }
+
 }

+ 199 - 96
resources/views/maintenance/expressPrinting/part/create.blade.php

@@ -16,7 +16,8 @@
                         </div>
                         <div class="form-group">
                             <label for=template-height>高</label>
-                            <input type="number" id="template-height" v-model="template.height" class="form form-control">
+                            <input type="number" id="template-height" v-model="template.height"
+                                   class="form form-control">
                         </div>
                         <div class="form-group">
                             <label for="template-border-type">边框类型</label>
@@ -26,7 +27,8 @@
                         </div>
                         <div class="form-group">
                             <label for="template-border-weight">边框大小</label>
-                            <input type="number" id="template-border-weight" v-model="template.borderWidth" class="form form-control">
+                            <input type="number" id="template-border-weight" v-model="template.borderWidth"
+                                   class="form form-control">
                         </div>
                     </div>
                     <div class="card-footer">
@@ -34,14 +36,25 @@
                     </div>
                 </div>
             </div>
-            <div class="col-6 justify-content-center align-items-center flex-fill" >
+            <div class="col-6 justify-content-center align-items-center flex-fill">
                 {{-- 模板展示--}}
                 <div v-if="template.type==='text'" :style="getStyle()">
-                    <span >@{{ template.text }}</span>
+                    <span>@{{ template.text }}</span>
                 </div>
-                {{-- 二维码展示 --}}
-                <svg v-show="template.type!=='text'" :style="{width:template.width,height:template.height}" id="barcodeDiv1">
+                {{-- 条纹码展示 --}}
+                <svg v-show="template.type === 'StripeCode'" :style="{width:template.width,height:template.height}"
+                     id="barcodeDiv">
                 </svg>
+
+                {{-- 二维码展示 --}}
+                <div v-show="template.type ==='QrCode'" :style="{width:template.width,height:template.height}"
+                     id="qrCodeDiv">
+                </div>
+
+                {{-- 图片展示 --}}
+                <div v-show="template.type ==='QrCode'" :style="{width:template.width,height:template.height}"
+                     id="ImageDiv">
+                </div>
             </div>
             <div class="col-3">
                 {{-- 属性 --}}
@@ -52,46 +65,59 @@
                     <div class="card-body">
                         <div class="form-group">
                             <label for="template-type">组件类型</label>
-                            <select class="form-control" v-model="template.type" @change="setContent">
+                            <select class="form-control" id="template-type" v-model="template.type" @change="setContent">
                                 <option v-for="type in types" :value="type.value">@{{ type.name }}</option>
                             </select>
                         </div>
-                        <div class="form-group">
-                            <label for="template-text">内容</label>
-                            <textarea id="template-text" class="form-text form-control" cols="5" rows="5" v-model="template.text"></textarea>
-                        </div>
-                        <div class="form-group">
-                            <label for="template-text-align">文本对齐方式</label>
-                            <select name="" id="template-text-align" v-model="template.justifyContent" class="form form-control">
-                                <option v-for="justifyContent in justifyContents" :value="justifyContent.value">@{{ justifyContent.name }}</option>
-                            </select>
-                        </div>
-                        <div class="form-group">
-                            <label for="template-text-align">文本垂直对齐</label>
-                            <select name="" id="template-text-align" v-model="template.alignItems" class="form form-control">
-                                <option v-for="alignItem in alignItems" :value="alignItem.value">@{{  alignItem.name }}</option>
-                            </select>
-                        </div>
-                        <div class="form-group">
-                            <label for="template-font-size">字体大小</label>
-                            <input type="text" id="template-font-size" v-model="template.fontSize" class="form form-control">
-                        </div>
-                        <div class="form-group">
-                            <label for="template-font-weight">字体宽</label>
-                            <select id="template-font-weight" v-model="template.fontWeight" class="form-control">
-                                <option v-for="fontWeight in fontWeights" :value="fontWeight.value" >@{{ fontWeight.name }}</option>
-                            </select>
+                        <div v-if="template.type === 'Image'">
+                            <button @click="showUploadModal" class="btn btn-sm btn-primary">上传文件</button>
                         </div>
+{{--                        <div class="form-group">--}}
+{{--                            <label for="template-text">内容</label>--}}
+{{--                            <textarea id="template-text" class="form-text form-control" cols="5" rows="5"--}}
+{{--                                      v-model="template.text"></textarea>--}}
+{{--                        </div>--}}
+{{--                        <div class="form-group">--}}
+{{--                            <label for="template-text-align">文本对齐方式</label>--}}
+{{--                            <select name="" id="template-text-align" v-model="template.justifyContent"--}}
+{{--                                    class="form form-control">--}}
+{{--                                <option v-for="justifyContent in justifyContents" :value="justifyContent.value">--}}
+{{--                                    @{{ justifyContent.name }}--}}
+{{--                                </option>--}}
+{{--                            </select>--}}
+{{--                        </div>--}}
+{{--                        <div class="form-group">--}}
+{{--                            <label for="template-text-align">文本垂直对齐</label>--}}
+{{--                            <select name="" id="template-text-align" v-model="template.alignItems"--}}
+{{--                                    class="form form-control">--}}
+{{--                                <option v-for="alignItem in alignItems" :value="alignItem.value">--}}
+{{--                                    @{{ alignItem.name }}--}}
+{{--                                </option>--}}
+{{--                            </select>--}}
+{{--                        </div>--}}
+{{--                        <div class="form-group">--}}
+{{--                            <label for="template-font-size">字体大小</label>--}}
+{{--                            <input type="text" id="template-font-size" v-model="template.fontSize"--}}
+{{--                                   class="form form-control">--}}
+{{--                        </div>--}}
+{{--                        <div class="form-group">--}}
+{{--                            <label for="template-font-weight">字体宽</label>--}}
+{{--                            <select id="template-font-weight" v-model="template.fontWeight" class="form-control">--}}
+{{--                                <option v-for="fontWeight in fontWeights" :value="fontWeight.value">--}}
+{{--                                    @{{ fontWeight.name }}--}}
+{{--                                </option>--}}
+{{--                            </select>--}}
+{{--                        </div>--}}
                     </div>
                 </div>
             </div>
         </div>
-        <div class="modal fade" id="saveModal" tabindex="-1"  aria-hidden="true">
-            <div class="modal-dialog">
+        <div class="modal fade" id="saveModal" tabindex="-1" aria-hidden="true">
+            <div class="modal-dialog modal-dialog-centered">
                 <div class="modal-content">
                     <div class="modal-header">
                         <h5 class="modal-title" id="saveModalLabel">保存组件</h5>
-                        <button type="button" class="close" data-dismiss="modal" aria-label="Close" >
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                             <span aria-hidden="true">&times;</span>
                         </button>
                     </div>
@@ -104,106 +130,183 @@
                         </form>
                     </div>
                     <div class="modal-footer">
-                        <button type="button" class="btn btn-secondary" data-dismiss="modal" >关闭</button>
+                        <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
                         <button type="button" class="btn btn-success" @click="create">保存</button>
                     </div>
                 </div>
             </div>
         </div>
+        <div v-if="template.type === 'Image'">
+            <template v-for="value in printImages.values">
+                <div class="list-group">
+                    @{{ value }}
+                </div>
+            </template>
+        </div>
+        <div class="modal" tabindex="-1" id="uploadFileModel">
+            <div class="modal-dialog modal-dialog-centered">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h5 class="modal-title">上传图片</h5>
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                            <span aria-hidden="true">&times;</span>
+                        </button>
+                    </div>
+                    <div class="modal-body">
+                        <div class="form-inline form-group">
+                            <label for="fileName" class="col-sm-3 col-form-label text-right ">图片名称</label>
+                            <input type="name"  class="form-control" id="fileName" placeholder="图片名">
+                        </div>
+
+                        <div class="form-inline form-group">
+                            <label for="uploadfile" class="col-sm-3 col-form-label text-right ">图片</label>
+                            <input type="file" id="uploadfile" class="form-control" name="image" accept="image/*" ref="upload">
+                        </div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                        <button type="button" class="btn btn-primary" @click="pushImage">上传</button>
+                    </div>
+                </div>
+            </div>
+        </div>
     </div>
+
 @endsection
 
 @section('lastScript')
     <script type="text/javascript" src="{{mix('js/utilities/barcode.js')}}"></script>
+    <script type="text/javascript" src="{{mix('/js/utilities/qrcode.js')}}"></script>
 
     <script>
         let vue = new Vue({
-            el:"#create-print-part",
-            data:{
-                printPart:{name:'',value:''},
-                template:{
-                    type:'text',
-                    width:200,
-                    height:100,
-                    borderStyle:'solid',
-                    borderWidth:1,
-                    fontSize:12,
-                    text:'',
-                    fontWeight:'normal',   //normal lighter bold
-                    justifyContent:'',     //文字水平对齐方式
-                    alignItems:'center',         //文字垂直对齐
+            el: "#create-print-part",
+            data: {
+                printPart: {name: '', value: ''},
+                printImages:{!! $imgPrintPart->toJson() !!},
+                template: {
+                    type: 'text',
+                    width: 200,
+                    height: 100,
+                    borderStyle: 'solid',
+                    borderWidth: 1,
+                    fontSize: 12,
+                    text: '',
+                    fontWeight: 'normal',   //normal lighter bold
+                    justifyContent: '',     //文字水平对齐方式
+                    alignItems: 'center',         //文字垂直对齐
                 },
-                types:[
-                    {name:"文本框",value:"text"},
-                    {name:"条纹码",value:"StripeCode"},
-                    {name:"二维码",value:"QrCode"},
-                    {name:"图片",value:"Image"},
+                types: [
+                    {name: "文本框", value: "text"},
+                    {name: "条纹码", value: "StripeCode"},
+                    {name: "二维码", value: "QrCode"},
+                    {name: "图片", value: "Image"},
                 ],
-                fontWeights:[
-                    {name:"正常",value:"normal"},
-                    {name:"细体",value:"lighter"},
-                    {name:"粗体",value:"bold"},
+                fontWeights: [
+                    {name: "正常", value: "normal"},
+                    {name: "细体", value: "lighter"},
+                    {name: "粗体", value: "bold"},
                 ],
-                justifyContents:[
-                    {name:"左对齐",value:""},
-                    {name:"居中",value:"center"},
-                    {name:"右对齐",value:"flex-end"},
+                justifyContents: [
+                    {name: "左对齐", value: ""},
+                    {name: "居中", value: "center"},
+                    {name: "右对齐", value: "flex-end"},
                 ],
-                alignItems:[
-                    {name:"顶部",value:""},
-                    {name:"居中",value:"center"},
-                    {name:"底部",value:"flex-end"},
+                alignItems: [
+                    {name: "顶部", value: ""},
+                    {name: "居中", value: "center"},
+                    {name: "底部", value: "flex-end"},
                 ],
-                borderStyles:[
-                    {name:"默认边框",value:"solid"},
-                    {name:"无边框",value:"none"},
-                    {name:"虚线边框",value:"dashed"},
+                borderStyles: [
+                    {name: "默认边框", value: "solid"},
+                    {name: "无边框", value: "none"},
+                    {name: "虚线边框", value: "dashed"},
                 ]
             },
             mounted() {
                 $("#create-print-part").removeClass('d-none');
             },
-            methods:{
-                show(){
+            methods: {
+                show() {
                     $('#saveModal').modal('show');
                 },
-                getStyle(){
+                showUploadModal(){
+                    $('#uploadFileModel').modal('show');
+                },
+                getStyle() {
                     return {
-                        'display':'flex',
-                        'width':this.template.width+'px',
-                        'height':this.template.height+'px',
-                        'border-style':this.template.borderStyle,
-                        'border-width':this.template.borderWidth+'px',
-                        'font-size':this.template.fontSize+'px',
-                        'font-weight':this.template.fontWeight,
-                        'justify-content':this.template.justifyContent,
-                        'align-items':this.template.alignItems,
+                        'display': 'flex',
+                        'width': this.template.width + 'px',
+                        'height': this.template.height + 'px',
+                        'border-style': this.template.borderStyle,
+                        'border-width': this.template.borderWidth + 'px',
+                        'font-size': this.template.fontSize + 'px',
+                        'font-weight': this.template.fontWeight,
+                        'justify-content': this.template.justifyContent,
+                        'align-items': this.template.alignItems,
                     };
                 },
-                create(){
+                create() {
                     tempTip.setDuration(3000);
                     tempTip.setIndex(2000);
                     let value = JSON.stringify(this.template);
-                    let data = {name:this.printPart.name,value:value};
-                    window.axios.post('{{url('apiLocal/maintenance/expressPrinting/part/create')}}',data).then(res=>{
-                        if(res.data.success){
+                    let data = {name: this.printPart.name, value: value};
+                    window.axios.post('{{url('apiLocal/maintenance/expressPrinting/part/create')}}', data).then(res => {
+                        if (res.data.success) {
                             tempTip.showSuccess(res.data.data);
                             $('#saveModal').modal('hide');
                             return;
                         }
                         tempTip.show(res.data.message);
+                    }).catch(err => {
+                        tempTip.show('网络异常:' + err);
+                    });
+                },
+                setContent() {
+                    if (this.template.type === "text") return;
+
+                    if (this.template.type === "StripeCode") {
+                        let div = $("#barcodeDiv");
+                        this.template.borderStyle = 'none';
+                        window.setBarcode("0123456789", "#barcodeDiv1", 2, 50, true)
+                        this.template.width = div.width();
+                        this.template.height = div.height();
+                    } else if (this.template.type === "QrCode") {
+                        $("#qrCodeDiv").html("");
+                        new QRCode(document.getElementById("qrCodeDiv"), {
+                            text: "占位二维码",
+                            width: 128,
+                            height: 128,
+                            colorDark: "#000000",
+                            colorLight: "#fff",
+                            correctLevel: QRCode.CorrectLevel.H,
+                        });
+                    } else if (this.template.type === "Image") {
+                        $("#qrCodeDiv").html("#ImageDiv");
+                    }
+                },
+                pushImage(){
+                    let url = '{{url("apiLocal/maintenance/expressPrinting/part/pushImage")}}'
+                    let data = new FormData();
+                    data.set("name",$("#fileName").val());
+                    let file= this.$refs.upload.files[0];
+                    data.set("file",file);
+                    window.tempTip.setIndex(2000);
+                    window.axios.post(url,data,{
+                        'Content-Type': 'multipart/form-data'
+                    }).then(res=>{
+                        if(res.data.success){
+                            window.tempTip.showSuccess("文件添加成功");
+                            $('#uploadFileModel').modal('hide');
+                            return
+                        }
+                        window.tempTip.show(res.data.message);
                     }).catch(err=>{
-                        tempTip.show('网络异常:'+err);
+                        window.tempTip.show(err)
                     });
+
                 },
-                setContent(){
-                    if(this.template.type === "text")return;
-                    this.template.borderStyle = 'none';
-                    let div = $("#barcodeDiv1");
-                    window.setBarcode("0123456789","#barcodeDiv1",2,50,true)
-                    this.template.width = div.width();
-                    this.template.height = div.height();
-                }
+
             }
         });
     </script>

+ 2 - 0
routes/apiLocal.php

@@ -131,6 +131,8 @@ Route::group(['prefix'=>'maintenance'],function (){
             Route::post('create','PrintPartController@storeApi');
             Route::post('destroy','PrintPartController@destroyApi');
             Route::post('printTemplate','PrintPartController@printTemplateApi');
+            Route::get('imagePart','PrintPartController@getImagesPartApi');
+            Route::post('pushImage','PrintPartController@pushImagesPartApi');
         });
         Route::group(['prefix'=>'template'],function(){
             Route::post('create','PrintTemplateController@storeApi');

+ 21 - 0
tests/Unit/BaseTest.php

@@ -1,5 +1,7 @@
 <?php
 
+use Illuminate\Http\UploadedFile;
+use Illuminate\Support\Facades\Storage;
 use Tests\TestCase;
 
 class BaseTest extends TestCase
@@ -14,4 +16,23 @@ class BaseTest extends TestCase
         dump(self::CONSTANT);
         $this->assertTrue(true);
     }
+
+    public function testPrintPart(){
+        $service = app(\App\Services\PrintPartService::class);
+        $item = $service->getImagePart();
+        dd($item);
+    }
+
+    public function testPushPartiImg()
+    {
+        Storage::fake('avatars');
+
+        $file = UploadedFile::fake()->image('avatar.jpg');
+        $response = $this->json('POST', 'apiLocal/maintenance/expressPrinting/part/pushImage', [
+            'name' => 'SF',
+            'file' => $file,
+        ]);
+
+        dd($response);
+    }
 }