bottomTools.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. <template>
  2. <view
  3. v-if="isShow"
  4. class="bottomTools"
  5. :style="{
  6. 'padding-bottom': pb,
  7. }"
  8. >
  9. <!-- Error -->
  10. <template v-if="tabTitle == 'Error'">
  11. <view
  12. class="miniBtn mr warn"
  13. @click="emptyLogs('error')"
  14. >
  15. <text class="miniBtnText">清空 x</text>
  16. </view>
  17. <btnTabs
  18. :list="errorTypeList"
  19. :value="errorTypeIndex"
  20. @indexChange="errorTypeIndexChange"
  21. />
  22. </template>
  23. <!-- Console -->
  24. <template v-if="tabTitle == 'Console'">
  25. <view
  26. class="miniBtn mr warn"
  27. @click="emptyLogs('console')"
  28. >
  29. <text class="miniBtnText">清空 x</text>
  30. </view>
  31. <btnTabs
  32. :list="consoleTypeList"
  33. :value="consoleTypeListIndex"
  34. @indexChange="consoleTypeIndexChange"
  35. />
  36. </template>
  37. <!-- Network -->
  38. <template v-if="tabTitle == 'Network'">
  39. <view
  40. class="miniBtn mr warn"
  41. @click="emptyLogs('network')"
  42. >
  43. <text class="miniBtnText">清空 x</text>
  44. </view>
  45. <MenuBtn
  46. :list="networkFilterType"
  47. :value="networkTypeListIndex"
  48. @indexChange="networkTypeIndexChange"
  49. title="筛选:"
  50. />
  51. <view class="mr"></view>
  52. <RequestSpeedLimit />
  53. <view class="mr"></view>
  54. <RequestTimeoutMock />
  55. </template>
  56. <!-- Pages -->
  57. <template v-if="tabTitle == 'Pages'">
  58. <view
  59. class="miniBtn mr warn"
  60. @click="emptyLogs('pages_1')"
  61. >
  62. <text class="miniBtnText">清空停留统计</text>
  63. </view>
  64. <view
  65. class="miniBtn mr warn"
  66. @click="emptyLogs('pages_2')"
  67. >
  68. <text class="miniBtnText">清空日活统计</text>
  69. </view>
  70. <view
  71. class="miniBtn mr primary"
  72. @click="goPage"
  73. >
  74. <text class="miniBtnText">跳转页面</text>
  75. </view>
  76. </template>
  77. <!-- Logs -->
  78. <template v-if="tabTitle == 'Logs'">
  79. <view
  80. class="miniBtn mr warn"
  81. @click="emptyLogs('logs')"
  82. >
  83. <text class="miniBtnText">清空 x</text>
  84. </view>
  85. </template>
  86. <!-- Storage -->
  87. <template v-if="tabTitle == 'Storage'">
  88. <view
  89. class="miniBtn mr warn"
  90. @click="emptyLogs('storage')"
  91. >
  92. <text class="miniBtnText">清空 x</text>
  93. </view>
  94. <!-- #ifdef H5 -->
  95. <btnTabs
  96. :list="storageFilterTypeList"
  97. :value="storageTypeListIndex"
  98. @indexChange="storageTypeIndexChange"
  99. />
  100. <!-- #endif -->
  101. <view
  102. class="miniBtn primary ml"
  103. @click="addStorage"
  104. >
  105. <text class="miniBtnText">新增数据+</text>
  106. </view>
  107. </template>
  108. <!-- UniBus -->
  109. <template v-if="tabTitle == 'UniBus'">
  110. <view
  111. class="miniBtn mr warn"
  112. @click="emptyLogs('UniBus')"
  113. >
  114. <text class="miniBtnText">清空 x</text>
  115. </view>
  116. <btnTabs
  117. :list="busFilterType"
  118. :value="busTypeListIndex"
  119. @indexChange="busTypeIndexChange"
  120. />
  121. </template>
  122. <!-- FileSys -->
  123. <template v-if="tabTitle == 'FileSys'">
  124. <!-- #ifdef APP-PLUS || MP-WEIXIN -->
  125. <scroll-view
  126. scroll-x
  127. class="dirList"
  128. >
  129. <view class="dirScrollItem">
  130. <text
  131. class="dirName"
  132. style="color: #999"
  133. @click="$emit('goChildDir', '_goIndex_0')"
  134. >
  135. {{ options.fileSysDirType }}
  136. </text>
  137. <text class="delimiter">/</text>
  138. <view
  139. v-for="(item, index) in options.fileSysDirList"
  140. :key="index"
  141. class="dirItem"
  142. >
  143. <text
  144. v-if="index != 0"
  145. class="delimiter"
  146. >
  147. /
  148. </text>
  149. <text
  150. class="dirName"
  151. @click="$emit('goChildDir', '_goIndex_' + (index + 1))"
  152. >
  153. {{ item }}
  154. </text>
  155. </view>
  156. </view>
  157. </scroll-view>
  158. <view
  159. class="miniBtn mr warn"
  160. @click="emptyFolder"
  161. >
  162. <text class="miniBtnText">清空 x</text>
  163. </view>
  164. <!-- #ifdef APP-PLUS -->
  165. <btnTabs
  166. :list="dirTypeList"
  167. :value="fileTypeListIndex"
  168. @indexChange="$emit('changeFileDirType', dirTypeList[$event].type)"
  169. />
  170. <view style="width: 20rpx"></view>
  171. <!-- #endif -->
  172. <view
  173. class="miniBtn primary"
  174. @click="createDir"
  175. >
  176. <text class="miniBtnText">新建文件(夹)</text>
  177. </view>
  178. <!-- #endif -->
  179. </template>
  180. <!-- JsRunner -->
  181. <template v-if="tabTitle == 'JsRunner'">
  182. <view class="jsRunnerTools">
  183. <view class="runOptions">
  184. <view class="radiusList">
  185. <text class="runType">运行环境:</text>
  186. <radio-group
  187. @change="jsRunType = $event.detail.value"
  188. class="radiusList"
  189. style="display: flex; flex-direction: row"
  190. >
  191. <view
  192. v-for="(item, index) in jsRunTypeList"
  193. :key="index"
  194. class="radiusItem"
  195. @click="jsRunType = item"
  196. >
  197. <radio
  198. class="radiusRadio"
  199. :value="item"
  200. :checked="jsRunType == item"
  201. color="#ff2d55"
  202. />
  203. <text
  204. class="radiusText"
  205. :style="{
  206. color: jsRunType == item ? '#ff2d55' : '#333',
  207. }"
  208. >
  209. {{ item }}
  210. </text>
  211. </view>
  212. </radio-group>
  213. </view>
  214. <view
  215. class="hisEmpty"
  216. @click="$emit('emptyCodeHis')"
  217. v-if="options.codeHisLength > 0"
  218. >
  219. <image
  220. class="hisEmptyIcon"
  221. src="@/devTools/page/static/delete.png"
  222. />
  223. <text class="hisEmptyText">清空记录</text>
  224. </view>
  225. <view
  226. class="logList"
  227. @click="showHisCode"
  228. >
  229. <text class="hisText">历史代码</text>
  230. <image
  231. class="unfold"
  232. src="@/devTools/page/static/unfold.png"
  233. />
  234. </view>
  235. </view>
  236. <view class="code">
  237. <textarea
  238. v-model="waitSendCode"
  239. class="codeInput"
  240. placeholder="js code ..."
  241. maxlength="-1"
  242. />
  243. <view
  244. class="codeSend"
  245. @click="runJs"
  246. >
  247. <text class="codeSendText">run</text>
  248. </view>
  249. </view>
  250. </view>
  251. </template>
  252. <!-- Vuex -->
  253. <template v-if="tabTitle == 'Vuex'">
  254. <btnTabs
  255. :list="stateTypeList"
  256. :value="stateTypeListIndex"
  257. @indexChange="stateTypeIndexChange"
  258. />
  259. </template>
  260. <codeHisPicker ref="codeHisPicker" />
  261. </view>
  262. </template>
  263. <script>
  264. import devCache from "../../core/libs/devCache";
  265. import appDelDir from "./libs/appDelDir";
  266. import btnTabs from "./ui/btnTabs.vue";
  267. import codeHisPicker from "./ui/codeHisPicker.vue";
  268. import MenuBtn from "./ui/menuBtn.vue";
  269. import RequestSpeedLimit from "./ui/requestSpeedLimit.vue";
  270. import RequestTimeoutMock from "./ui/requestTimeoutMock.vue";
  271. export default {
  272. components: {
  273. btnTabs,
  274. codeHisPicker,
  275. MenuBtn,
  276. RequestSpeedLimit,
  277. RequestTimeoutMock,
  278. },
  279. props: {
  280. /**
  281. * 列表索引
  282. */
  283. tabIndex: {
  284. type: Number,
  285. default: 0,
  286. },
  287. /**
  288. * 当前标题
  289. */
  290. tabTitle: {
  291. type: String,
  292. default: "",
  293. },
  294. /**
  295. * 配置项
  296. */
  297. options: {
  298. type: Object,
  299. default: () => ({
  300. errorFilterType: "",
  301. consoleFilterType: "",
  302. networkFilterType: "",
  303. busFilterType: "",
  304. fileSysDirList: [],
  305. fileSysDirType: "",
  306. storageType: "",
  307. }),
  308. },
  309. /**
  310. * 是否渲染
  311. */
  312. isShow: {
  313. type: Boolean,
  314. default: false,
  315. },
  316. /**
  317. * Vuex变量类型
  318. */
  319. stateType: {
  320. type: String,
  321. default: "vuex",
  322. },
  323. },
  324. data() {
  325. let pb = "20px";
  326. // #ifdef H5
  327. pb = "8px";
  328. // #endif
  329. let sys = uni.getSystemInfoSync();
  330. if (sys.platform == "ios") {
  331. pb = "40px";
  332. }
  333. let jsRunTypeList = [];
  334. // #ifdef H5
  335. jsRunTypeList = ["h5"];
  336. // #endif
  337. // #ifdef APP-PLUS
  338. jsRunTypeList = ["nvue", "webview"];
  339. // #endif
  340. return {
  341. /**
  342. * 底部边距
  343. */
  344. pb,
  345. /**
  346. * 错误类型列表
  347. */
  348. errorTypeList: [
  349. { title: "全部", type: "" },
  350. { title: "error", type: "ve" },
  351. { title: "warn", type: "vw" },
  352. { title: "jsError", type: "oe" },
  353. { title: "unknown", type: "n" },
  354. ],
  355. /**
  356. * console过滤类型
  357. */
  358. consoleTypeList: [
  359. { title: "全部", type: "" },
  360. { title: "log", type: "log" },
  361. { title: "info", type: "info" },
  362. { title: "warn", type: "warn" },
  363. { title: "error", type: "error" },
  364. ],
  365. /**
  366. * 请求过滤类型
  367. */
  368. networkFilterType: [
  369. { title: "全部请求", type: "", msg: "不使用筛选" },
  370. { title: "请求失败", type: "请求失败", msg: "仅展示请求失败的记录" },
  371. { title: "1s+", type: "1s+", msg: "仅展示响应超过1秒的记录" },
  372. { title: "5s+", type: "5s+", msg: "仅展示响应超过5秒的记录" },
  373. { title: "10s+", type: "10s+", msg: "仅展示响应超过10秒的记录" },
  374. { title: "500KB+", type: "500KB+", msg: "仅展示响应内容超过500KB的记录" },
  375. { title: "1MB+", type: "1MB+", msg: "仅展示响应内容超过1MB的记录" },
  376. { title: "get", type: "get", msg: "仅展示get请求" },
  377. { title: "post", type: "post", msg: "仅展示post请求" },
  378. { title: "other", type: "other", msg: "除了get和post的其他请求" },
  379. ],
  380. /**
  381. * uni bus 过滤类型
  382. */
  383. busFilterType: [
  384. { title: "全部", type: "" },
  385. { title: "on", type: "on" },
  386. { title: "once", type: "once" },
  387. { title: "emit", type: "emit" },
  388. { title: "off", type: "off" },
  389. ],
  390. /**
  391. * 文件类型
  392. */
  393. dirTypeList: [
  394. { title: "_doc", type: "PRIVATE_DOC" },
  395. { title: "_www", type: "PRIVATE_WWW" },
  396. { title: "公共文档", type: "PUBLIC_DOCUMENTS" },
  397. { title: "公共下载", type: "PUBLIC_DOWNLOADS" },
  398. ],
  399. /**
  400. * 缓存类型
  401. */
  402. storageFilterTypeList: [
  403. { title: "localStorage", type: "localStorage" },
  404. { title: "sessionStorage", type: "sessionStorage" },
  405. { title: "cookie", type: "cookie" },
  406. ],
  407. /**
  408. * 等待执行的js代码
  409. */
  410. waitSendCode: "",
  411. /**
  412. * js运行类型
  413. */
  414. jsRunType: jsRunTypeList[0],
  415. jsRunTypeList,
  416. /**
  417. * Vuex变量类型
  418. */
  419. stateTypeList: [
  420. { title: "vuex", type: "vuex" },
  421. { title: "pinia", type: "pinia" },
  422. { title: "globalData", type: "globalData" },
  423. ],
  424. };
  425. },
  426. computed: {
  427. /**
  428. * 错误筛选分类index
  429. */
  430. errorTypeIndex() {
  431. return this.errorTypeList.findIndex((x) => x.type == this.options.errorFilterType);
  432. },
  433. /**
  434. * 日志分类索引
  435. */
  436. consoleTypeListIndex() {
  437. return this.consoleTypeList.findIndex((x) => x.type == this.options.consoleFilterType);
  438. },
  439. /**
  440. * 网络筛选索引
  441. */
  442. networkTypeListIndex() {
  443. return this.networkFilterType.findIndex((x) => x.type == this.options.networkFilterType);
  444. },
  445. /**
  446. * bus分类索引
  447. */
  448. busTypeListIndex() {
  449. return this.busFilterType.findIndex((x) => x.type == this.options.busFilterType);
  450. },
  451. /**
  452. * 文件分类索引
  453. */
  454. fileTypeListIndex() {
  455. return this.dirTypeList.findIndex((x) => x.type == this.options.fileSysDirType);
  456. },
  457. /**
  458. * 缓存类型索引
  459. */
  460. storageTypeListIndex() {
  461. return this.storageFilterTypeList.findIndex((x) => x.type == this.options.storageType);
  462. },
  463. /**
  464. * Vuex变量类型
  465. */
  466. stateTypeListIndex() {
  467. return this.stateTypeList.findIndex((x) => x.type == this.stateType);
  468. },
  469. },
  470. methods: {
  471. /**
  472. * 过滤类型改变
  473. */
  474. filterTypeChange(type) {
  475. this.$emit("filterTypeChange", type);
  476. },
  477. /**
  478. * 错误类型索引改变
  479. */
  480. errorTypeIndexChange(e) {
  481. this.filterTypeChange(this.errorTypeList[e].type);
  482. },
  483. /**
  484. * 日志分类索引改变
  485. */
  486. consoleTypeIndexChange(e) {
  487. this.filterTypeChange(this.consoleTypeList[e].type);
  488. },
  489. /**
  490. * 网络状态筛选改变事件
  491. */
  492. networkTypeIndexChange(e) {
  493. this.filterTypeChange(this.networkFilterType[e].type);
  494. },
  495. /**
  496. * bus筛选改变事件
  497. */
  498. busTypeIndexChange(e) {
  499. this.filterTypeChange(this.busFilterType[e].type);
  500. },
  501. /**
  502. * 文件分类改变事件
  503. */
  504. fileTypeIndexChange(e) {
  505. this.$emit("changeFileDirType", this.dirTypeList[e].type);
  506. },
  507. /**
  508. * 缓存类型改变事件
  509. */
  510. storageTypeIndexChange(e) {
  511. this.$emit("changeStorageType", this.storageFilterTypeList[e].type);
  512. },
  513. /**
  514. * Vuex变量类型改变事件
  515. */
  516. stateTypeIndexChange(e) {
  517. this.$emit("changeStateType", this.stateTypeList[e].type);
  518. },
  519. /**
  520. * 清空日志
  521. */
  522. emptyLogs(type) {
  523. let that = this;
  524. let title = {
  525. error: "报错记录",
  526. console: "console",
  527. network: "请求日志",
  528. pages_1: "页面停留统计",
  529. pages_2: "页面日活统计",
  530. logs: "Logs",
  531. UniBus: "UniBus",
  532. storage: "Storage",
  533. };
  534. // #ifdef H5
  535. if (type == "storage") {
  536. title[type] = this.options.storageType;
  537. }
  538. // #endif
  539. uni.showModal({
  540. title: "警告",
  541. content: `是否确认清空${title[type]}全部数据?`,
  542. success(e) {
  543. if (e.confirm) {
  544. uni.showLoading({
  545. title: "处理中...",
  546. });
  547. if (type == "error") {
  548. devCache.set("errorReport", []);
  549. } else if (type == "console") {
  550. uni.$emit("devTools_delConsoleAll");
  551. } else if (type == "network") {
  552. uni.$emit("devTools_delNetworkAll");
  553. } else if (type == "logs") {
  554. devCache.set("logReport", []);
  555. } else if (type == "UniBus") {
  556. uni.$emit("devTools_delUniBusAll");
  557. } else if (type == "pages_1") {
  558. devCache.set("pageCount", []);
  559. } else if (type == "pages_2") {
  560. devCache.set("dayOnline", []);
  561. } else if (type == "storage") {
  562. that.delStorage();
  563. }
  564. setTimeout(() => {
  565. that.$emit("getPage");
  566. }, 5500);
  567. setTimeout(() => {
  568. uni.hideLoading();
  569. uni.showToast({
  570. title: "清空成功!",
  571. icon: "success",
  572. });
  573. }, 5000);
  574. }
  575. },
  576. });
  577. },
  578. /**
  579. * 清空全部缓存
  580. */
  581. delStorage() {
  582. // #ifdef APP-PLUS
  583. let keys = plus.storage.getAllKeys();
  584. for (let i = 0; i < keys.length; i++) {
  585. const key = String(keys[i]);
  586. if (key.indexOf("devTools_") == 0) {
  587. continue;
  588. }
  589. uni.removeStorageSync(key);
  590. }
  591. // #endif
  592. // #ifdef H5
  593. if (this.options.storageType == "localStorage") {
  594. for (let i = 0; i < localStorage.length; i++) {
  595. let key = String(localStorage.key(i));
  596. if (key.indexOf("devTools_") == 0) {
  597. continue;
  598. }
  599. uni.removeStorageSync(key);
  600. }
  601. } else if (this.options.storageType == "sessionStorage") {
  602. for (let i = 0; i < sessionStorage.length; i++) {
  603. let key = String(sessionStorage.key(i));
  604. if (key.indexOf("devTools_") == 0) {
  605. continue;
  606. }
  607. sessionStorage.removeItem(key);
  608. }
  609. } else if (this.options.storageType == "cookie") {
  610. let keys = [];
  611. document.cookie.split(";").forEach((cookieStr) => {
  612. const [name, value] = cookieStr.trim().split("=");
  613. keys.push(name);
  614. });
  615. keys.map((k) => {
  616. document.cookie = `${k}=;expires=` + new Date(new Date().getTime() + 200).toGMTString() + ";path=/";
  617. });
  618. }
  619. // #endif
  620. // #ifdef MP
  621. let keyList = devCache.get("storage");
  622. if (!keyList) keyList = [];
  623. for (let i = 0; i < keyList.length; i++) {
  624. const key = keyList[i];
  625. if (key.indexOf("devTools_") == 0) {
  626. continue;
  627. }
  628. uni.removeStorageSync(key);
  629. }
  630. // #endif
  631. },
  632. /**
  633. * 清空文件夹
  634. */
  635. emptyFolder() {
  636. let that = this;
  637. if (that.options.fileSysDirType == "PRIVATE_WWW") {
  638. return uni.showToast({
  639. title: "该目录不可删除",
  640. icon: "none",
  641. });
  642. }
  643. uni.showModal({
  644. title: "提示",
  645. content: "是否确认清空全部文件?",
  646. success(res) {
  647. if (res.confirm) {
  648. uni.showLoading({
  649. title: "清空中",
  650. });
  651. let path = "";
  652. switch (that.options.fileSysDirType) {
  653. case "wx":
  654. path = wx.env.USER_DATA_PATH;
  655. break;
  656. case "PRIVATE_DOC":
  657. path = "_doc";
  658. break;
  659. case "PUBLIC_DOCUMENTS":
  660. path = "_documents";
  661. break;
  662. case "PUBLIC_DOWNLOADS":
  663. path = "_downloads";
  664. break;
  665. default:
  666. break;
  667. }
  668. // #ifdef APP-PLUS
  669. appDelDir(path + "/", false)
  670. .then(() => {
  671. uni.hideLoading();
  672. uni.showToast({
  673. title: "清空成功!",
  674. icon: "success",
  675. });
  676. that.$emit("getPage");
  677. })
  678. .catch(() => {
  679. uni.hideLoading();
  680. uni.showToast({
  681. title: "清空失败!",
  682. icon: "none",
  683. });
  684. });
  685. // #endif
  686. // #ifdef MP-WEIXIN
  687. let fs = wx.getFileSystemManager();
  688. fs.rmdir({
  689. dirPath: path + "/",
  690. recursive: true,
  691. success() {
  692. uni.hideLoading();
  693. uni.showToast({
  694. title: "清空成功!",
  695. icon: "success",
  696. });
  697. that.$emit("getPage");
  698. },
  699. fail() {
  700. uni.hideLoading();
  701. uni.showToast({
  702. title: "清空失败!",
  703. icon: "none",
  704. });
  705. },
  706. });
  707. // #endif
  708. }
  709. },
  710. });
  711. },
  712. /**
  713. * 创建文件夹
  714. */
  715. createDir() {
  716. let that = this;
  717. let menu = [
  718. {
  719. text: `新建文件`,
  720. click() {
  721. that.$emit("editDirName", {
  722. isEdit: false,
  723. isDir: false,
  724. });
  725. },
  726. },
  727. {
  728. text: `新建文件夹`,
  729. click() {
  730. that.$emit("editDirName", {
  731. isEdit: false,
  732. isDir: true,
  733. });
  734. },
  735. },
  736. ];
  737. uni.showActionSheet({
  738. itemList: menu.map((x) => x.text),
  739. success({ tapIndex }) {
  740. menu[tapIndex].click();
  741. },
  742. });
  743. },
  744. /**
  745. * 新增缓存
  746. */
  747. addStorage() {
  748. uni.$emit("devTools_showAddStorageDialog");
  749. },
  750. /**
  751. * 执行js
  752. */
  753. runJs() {
  754. let that = this;
  755. if (this.waitSendCode == "") {
  756. return uni.showToast({
  757. title: "请先输入需要执行的js代码",
  758. icon: "none",
  759. });
  760. } else {
  761. let code = String(this.waitSendCode);
  762. this.$emit("runJs", { code, type: that.jsRunType });
  763. this.waitSendCode = "";
  764. }
  765. },
  766. /**
  767. * 获取历史代码运行记录
  768. */
  769. showHisCode() {
  770. let that = this;
  771. let his = devCache.get("codeRunHis");
  772. if (!his) his = [];
  773. if (his.length == 0) {
  774. return uni.showToast({
  775. title: "暂无记录!",
  776. icon: "none",
  777. });
  778. }
  779. that.$refs.codeHisPicker.show(his).then((res) => {
  780. that.waitSendCode = res;
  781. });
  782. },
  783. /**
  784. * 跳转指定页面
  785. */
  786. goPage() {
  787. uni.$emit("devTools_showRouteDialog");
  788. },
  789. },
  790. };
  791. </script>
  792. <style lang="scss" scoped>
  793. .bottomTools {
  794. position: fixed;
  795. z-index: 3;
  796. bottom: 0;
  797. left: 0;
  798. width: 750rpx;
  799. border-top: 1px solid rgba(0, 0, 0, 0.05);
  800. background-color: #fff;
  801. padding-top: 15rpx;
  802. padding-left: 20rpx;
  803. padding-right: 20rpx;
  804. display: flex;
  805. flex-wrap: wrap;
  806. flex-direction: row;
  807. align-items: center;
  808. .mr {
  809. margin-right: 20rpx;
  810. }
  811. .mt {
  812. margin-left: 20rpx;
  813. }
  814. .ml {
  815. margin-left: 20rpx;
  816. }
  817. .miniBtn {
  818. height: 40rpx;
  819. border-radius: 8rpx;
  820. padding: 0 10rpx;
  821. border: 1px solid rgba(0, 0, 0, 0.05);
  822. &.warn {
  823. background-color: rgb(255, 251, 229);
  824. }
  825. &.primary {
  826. background-color: #ecf5ff;
  827. }
  828. .miniBtnText {
  829. font-size: 20rpx;
  830. height: 40rpx;
  831. line-height: 40rpx;
  832. }
  833. }
  834. }
  835. .dirList {
  836. display: flex;
  837. flex-direction: row;
  838. align-items: center;
  839. width: 710rpx;
  840. height: 34rpx;
  841. margin-bottom: 10rpx;
  842. /* #ifndef APP-PLUS */
  843. white-space: nowrap;
  844. /* #endif */
  845. .dirScrollItem {
  846. display: flex;
  847. flex-direction: row;
  848. align-items: center;
  849. height: 34rpx;
  850. }
  851. .dirItem {
  852. display: flex;
  853. flex-direction: row;
  854. align-items: center;
  855. }
  856. .delimiter {
  857. color: #999;
  858. margin: 0 6rpx;
  859. font-size: 22rpx;
  860. line-height: 34rpx;
  861. }
  862. .dirName {
  863. color: #333;
  864. font-size: 22rpx;
  865. line-height: 34rpx;
  866. height: 34rpx;
  867. padding: 0 6rpx;
  868. background-color: rgba(0, 0, 0, 0.02);
  869. border-radius: 6rpx;
  870. }
  871. }
  872. .jsRunnerTools {
  873. display: flex;
  874. flex-direction: column;
  875. width: 710rpx;
  876. .runOptions {
  877. display: flex;
  878. flex-direction: row;
  879. align-items: center;
  880. width: 710rpx;
  881. justify-content: space-between;
  882. padding-bottom: 10rpx;
  883. .radiusList {
  884. display: flex;
  885. flex-direction: row;
  886. align-items: center;
  887. .runType {
  888. font-size: 20rpx;
  889. line-height: 24rpx;
  890. color: #333;
  891. }
  892. .radiusItem {
  893. display: flex;
  894. flex-direction: row;
  895. align-items: center;
  896. margin-left: 10rpx;
  897. .radiusText {
  898. font-size: 20rpx;
  899. line-height: 24rpx;
  900. color: #333;
  901. }
  902. .radiusRadio {
  903. transform: scale(0.5);
  904. }
  905. }
  906. }
  907. .hisEmpty {
  908. display: flex;
  909. flex-direction: row;
  910. align-items: center;
  911. .hisEmptyIcon {
  912. width: 16rpx;
  913. height: 16rpx;
  914. }
  915. .hisEmptyText {
  916. font-size: 20rpx;
  917. margin-left: 5rpx;
  918. color: #ff2d55;
  919. }
  920. }
  921. .logList {
  922. // margin-right: 120rpx;
  923. display: flex;
  924. flex-direction: row;
  925. align-items: center;
  926. .hisText {
  927. font-size: 20rpx;
  928. color: #777;
  929. line-height: 24rpx;
  930. margin-right: 5rpx;
  931. }
  932. .unfold {
  933. width: 24rpx;
  934. height: 24rpx;
  935. }
  936. }
  937. }
  938. .code {
  939. display: flex;
  940. flex-direction: row;
  941. align-items: center;
  942. justify-content: space-between;
  943. width: 710rpx;
  944. .codeInput {
  945. width: 590rpx;
  946. height: 100rpx;
  947. font-size: 20rpx;
  948. line-height: 28rpx;
  949. color: #333;
  950. padding: 10rpx;
  951. background-color: rgba(0, 0, 0, 0.03);
  952. border-radius: 15rpx;
  953. }
  954. .codeSend {
  955. width: 100rpx;
  956. height: 100rpx;
  957. border-radius: 15rpx;
  958. border: 1px solid #ff2d55;
  959. display: flex;
  960. flex-direction: row;
  961. align-items: center;
  962. justify-content: center;
  963. .codeSendText {
  964. color: #ff2d55;
  965. font-size: 24rpx;
  966. font-weight: bold;
  967. }
  968. }
  969. .codeSend:active {
  970. background-color: rgba(0, 0, 0, 0.03);
  971. }
  972. }
  973. }
  974. .menuBtn {
  975. }
  976. </style>