简易输入提示
This commit is contained in:
parent
5f50dc8f2e
commit
9609aef740
@ -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
|
||||||
|
*.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>
|
<title>录播节目点播信息修改</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link href="{{ mix('/css/app.css') }}" rel="stylesheet"/>
|
<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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@include("common.header")
|
@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) }}">
|
<input class="form-input border-0 border-b-2 w-full" type="text" name="name" value="{{ old('name', $append->name) }}">
|
||||||
</label>
|
</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) }}">
|
<input class="form-input border-0 border-b-2 w-full" type="text" name="from" value="{{ old('from', $append->from) }}">
|
||||||
</label>
|
</label>
|
||||||
@ -66,4 +68,5 @@
|
|||||||
</form>
|
</form>
|
||||||
@include("common.footer")
|
@include("common.footer")
|
||||||
</body>
|
</body>
|
||||||
|
<script src="{{ mix('/js/component/from_select.js') }}" rel="script"></script>
|
||||||
</html>
|
</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', ["\\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->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->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->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");
|
$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'])
|
.extract(['axios', 'lodash'])
|
||||||
.js('resources/js/webauthn.js', 'public/js')
|
.js('resources/js/webauthn.js', 'public/js')
|
||||||
|
.copy('resources/css/vendor', 'public/css/vendor')
|
||||||
.postCss('resources/css/app.css', 'public/css', [
|
.postCss('resources/css/app.css', 'public/css', [
|
||||||
require('tailwindcss')
|
require('tailwindcss')
|
||||||
])
|
])
|
||||||
.disableNotifications();
|
.disableNotifications();
|
||||||
if (mix.inProduction()) {
|
if (mix.inProduction()) {
|
||||||
mix.version();
|
mix.version();
|
||||||
|
} else {
|
||||||
|
mix.sourceMaps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user