Search, quick search, new command line function, use '> + space' to enter command line mode.

This commit is contained in:
fanchenio 2023-11-23 10:40:04 +08:00
parent 26ae2093e3
commit f40cab0107
14 changed files with 488 additions and 191 deletions

View File

@ -70,6 +70,8 @@ let simplifiedChinese = {
colonKeywordSpace: "冒号 + 关键字 + 空格", colonKeywordSpace: "冒号 + 关键字 + 空格",
color: "颜色", color: "颜色",
columnNumber: "列数", columnNumber: "列数",
commandLine: "命令行",
commandLinePrompt1: "使用“> + 空格”进入命令行模式。",
commandPrompt: "命令提示符", commandPrompt: "命令提示符",
computer: "计算机", computer: "计算机",
computerManagement: "计算机管理", computerManagement: "计算机管理",
@ -204,6 +206,7 @@ let simplifiedChinese = {
password: "密码", password: "密码",
pasteIcon: "粘贴图标", pasteIcon: "粘贴图标",
powerOptions: "电源选项", powerOptions: "电源选项",
powerShell: "PowerShell",
programsFeatures: "程序和功能", programsFeatures: "程序和功能",
proxy: "代理", proxy: "代理",
proxyPrompt: proxyPrompt:
@ -371,6 +374,8 @@ let traditionalChinese = {
colonKeywordSpace: "冒號 + 關鍵字 + 空格", colonKeywordSpace: "冒號 + 關鍵字 + 空格",
color: "顏色", color: "顏色",
columnNumber: "列數", columnNumber: "列數",
commandLine: "命令行",
commandLinePrompt1: "使用「> + 空格」進入命令行模式。",
commandPrompt: "命令提示符", commandPrompt: "命令提示符",
computer: "計算機", computer: "計算機",
computerManagement: "計算機管理", computerManagement: "計算機管理",
@ -505,6 +510,7 @@ let traditionalChinese = {
password: "密碼", password: "密碼",
pasteIcon: "粘貼圖標", pasteIcon: "粘貼圖標",
powerOptions: "電源選項", powerOptions: "電源選項",
powerShell: "PowerShell",
programsFeatures: "程序和功能", programsFeatures: "程序和功能",
proxy: "代理", proxy: "代理",
proxyPrompt: proxyPrompt:
@ -678,6 +684,8 @@ let english = {
colonKeywordSpace: "Colon + Keyword + Space", colonKeywordSpace: "Colon + Keyword + Space",
color: "Color", color: "Color",
columnNumber: "Column Number", columnNumber: "Column Number",
commandLine: "Command Line",
commandLinePrompt1: 'Use "> + space" to enter command line mode.',
commandPrompt: "Command Prompt", commandPrompt: "Command Prompt",
computer: "Computer", computer: "Computer",
computerManagement: "Computer Management", computerManagement: "Computer Management",
@ -814,6 +822,7 @@ let english = {
password: "Password", password: "Password",
pasteIcon: "Paste Icon", pasteIcon: "Paste Icon",
powerOptions: "Power Options", powerOptions: "Power Options",
powerShell: "PowerShell",
programsFeatures: "Programs Features", programsFeatures: "Programs Features",
proxy: "Proxy", proxy: "Proxy",
proxyPrompt: proxyPrompt:

View File

@ -1,6 +1,7 @@
import { import {
Appearance, Appearance,
Classification, Classification,
CommandLine,
General, General,
Item, Item,
Network, Network,
@ -317,6 +318,20 @@ function getWebSearch({
}; };
} }
/**
*
* @returns
*/
function getCommandLine({
defaultUse = "cmd",
}: {
defaultUse?: string | null;
}): CommandLine {
return {
defaultUse: defaultUse ?? "cmd",
};
}
/** /**
* *
* @returns * @returns
@ -377,6 +392,9 @@ function getSetting(setting: Setting | null): Setting {
webSearch: getWebSearch( webSearch: getWebSearch(
setting && setting.webSearch ? setting.webSearch : {} setting && setting.webSearch ? setting.webSearch : {}
), ),
commandLine: getCommandLine(
setting && setting.commandLine ? setting.commandLine : {}
),
network: getNetwork(setting && setting.network ? setting.network : {}), network: getNetwork(setting && setting.network ? setting.network : {}),
}; };
} }

View File

@ -163,4 +163,13 @@ export default function () {
ipcMain.on("exit", () => { ipcMain.on("exit", () => {
app.quit(); app.quit();
}); });
// 运行
ipcMain.on("run", (event, args) => {
global.addon.shellExecute(
args.operation,
args.target,
args.params ?? "",
app.getPath("home")
);
});
} }

View File

@ -24,7 +24,7 @@ function createQuickSearchWindow() {
fullscreenable: false, fullscreenable: false,
resizable: false, resizable: false,
alwaysOnTop: true, alwaysOnTop: true,
backgroundColor: getMainBackgorunColor(), backgroundColor: global.setting.appearance.theme.mainBackgroundColor,
webPreferences: { webPreferences: {
spellcheck: false, spellcheck: false,
backgroundThrottling: false, backgroundThrottling: false,

View File

@ -105,6 +105,15 @@ contextBridge.exposeInMainWorld("api", {
exit: () => { exit: () => {
ipcRenderer.send("exit"); ipcRenderer.send("exit");
}, },
// 运行
run: (
operation: string,
target: string,
params: string | null,
startLocation: string | null
) => {
ipcRenderer.send("run", { operation, target, params, startLocation });
},
}); });
contextBridge.exposeInMainWorld("main", { contextBridge.exposeInMainWorld("main", {

View File

@ -30,6 +30,7 @@
"devDependencies": { "devDependencies": {
"@napi-rs/cli": "^2.16.3", "@napi-rs/cli": "^2.16.3",
"@vicons/material": "^0.12.0", "@vicons/material": "^0.12.0",
"@vicons/ionicons5": "^0.12.0",
"@vicons/utils": "^0.1.4", "@vicons/utils": "^0.1.4",
"@vitejs/plugin-vue": "^4.4.0", "@vitejs/plugin-vue": "^4.4.0",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.16",
@ -70,4 +71,4 @@
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"xml2js": "^0.6.2" "xml2js": "^0.6.2"
} }
} }

View File

@ -0,0 +1,20 @@
<template>
<span
class="ml-auto text-[12px] py-[4px] px-[6px]"
style="border-radius: 4px"
:style="{
color: store.setting.appearance.theme.mainFontColor,
backgroundColor: store.setting.appearance.theme.secondBackgroundColor,
}"
>{{ text }}</span
>
</template>
<script setup lang="ts">
import { useMainStore } from "../store";
// pinia
const store = useMainStore();
// props
const props = defineProps<{
text: string;
}>();
</script>

6
src/index.d.ts vendored
View File

@ -31,6 +31,12 @@ declare global {
openURL: (url: string) => void; openURL: (url: string) => void;
getVersion: () => string; getVersion: () => string;
exit: () => void; exit: () => void;
run: (
operation: string,
target: string,
params: string | null,
startLocation: string | null
) => void;
}; };
main: { main: {
showWindow: (blurHide: boolean) => void; showWindow: (blurHide: boolean) => void;

View File

@ -1,7 +1,6 @@
<template> <template>
<div <div
class="overflow-x-hidden max-h-[525px]" class="overflow-x-hidden max-h-[525px]"
style="text-shadow: none"
:style="{ :style="{
color: store.setting.appearance.theme.mainFontColor, color: store.setting.appearance.theme.mainFontColor,
backgroundColor: store.setting.appearance.theme.mainBackgroundColor, backgroundColor: store.setting.appearance.theme.mainBackgroundColor,
@ -16,20 +15,16 @@
resultList && resultList.length > 0 ? 'solid' : undefined, resultList && resultList.length > 0 ? 'solid' : undefined,
}" }"
> >
<div class="mx-2 whitespace-nowrap flex items-center"> <div class="mx-[10px] whitespace-nowrap flex items-center">
<svg <Icon class="app-region-drag" size="22" v-if="mode === 'search'">
class="w-[24px] h-[24px] app-region-drag" <SearchOutline></SearchOutline>
viewBox="0 96 960 960" </Icon>
v-if="!webSearch" <Icon class="app-region-drag" size="22" v-if="mode === 'commandLine'">
> <TerminalOutline></TerminalOutline>
<path </Icon>
fill="currentColor"
d="M779.385 902.154 528.923 651.693q-30 25.538-69 39.538-39 14-78.385 14-96.1 0-162.665-66.529-66.566-66.529-66.566-162.577t66.529-162.702q66.529-66.654 162.577-66.654 96.049 0 162.702 66.565Q610.769 379.899 610.769 476q0 41.692-14.769 80.692-14.769 39-38.769 66.693l250.462 250.461-28.308 28.308ZM381.538 665.231q79.616 0 134.423-54.808Q570.769 555.615 570.769 476q0-79.615-54.808-134.423-54.807-54.808-134.423-54.808-79.615 0-134.423 54.808Q192.308 396.385 192.308 476q0 79.615 54.807 134.423 54.808 54.808 134.423 54.808Z"
/>
</svg>
<span <span
class="text-2xl block app-region-drag" class="text-xl block app-region-drag"
v-else-if="webSearch && webSearchSource" v-if="mode === 'webSearch' && webSearchSource"
>{{ webSearchSource.name }}</span >{{ webSearchSource.name }}</span
> >
</div> </div>
@ -37,12 +32,12 @@
ref="searchInput" ref="searchInput"
type="text" type="text"
v-model="value" v-model="value"
class="w-full resize-none text-2xl font-light hover:outline-0 focus-visible:outline-0" class="w-full resize-none text-xl font-light hover:outline-0 focus-visible:outline-0"
:style="{ :style="{
backgroundColor: store.setting.appearance.theme.mainBackgroundColor, backgroundColor: store.setting.appearance.theme.mainBackgroundColor,
color: store.setting.appearance.theme.mainFontColor, color: store.setting.appearance.theme.mainFontColor,
}" }"
placeholder="Dawn Launcher" :placeholder="getPlaceholder()"
/> />
</div> </div>
<ul <ul
@ -59,7 +54,7 @@
> >
<li <li
v-for="(item, index) of resultList" v-for="(item, index) of resultList"
class="item flex items-center px-2 h-[48px]" class="item flex items-center px-[12px] h-[48px]"
:key="'item-' + item.id + '-' + index" :key="'item-' + item.id + '-' + index"
:id="'item-' + index" :id="'item-' + index"
:item-id="item.id" :item-id="item.id"
@ -75,33 +70,57 @@
}" }"
:title="getItemTitle(item as Item)" :title="getItemTitle(item as Item)"
:index="index" :index="index"
:target="item.data.target"
> >
<CustomItemIcon :item="(item as Item)" :icon-size="32"></CustomItemIcon> <CustomItemIcon :item="(item as Item)" :icon-size="28"></CustomItemIcon>
<span <span
class="text-sm ml-2 overflow-hidden text-ellipsis whitespace-nowrap h-[20px] flex-1 pr-[10px]" class="text-sm ml-[10px] overflow-hidden text-ellipsis whitespace-nowrap h-[20px] flex-1 pr-[10px]"
>{{ getName(item.name) >{{ getName(item.name)
}}<span class="text-xs ml-2">{{ }}<span v-if="mode === 'search'" class="text-xs ml-2">{{
getSearchItemClassificationName((item as Item).classificationId) getSearchItemClassificationName((item as Item).classificationId)
}}</span></span }}</span></span
> >
<span <template
class="ml-auto text-[12px]"
v-if=" v-if="
store.setting.quickSearch.openShortcutKey !== 'none' && index <= 9 store.setting.quickSearch.openShortcutKey !== 'none' && index <= 9
" "
:style="{
color: hexToRGBA(store.setting.appearance.theme.mainFontColor, 0.7),
}"
>{{
showHistory
? "Alt + "
: store.setting.quickSearch.openShortcutKey === "numberKey"
? store.language.numberKey
: store.setting.quickSearch.openShortcutKey === "ctrlNumberKey"
? "Ctrl + "
: "Alt + "
}}{{ index + 1 === 10 ? 0 : index + 1 }}</span
> >
<template
v-if="
showHistory ||
store.setting.quickSearch.openShortcutKey === 'altNumberKey'
"
>
<keyText text="Alt"></keyText>
&nbsp;+&nbsp;
<keyText
:text="(index + 1 === 10 ? 0 : index + 1).toString()"
></keyText>
</template>
<template
v-else-if="
store.setting.quickSearch.openShortcutKey === 'numberKey'
"
>
<keyText
:text="
store.language.numberKey +
(index + 1 === 10 ? 0 : index + 1).toString()
"
></keyText>
</template>
<template
v-else-if="
store.setting.quickSearch.openShortcutKey === 'ctrlNumberKey'
"
>
<keyText text="Ctrl"></keyText>
&nbsp;+&nbsp;
<keyText
:text="(index + 1 === 10 ? 0 : index + 1).toString()"
></keyText>
</template>
</template>
</li> </li>
</ul> </ul>
</div> </div>
@ -131,7 +150,15 @@ import "simplebar/dist/simplebar.css";
import CustomItemIcon from "../../components/CustomItemIcon.vue"; import CustomItemIcon from "../../components/CustomItemIcon.vue";
import { getClassElement, hexToRGBA } from "../../utils/style"; import { getClassElement, hexToRGBA } from "../../utils/style";
import { convert } from "../../../commons/utils/common"; import { convert } from "../../../commons/utils/common";
import { itemAllRemoveStyle, searchResultDivMoveScroll } from "./js/index"; import {
itemAllRemoveStyle,
searchResultDivMoveScroll,
getCommandLineItemList,
commandLineRun as commonCommandLineRun,
} from "./js/index";
import keyText from "../../components/KeyText.vue";
import { Icon } from "@vicons/utils";
import { SearchOutline, TerminalOutline } from "@vicons/ionicons5";
import { useMainStore } from "../../store"; import { useMainStore } from "../../store";
// pinia // pinia
const store = useMainStore(); const store = useMainStore();
@ -142,7 +169,7 @@ let searchInput = ref<any>(null);
// //
let value = ref<string | null>(null); let value = ref<string | null>(null);
// //
let webSearch = ref(false); let mode = ref<"search" | "webSearch" | "commandLine">("search");
// //
let webSearchSource = ref<WebSearchSource | null>(null); let webSearchSource = ref<WebSearchSource | null>(null);
// //
@ -160,7 +187,8 @@ watch(
); );
// //
function search() { function search() {
if (!webSearch.value) { if (mode.value === "search") {
//
if (value.value) { if (value.value) {
showHistory.value = false; showHistory.value = false;
resultList.value = searchItem(value.value, searchMap, 50); resultList.value = searchItem(value.value, searchMap, 50);
@ -178,21 +206,25 @@ function search() {
// //
getHistory(); getHistory();
} }
// refresh();
resetScroll();
// DOM
nextTick(() => {
//
let height =
!resultList.value || resultList.value.length === 0
? 0
: resultList.value.length > 9
? 10 * 48 + 1
: resultList.value.length * 48 + 1;
window.quickSearch.setWindowHeight(height + 44);
});
} }
} }
//
function refresh() {
//
resetScroll();
// DOM
nextTick(() => {
//
let height =
!resultList.value || resultList.value.length === 0
? 0
: resultList.value.length > 9
? 10 * 48 + 1
: resultList.value.length * 48 + 1;
window.quickSearch.setWindowHeight(height + 44);
});
}
/** /**
* 重置滚动条 * 重置滚动条
*/ */
@ -268,34 +300,34 @@ function getHistory() {
resultList.value = []; resultList.value = [];
showHistory.value = false; showHistory.value = false;
} }
// refresh();
resetScroll();
// DOM
nextTick(() => {
//
let height =
!resultList.value || resultList.value.length === 0
? 0
: resultList.value.length > 9
? 10 * 48 + 1
: resultList.value.length * 48 + 1;
window.quickSearch.setWindowHeight(height + 44);
});
} }
// //
function parentRunItem(e: any) { function parentRunItem(e: any) {
// item // item
let itemElement = getClassElement(e, "item"); let itemElement = getClassElement(e, "item");
if (itemElement) { if (itemElement) {
// ID if (mode.value === "search") {
let itemId = parseInt(itemElement.getAttribute("item-id")); // ID
// let itemId = parseInt(itemElement.getAttribute("item-id"));
let item = getItemById(itemId); //
if (item && item.data) { let item = getItemById(itemId);
runItem(item); if (item && item.data) {
runItem(item);
}
} else if (mode.value === "commandLine") {
//
commandLineRun(itemElement.getAttribute("target"));
} }
} }
} }
//
function commandLineRun(target: string) {
if (store.setting.quickSearch.openAfterHideQuickSearchWindow) {
hide();
}
commonCommandLineRun(target, value.value);
}
// //
function runItem(item: Item) { function runItem(item: Item) {
if (store.setting.quickSearch.openAfterHideQuickSearchWindow) { if (store.setting.quickSearch.openAfterHideQuickSearchWindow) {
@ -303,6 +335,21 @@ function runItem(item: Item) {
} }
run("quickSearch", "open", item); run("quickSearch", "open", item);
} }
// placeholder
function getPlaceholder() {
let text = "Dawn Launcher";
if (
mode.value === "webSearch" &&
webSearchSource.value &&
webSearchSource.value.description &&
webSearchSource.value.description.trim() !== ""
) {
text = webSearchSource.value.description.trim();
} else if (mode.value === "commandLine") {
text = "Command Line";
}
return text;
}
// //
function hide() { function hide() {
window.quickSearch.hideWindow(); window.quickSearch.hideWindow();
@ -311,33 +358,35 @@ function hide() {
function contextmenu(e: any) { function contextmenu(e: any) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// if (mode.value === "search") {
let item: Item | null = null; //
// let item: Item | null = null;
if (getClassElement(e, "item")) { //
// if (getClassElement(e, "item")) {
// ID //
let element = getClassElement(e, "item"); // ID
// ID let element = getClassElement(e, "item");
let id = parseInt(element.getAttribute("item-id")); // ID
// let id = parseInt(element.getAttribute("item-id"));
item = convert(getItemById(id)); //
} item = convert(getItemById(id));
if (item) { }
// if (item) {
store.quickSearchItemRightMenuItemId = item.id; //
window.item.showRightMenu({ store.quickSearchItemRightMenuItemId = item.id;
item, window.item.showRightMenu({
x: e.screenX, item,
y: e.screenY, x: e.screenX,
type: "quickSearch", y: e.screenY,
}); type: "quickSearch",
});
}
} }
} }
// dragover // dragover
function dragover(e: any) { function dragover(e: any) {
// //
if (store.setting.quickSearch.useItemOpen) { if (mode.value === "search" && store.setting.quickSearch.useItemOpen) {
// //
let target = findElement(e.target, "item"); let target = findElement(e.target, "item");
// //
@ -363,40 +412,42 @@ function dragover(e: any) {
} }
// drop // drop
function drop(e: any) { function drop(e: any) {
// if (mode.value === "search") {
let item: Item | null = null; //
let itemElement = findElement(e.target, "item"); let item: Item | null = null;
if (itemElement) { let itemElement = findElement(e.target, "item");
let id = itemElement.getAttribute("item-id"); if (itemElement) {
if (id) { let id = itemElement.getAttribute("item-id");
item = getItemById(parseInt(id)); if (id) {
} item = getItemById(parseInt(id));
}
//
let pathList = [];
for (const file of e.dataTransfer.files) {
pathList.push(file.path);
}
//
if (store.setting.quickSearch.useItemOpen && item && pathList.length > 0) {
//
if (pathList.length === 1 && pathList[0] === item.data.target) {
return;
}
let params = "";
for (let i = 0; i < pathList.length; i++) {
if (i > 0) {
params += " ";
} }
params += '"' + pathList[i] + '"';
} }
if (item.data.params) { //
params += " " + item.data.params; let pathList = [];
for (const file of e.dataTransfer.files) {
pathList.push(file.path);
}
//
if (store.setting.quickSearch.useItemOpen && item && pathList.length > 0) {
//
if (pathList.length === 1 && pathList[0] === item.data.target) {
return;
}
let params = "";
for (let i = 0; i < pathList.length; i++) {
if (i > 0) {
params += " ";
}
params += '"' + pathList[i] + '"';
}
if (item.data.params) {
params += " " + item.data.params;
}
let copyItem: Item = convert(item);
copyItem.data.params = params;
//
runItem(copyItem);
} }
let copyItem: Item = convert(item);
copyItem.data.params = params;
//
runItem(copyItem);
} }
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -430,7 +481,7 @@ function keydown(e: any) {
} }
// //
if (e.keyCode === 32) { if (e.keyCode === 32) {
if (!webSearch.value) { if (mode.value !== "webSearch") {
// //
if (value.value && value.value.trim() !== "") { if (value.value && value.value.trim() !== "") {
let flag = false; let flag = false;
@ -448,7 +499,7 @@ function keydown(e: any) {
: value.value; : value.value;
for (let searchSource of store.setting.webSearch.searchSourceList) { for (let searchSource of store.setting.webSearch.searchSourceList) {
if (keyword === searchSource.keyword) { if (keyword === searchSource.keyword) {
webSearch.value = true; mode.value = "webSearch";
webSearchSource.value = searchSource; webSearchSource.value = searchSource;
value.value = null; value.value = null;
resultList.value = []; resultList.value = [];
@ -461,32 +512,57 @@ function keydown(e: any) {
} }
} }
} }
if (mode.value !== "webSearch" && mode.value !== "commandLine") {
//
if (value.value && value.value.trim() !== "") {
if (value.value === ">") {
mode.value = "commandLine";
value.value = null;
resultList.value = getCommandLineItemList();
selected.value = 0;
refresh();
e.stopPropagation();
e.preventDefault();
}
}
}
} }
// enter // enter
if (e.keyCode === 13) { if (e.keyCode === 13) {
if (webSearch.value && webSearchSource.value) { if (mode.value === "webSearch" && webSearchSource.value) {
let url = webSearchSource.value.url.replace("{w}", value.value ?? ""); let url = webSearchSource.value.url.replace("{w}", value.value ?? "");
window.api.openURL(url); window.api.openURL(url);
if (store.setting.quickSearch.openAfterHideQuickSearchWindow) { if (store.setting.quickSearch.openAfterHideQuickSearchWindow) {
hide(); hide();
} }
} else if ( } else if (
!webSearch.value && mode.value === "search" &&
resultList.value.length - 1 >= selected.value resultList.value.length - 1 >= selected.value
) { ) {
runItem(resultList.value[selected.value] as Item); runItem(resultList.value[selected.value] as Item);
} else if (
mode.value === "commandLine" &&
resultList.value.length - 1 >= selected.value
) {
commandLineRun(resultList.value[selected.value].data.target!);
} }
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
} }
// 退 // 退
if (e.keyCode === 8) { if (e.keyCode === 8) {
if (webSearch.value) { if (mode.value === "webSearch") {
if (!value.value || value.value.trim() === "") { if (!value.value || value.value.trim() === "") {
webSearch.value = false; mode.value = "search";
webSearchSource.value = null; webSearchSource.value = null;
window.quickSearch.setWindowHeight(44); window.quickSearch.setWindowHeight(44);
} }
} else if (mode.value === "commandLine") {
if (!value.value || value.value.trim() === "") {
mode.value = "search";
resultList.value = [];
window.quickSearch.setWindowHeight(44);
}
} }
} }
if (showHistory.value) { if (showHistory.value) {
@ -547,7 +623,11 @@ function keydown(e: any) {
index = e.key - 1; index = e.key - 1;
} }
if (resultList.value && index < resultList.value.length) { if (resultList.value && index < resultList.value.length) {
runItem(resultList.value[index] as Item); if (mode.value === "search") {
runItem(resultList.value[index] as Item);
} else if (mode.value === "commandLine") {
commandLineRun(resultList.value[index].data.target!);
}
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
} }
@ -606,7 +686,7 @@ onMounted(() => {
value.value = null; value.value = null;
resultList.value = []; resultList.value = [];
selected.value = 0; selected.value = 0;
webSearch.value = false; mode.value = "search";
webSearchSource.value = null; webSearchSource.value = null;
}) })
); );

View File

@ -18,20 +18,17 @@
}" }"
> >
<div class="mx-2 whitespace-nowrap flex items-center"> <div class="mx-2 whitespace-nowrap flex items-center">
<svg <Icon size="18" v-if="mode === 'search'">
class="w-[18px] h-[18px]" <SearchOutline></SearchOutline>
:style="{ color: store.setting.appearance.theme.mainFontColor }" </Icon>
viewBox="0 0 24 24" <Icon size="18" v-if="mode === 'commandLine'">
v-if="!webSearch" <TerminalOutline></TerminalOutline>
</Icon>
<span
class="text-sm block"
v-if="mode === 'webSearch' && webSearchSource"
>{{ webSearchSource.name }}</span
> >
<path
fill="currentColor"
d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"
/>
</svg>
<span class="text-sm block" v-else-if="webSearch && webSearchSource">{{
webSearchSource.name
}}</span>
</div> </div>
<input <input
ref="searchInput" ref="searchInput"
@ -42,14 +39,7 @@
backgroundColor: store.setting.appearance.theme.mainBackgroundColor, backgroundColor: store.setting.appearance.theme.mainBackgroundColor,
color: store.setting.appearance.theme.mainFontColor, color: store.setting.appearance.theme.mainFontColor,
}" }"
:placeholder=" :placeholder="getPlaceholder()"
webSearch &&
webSearchSource &&
webSearchSource.description &&
webSearchSource.description.trim() !== ''
? webSearchSource.description
: store.language.search
"
/> />
<Icon <Icon
size="18" size="18"
@ -89,12 +79,13 @@
:item-id="item.id" :item-id="item.id"
:title="getItemTitle(item as Item)" :title="getItemTitle(item as Item)"
:index="index" :index="index"
:target="item.data.target"
> >
<CustomItemIcon :item="(item as Item)" :icon-size="32"></CustomItemIcon> <CustomItemIcon :item="(item as Item)" :icon-size="32"></CustomItemIcon>
<span <span
class="text-sm ml-2 overflow-hidden text-ellipsis whitespace-nowrap h-[20px]" class="text-sm ml-2 overflow-hidden text-ellipsis whitespace-nowrap h-[20px]"
>{{ getName(item.name) >{{ getName(item.name)
}}<span class="text-xs ml-2">{{ }}<span v-if="mode === 'search'" class="text-xs ml-2">{{
getSearchItemClassificationName((item as Item).classificationId) getSearchItemClassificationName((item as Item).classificationId)
}}</span></span }}</span></span
> >
@ -130,14 +121,20 @@ import { WebSearchSource } from "../../../../types/setting";
import { convert } from "../../../../commons/utils/common"; import { convert } from "../../../../commons/utils/common";
import "simplebar"; import "simplebar";
import "simplebar/dist/simplebar.css"; import "simplebar/dist/simplebar.css";
import { itemAllRemoveStyle, searchResultDivMoveScroll } from "../js/index"; import {
getCommandLineItemList,
itemAllRemoveStyle,
searchResultDivMoveScroll,
commandLineRun,
} from "../js/index";
import { SearchOutline, TerminalOutline } from "@vicons/ionicons5";
import { useMainStore } from "../../../store"; import { useMainStore } from "../../../store";
// pinia // pinia
const store = useMainStore(); const store = useMainStore();
// //
let searchInput = ref<any>(null); let searchInput = ref<any>(null);
// //
let webSearch = ref(false); let mode = ref<"search" | "webSearch" | "commandLine">("search");
// //
let webSearchSource = ref<WebSearchSource | null>(null); let webSearchSource = ref<WebSearchSource | null>(null);
// //
@ -162,7 +159,7 @@ watch(
); );
// //
function search() { function search() {
if (!webSearch.value) { if (mode.value === "search") {
if (value.value) { if (value.value) {
resultList.value = searchItem(value.value, searchMap, 50); resultList.value = searchItem(value.value, searchMap, 50);
if (resultList.value && resultList.value.length > 0) { if (resultList.value && resultList.value.length > 0) {
@ -190,16 +187,37 @@ function runItem(e: any) {
// item // item
let itemElement = getClassElement(e, "search-result-item"); let itemElement = getClassElement(e, "search-result-item");
if (itemElement) { if (itemElement) {
// ID if (mode.value === "search") {
let itemId = parseInt(itemElement.getAttribute("item-id")); // ID
// let itemId = parseInt(itemElement.getAttribute("item-id"));
let item = getItemById(itemId); //
if (item && item.data) { let item = getItemById(itemId);
run("search", "open", item); if (item && item.data) {
run("search", "open", item);
close();
}
} else if (mode.value === "commandLine") {
//
commandLineRun(itemElement.getAttribute("target"), value.value);
close(); close();
} }
} }
} }
// placeholder
function getPlaceholder() {
let text = store.language.search;
if (
mode.value === "webSearch" &&
webSearchSource.value &&
webSearchSource.value.description &&
webSearchSource.value.description.trim() !== ""
) {
text = webSearchSource.value.description.trim();
} else if (mode.value === "commandLine") {
text = "Command Line";
}
return text;
}
// //
function close() { function close() {
store.search = false; store.search = false;
@ -217,27 +235,29 @@ watch(
function contextmenu(e: any) { function contextmenu(e: any) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// if (mode.value === "search") {
let item: Item | null = null; //
// let item: Item | null = null;
if (getClassElement(e, "search-result-item")) { //
// if (getClassElement(e, "search-result-item")) {
// ID //
let element = getClassElement(e, "search-result-item"); // ID
// ID let element = getClassElement(e, "search-result-item");
let id = parseInt(element.getAttribute("item-id")); // ID
// let id = parseInt(element.getAttribute("item-id"));
item = convert(getItemById(id)); //
} item = convert(getItemById(id));
if (item) { }
// if (item) {
store.searchItemRightMenuItemId = item.id; //
window.item.showRightMenu({ store.searchItemRightMenuItemId = item.id;
item, window.item.showRightMenu({
x: e.screenX, item,
y: e.screenY, x: e.screenX,
type: "search", y: e.screenY,
}); type: "search",
});
}
} }
} }
function keydown(e: any) { function keydown(e: any) {
@ -275,7 +295,7 @@ function keydown(e: any) {
} }
// //
if (e.keyCode === 32) { if (e.keyCode === 32) {
if (!webSearch.value) { if (mode.value === "search") {
// //
if (value.value && value.value.trim() !== "") { if (value.value && value.value.trim() !== "") {
let flag = false; let flag = false;
@ -293,7 +313,7 @@ function keydown(e: any) {
: value.value; : value.value;
for (let searchSource of store.setting.webSearch.searchSourceList) { for (let searchSource of store.setting.webSearch.searchSourceList) {
if (keyword === searchSource.keyword) { if (keyword === searchSource.keyword) {
webSearch.value = true; mode.value = "webSearch";
webSearchSource.value = searchSource; webSearchSource.value = searchSource;
value.value = null; value.value = null;
resultList.value = []; resultList.value = [];
@ -304,29 +324,55 @@ function keydown(e: any) {
} }
} }
} }
if (mode.value !== "webSearch" && mode.value !== "commandLine") {
//
if (value.value && value.value.trim() !== "") {
if (value.value === ">") {
mode.value = "commandLine";
value.value = null;
resultList.value = getCommandLineItemList();
selected.value = 0;
e.preventDefault();
}
}
}
} }
// enter // enter
if (e.keyCode === 13) { if (e.keyCode === 13) {
if (webSearch.value && webSearchSource.value) { if (mode.value === "webSearch" && webSearchSource.value) {
let url = webSearchSource.value.url.replace("{w}", value.value ?? ""); let url = webSearchSource.value.url.replace("{w}", value.value ?? "");
window.api.openURL(url); window.api.openURL(url);
close(); close();
} else if ( } else if (
!webSearch.value && mode.value === "search" &&
resultList.value.length - 1 >= selected.value resultList.value.length - 1 >= selected.value
) { ) {
run("search", "open", resultList.value[selected.value] as Item); run("search", "open", resultList.value[selected.value] as Item);
close(); close();
} else if (
mode.value === "commandLine" &&
resultList.value.length - 1 >= selected.value
) {
commandLineRun(
resultList.value[selected.value].data.target!,
value.value
);
close();
} }
e.preventDefault(); e.preventDefault();
} }
// 退 // 退
if (e.keyCode === 8) { if (e.keyCode === 8) {
if (webSearch.value) { if (mode.value === "webSearch") {
if (!value.value || value.value.trim() === "") { if (!value.value || value.value.trim() === "") {
webSearch.value = false; mode.value = "search";
webSearchSource.value = null; webSearchSource.value = null;
} }
} else if (mode.value === "commandLine") {
if (!value.value || value.value.trim() === "") {
mode.value = "search";
resultList.value = [];
}
} }
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -1401,6 +1401,24 @@
</NForm> </NForm>
</div> </div>
<div class="mx-2" v-if="selectedMenuId === 7"> <div class="mx-2" v-if="selectedMenuId === 7">
<NForm label-placement="left" :show-feedback="false" size="small">
<span class="block font-semibold">{{
store.language.default
}}</span>
<NFormItem class="mt-2">
<NSelect
v-model:value="setting.commandLine.defaultUse"
:options="commandLineDefultUseOptions"
size="small"
></NSelect>
</NFormItem>
<Desc
class="mt-2"
:content="store.language.commandLinePrompt1"
></Desc>
</NForm>
</div>
<div class="mx-2" v-if="selectedMenuId === 8">
<NForm label-placement="left" :show-feedback="false" size="small"> <NForm label-placement="left" :show-feedback="false" size="small">
<span class="block font-semibold">{{ <span class="block font-semibold">{{
store.language.proxy store.language.proxy
@ -1550,6 +1568,10 @@ let menuList = [
}, },
{ {
id: 7, id: 7,
label: store.language.commandLine,
},
{
id: 8,
label: store.language.network, label: store.language.network,
}, },
]; ];
@ -2213,6 +2235,17 @@ function closeSaveSearchSource() {
searchSourceURL.value = null; searchSourceURL.value = null;
searchSourceDescription.value = null; searchSourceDescription.value = null;
} }
// 使
let commandLineDefultUseOptions = ref([
{
label: store.language.commandPrompt,
value: "cmd",
},
{
label: store.language.powerShell,
value: "powershell",
},
]);
// //
let height = ref(0); let height = ref(0);
// //

8
types/setting.d.ts vendored
View File

@ -190,6 +190,12 @@ export interface WebSearch {
searchSourceList: Array<WebSearchSource>; searchSourceList: Array<WebSearchSource>;
} }
// 命令行
export interface CommandLine {
// 默认使用
defaultUse: string;
}
// 网络搜索源 // 网络搜索源
export interface WebSearchSource { export interface WebSearchSource {
// ID // ID
@ -238,6 +244,8 @@ export interface Setting {
quickSearch: QuickSearch; quickSearch: QuickSearch;
// 网络搜索 // 网络搜索
webSearch: WebSearch; webSearch: WebSearch;
// 命令行
commandLine: CommandLine;
// 网络 // 网络
network: Network; network: Network;
} }

View File

@ -475,6 +475,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@vicons/ionicons5@^0.12.0":
version "0.12.0"
resolved "https://registry.npmmirror.com/@vicons/ionicons5/-/ionicons5-0.12.0.tgz#c39fda04420dfae3b58053faf8aaf3555253299d"
integrity sha512-Iy1EUVRpX0WWxeu1VIReR1zsZLMc4fqpt223czR+Rpnrwu7pt46nbnC2ycO7ItI/uqDLJxnbcMC7FujKs9IfFA==
"@vicons/material@^0.12.0": "@vicons/material@^0.12.0":
version "0.12.0" version "0.12.0"
resolved "https://registry.npmmirror.com/@vicons/material/-/material-0.12.0.tgz#068e72fa40bd7f780af5fc68011fb69010c8e0b5" resolved "https://registry.npmmirror.com/@vicons/material/-/material-0.12.0.tgz#068e72fa40bd7f780af5fc68011fb69010c8e0b5"