You've already forked lubo_comment_query
							
							简易输入提示
This commit is contained in:
		| @@ -59,4 +59,12 @@ class ProgramAppendConstructController extends BaseController | ||||
|         ])); | ||||
|     } | ||||
| 
 | ||||
|     public function from_list(Request $request) { | ||||
|         $query = ProgramAppends::query()->groupBy("from")->select("from")->selectRaw("count(1) as total_count")->orderByDesc("total_count"); | ||||
|         if ($request->has("value")) { | ||||
|             $keyword = $request->get("value"); | ||||
|             $query->where("from", "like", "%{$keyword}%"); | ||||
|         } | ||||
|         return $query->get()->toArray(); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										2
									
								
								public/js/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/js/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1,3 @@ | ||||
| *.js | ||||
| *.js.LICENSE.txt | ||||
|  | ||||
|   | ||||
							
								
								
									
										39
									
								
								resources/css/vendor/picomplete/picomplete.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								resources/css/vendor/picomplete/picomplete.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| .picomplete { | ||||
|     position: relative; | ||||
|     display: inline-block; | ||||
| } | ||||
| 
 | ||||
| .picomplete-items { | ||||
|     position: absolute; | ||||
|     border: 1px solid #d4d4d4; | ||||
|     border-bottom: none; | ||||
|     border-top: none; | ||||
|     z-index: 99; | ||||
| 
 | ||||
|     overflow-y: scroll; | ||||
|     max-height: 185px; | ||||
|     scrollbar-width: thin !important; | ||||
| } | ||||
| 
 | ||||
| .picomplete-items div { | ||||
|     padding: 3px 10px 3px 10px; | ||||
|     cursor: pointer; | ||||
|     background-color: #fff; | ||||
|     border-bottom: 1px solid #d4d4d4; | ||||
| } | ||||
| 
 | ||||
| .picomplete-items div:hover { | ||||
|     background-color: #e9e9e9; | ||||
| } | ||||
| 
 | ||||
| .picomplete-items::-webkit-scrollbar { | ||||
|     width: 2px; | ||||
| } | ||||
| 
 | ||||
| .picomplete-items::-webkit-scrollbar-track { | ||||
|     background: whitesmoke; | ||||
| } | ||||
| 
 | ||||
| .picomplete-items::-webkit-scrollbar-thumb { | ||||
|     background: grey; | ||||
| } | ||||
							
								
								
									
										19
									
								
								resources/js/component/from_select.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/js/component/from_select.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| import PickleComplate from "../vendor/picomplete/picomplete"; | ||||
|  | ||||
| (function () { | ||||
|     new PickleComplate({ | ||||
|         request: { | ||||
|             url: '/programs/construct/append/from_list?', | ||||
|             type: 'GET', | ||||
|             value: 'from', | ||||
|             text: 'from', | ||||
|         }, | ||||
|         config: { | ||||
|             type: 'server', | ||||
|             target: '#from_select', | ||||
|             clickCallback: (target, node) => { | ||||
|                 target.value = node.value; | ||||
|             }, | ||||
|         }, | ||||
|     }) | ||||
| })() | ||||
							
								
								
									
										186
									
								
								resources/js/vendor/picomplete/picomplete.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								resources/js/vendor/picomplete/picomplete.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | ||||
| export default class PickleComplate { | ||||
|     /** | ||||
|      *  | ||||
|      * @param {object} obj as tree object  | ||||
|      */ | ||||
|     constructor(obj = null) { | ||||
|         //set config | ||||
|         this.config = obj.config; | ||||
|         //set fetch parameters | ||||
|         this.req_params = obj.request; | ||||
|         //target element | ||||
|         this.element = null; | ||||
|         //static data  | ||||
|         this.container = obj.data; | ||||
|         //list div element | ||||
|         this.sug_div = null; | ||||
|  | ||||
|         if(this.config.reqCallback === undefined) this.config.reqCallback = null; | ||||
|         if(this.config.changeCallback === undefined) this.config.changeCallback = null; | ||||
|  | ||||
|  | ||||
|         //start events | ||||
|         this.staticEvents(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * this method will set events | ||||
|      */ | ||||
|     staticEvents() { | ||||
|         // key up event | ||||
|         document.querySelectorAll(this.config.target+' input').forEach(e => { | ||||
|             e.addEventListener('keyup', el => { | ||||
|                 if(this.config.changeCallback !== undefined && this.config.changeCallback!== null) this.config.changeCallback(el.target); | ||||
|                 if(el.target.value.trim().length>0){ | ||||
|                     this.element = el.target; | ||||
|                     this.closeAllLists(); | ||||
|                     //if anything is match show list | ||||
|                     setTimeout(() => { | ||||
|                         this.getSuggests(el.target); | ||||
|                     }, 30); | ||||
|                 }else{ | ||||
|                     this.closeAllLists(); | ||||
|                 } | ||||
|  | ||||
|                 if(this.config.changeCallback != null) this.config.changeCallback(el,el.target.value); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         //close all lists | ||||
|         document.addEventListener("click", e => { | ||||
|             //close all lists | ||||
|             this.closeAllLists(); | ||||
|         }); | ||||
|  | ||||
|         //listen item clicks | ||||
|         document.querySelectorAll(this.config.target).forEach(e => { | ||||
|             e.addEventListener('click', el => { | ||||
|                 if(el.target.classList.contains('picomplete-item')){ | ||||
|                     if(this.config.clickCallback !== undefined && this.config.clickCallback !== null){ | ||||
|                         //send target element and node data | ||||
|                         this.config.clickCallback(this.element,this.container[el.target.getAttribute('data-index')]) | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     //#region event transactions | ||||
|     /** | ||||
|      * this method will close all lists | ||||
|      */ | ||||
|     async closeAllLists() { | ||||
|         /*close all autocomplete lists in the document*/ | ||||
|         let elms = document.querySelectorAll('.picomplete-items'); | ||||
|         for (let i = 0; i < elms.length; i++) { | ||||
|             elms[i].parentNode.removeChild(elms[i]); | ||||
|         } | ||||
|         this.sug_div = null; | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     async getSuggests(el) { | ||||
|          | ||||
|         //check container type | ||||
|         if(this.config.type === 'server'){ | ||||
|             await this.getData(el.value.toLowerCase()); | ||||
|         } | ||||
|         //for each item in container | ||||
|         if(this.container.length > 0){ | ||||
|             //first create div element for suggest | ||||
|             this.sug_div = document.createElement('DIV'); | ||||
|             this.sug_div.classList.add('picomplete-items'); | ||||
|             for (let i = 0; i < this.container.length; i++) { | ||||
|                 if (this.container[i].text.toLowerCase().includes(el.value.toLowerCase()) || this.container[i].value.toLowerCase().includes(el.value.toLowerCase())) { | ||||
|                     //create list item | ||||
|                     let item = document.createElement('DIV'); | ||||
|                     //set class | ||||
|                     item.classList.add('picomplete-item'); | ||||
|                     //set value | ||||
|                     item.setAttribute('data-value',this.container[i].value); | ||||
|                     //set value | ||||
|                     item.setAttribute('data-index',i); | ||||
|                     //set text | ||||
|                     item.innerHTML = this.container[i].text; | ||||
|                     //add item to list | ||||
|                     this.sug_div.appendChild(item); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         //add list to input  | ||||
|         if(this.sug_div !== null) this.element.parentNode.appendChild(this.sug_div); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * this method will send request to given parameters and return list of results | ||||
|      * @param {string} value  | ||||
|      */ | ||||
|     async getData(value){ | ||||
|         //define if parameters is not defined | ||||
|         if(this.req_params.params===undefined){ | ||||
|             this.req_params.params = {}; | ||||
|         } | ||||
|         //set value to params | ||||
|         this.req_params.params.value = value; | ||||
|         await this.request({ | ||||
|             method: this.req_params.type, | ||||
|             url: this.req_params.url, | ||||
|             data:this.req_params.params | ||||
|         },this.config.reqCallback).then(rsp => { | ||||
|             this.container = []; | ||||
|             if(rsp.length>0){ | ||||
|                 for (let i = 0; i <rsp.length; i++) { | ||||
|                     this.container.push({ | ||||
|                         value : rsp[i][this.req_params.value], | ||||
|                         text : rsp[i][this.req_params.text], | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     //#endregion | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * system request method | ||||
|      * @param {json object} rqs  | ||||
|      */ | ||||
|      async request(rqs, reqCallback = null) { | ||||
|         let fD = new FormData(); | ||||
|         let rsp; | ||||
|         const url_params = []; | ||||
|         const op = { | ||||
|             method: rqs['method'], | ||||
|         }; | ||||
|  | ||||
|         if(reqCallback !== null) rqs['data'] = reqCallback(rqs['data']); | ||||
|  | ||||
|         if (rqs['method'] !== 'GET') { | ||||
|             op.body = fD; | ||||
|             for (let key in rqs['data']) { | ||||
|                 fD.append(key, rqs['data'][key]); | ||||
|             } | ||||
|         }else{ | ||||
|             if(!rqs['url'].includes("&")){ | ||||
|                 rqs['url']+='&'; | ||||
|             } | ||||
|             for (let key in rqs['data']) { | ||||
|                 url_params.push(key+'='+rqs['data'][key]); | ||||
|             } | ||||
|             rqs['url']+=url_params.join('&'); | ||||
|         } | ||||
|  | ||||
|         rsp = await fetch(rqs['url'], op); | ||||
|  | ||||
|         return await rsp.json() | ||||
|     } | ||||
| } | ||||
| @@ -4,6 +4,8 @@ | ||||
|     <title>录播节目点播信息修改</title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <link href="{{ mix('/css/app.css') }}" rel="stylesheet"/> | ||||
|     <script src="{{ mix('/js/manifest.js') }}" rel="script"></script> | ||||
|     <link href="{{ asset('/css/vendor/picomplete/picomplete.css') }}" rel="stylesheet"/> | ||||
| </head> | ||||
| <body> | ||||
| @include("common.header") | ||||
| @@ -28,7 +30,7 @@ | ||||
|         追加内容(点播可不填) | ||||
|         <input class="form-input border-0 border-b-2 w-full" type="text" name="name" value="{{ old('name', $append->name) }}"> | ||||
|     </label> | ||||
|     <label class="block my-2"> | ||||
|     <label class="block my-2" id="from_select"> | ||||
|         点播老板 | ||||
|         <input class="form-input border-0 border-b-2 w-full" type="text" name="from" value="{{ old('from', $append->from) }}"> | ||||
|     </label> | ||||
| @@ -66,4 +68,5 @@ | ||||
| </form> | ||||
| @include("common.footer") | ||||
| </body> | ||||
| <script src="{{ mix('/js/component/from_select.js') }}" rel="script"></script> | ||||
| </html> | ||||
|   | ||||
| @@ -55,6 +55,7 @@ Route::prefix("/programs/construct")->middleware("auth:web")->group(function (Ro | ||||
|     $router->get('/{program}/append', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","index"])->name("program.construct.append.list"); | ||||
|     $router->get('/{program}/append/add', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","add"])->name("program.construct.append.add"); | ||||
|     $router->post('/{program}/append/add', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","create"])->name("program.construct.append.create"); | ||||
|     $router->get('/append/from_list', ["\\App\\Http\\Controllers\\ProgramAppendConstructController", "from_list"])->name("program.construct.append.from_list"); | ||||
|     $router->get('/append/{append}', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","edit"])->name("program.construct.append.edit"); | ||||
|     $router->post('/append/{append}', ["\\App\\Http\\Controllers\\ProgramAppendConstructController","submit"])->name("program.construct.append.submit"); | ||||
| }); | ||||
|   | ||||
| @@ -11,14 +11,19 @@ const mix = require('laravel-mix'); | ||||
|  | | ||||
|  */ | ||||
|  | ||||
| mix.js('resources/js/app.js', 'public/js') | ||||
| mix | ||||
|     .js('resources/js/component/from_select.js', 'public/js/component') | ||||
|     .js('resources/js/app.js', 'public/js') | ||||
|     .extract(['axios', 'lodash']) | ||||
|     .js('resources/js/webauthn.js', 'public/js') | ||||
|     .copy('resources/css/vendor', 'public/css/vendor') | ||||
|     .postCss('resources/css/app.css', 'public/css', [ | ||||
|         require('tailwindcss') | ||||
|     ]) | ||||
|     .disableNotifications(); | ||||
| if (mix.inProduction()) { | ||||
|     mix.version(); | ||||
| } else { | ||||
|     mix.sourceMaps() | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user