Ver código fonte

提交弹窗ui

xbx 6 meses atrás
pai
commit
7b540dea9c

+ 4 - 1
README.md

@@ -1,4 +1,4 @@
-# vue-chrome3-demo
+# 智投视频采集插件
 
 ## Project setup
 ```
@@ -22,3 +22,6 @@ npm run lint
 
 ### Customize configuration
 See [Configuration Reference](https://cli.vuejs.org/config/).
+
+### v3manifest
+v3 +webpack5 暂时无法在外网找到热更新的解决方案 暂时参考友商 使用v2 开发 v3配置留作备份 ,方便后续 chrome停止v2插件以后  无缝切换到v3

+ 13 - 3
package.json

@@ -1,16 +1,22 @@
 {
-  "name": "vue-chrome3-demo",
+  "name": "zt-chrome3-extension",
   "version": "0.1.0",
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
-    "build": "vue-cli-service build",
+    "test": "vue-cli-service build  --mode=development",
+    "build": "vue-cli-service build --watch",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
     "copy-webpack-plugin": "^11.0.0",
     "core-js": "^3.8.3",
+    "css-loader": "^7.1.2",
+    "html-webpack-plugin": "^5.6.0",
+    "less": "^4.2.0",
+    "less-loader": "^12.2.0",
     "mini-css-extract-plugin": "^2.9.1",
+    "style-loader": "^4.0.0",
     "vue": "^3.2.13"
   },
   "devDependencies": {
@@ -19,11 +25,15 @@
     "@vue/cli-plugin-babel": "~5.0.0",
     "@vue/cli-plugin-eslint": "~5.0.0",
     "@vue/cli-service": "~5.0.0",
+    "autoprefixer": "^10.4.20",
     "element-plus": "^2.8.5",
     "eslint": "^7.32.0",
     "eslint-plugin-vue": "^8.0.3",
+    "postcss": "^8.4.47",
+    "postcss-loader": "^8.1.1",
     "unplugin-auto-import": "^0.16.1",
-    "unplugin-vue-components": "^0.25.2"
+    "unplugin-vue-components": "^0.25.2",
+    "webpack-ext-reloader": "^1.1.13"
   },
   "eslintConfig": {
     "root": true,

Diferenças do arquivo suprimidas por serem muito extensas
+ 761 - 120
pnpm-lock.yaml


+ 17 - 0
postcss.config.js

@@ -0,0 +1,17 @@
+
+module.exports = {
+    plugins: {
+      // 兼容浏览器,添加前缀
+      'autoprefixer':{
+          overrideBrowserslist: [
+            "Android 4.1",
+            "iOS 7.1",
+            "Chrome > 31",
+            "ff > 31",
+            "ie >= 8"
+            //'last 10 versions', // 所有主流浏览器最近2个版本
+        ],
+        grid: true
+      }
+    }
+}

+ 3 - 3
script/replaceCssPlugin.js

@@ -11,13 +11,13 @@ class ReplaceCssPlugin {
         // 遍历所有编译后的资源
         Object.keys(compilation.assets).forEach((filename) => {
           if (filename.endsWith(".css")) {
-            console.log(filename, "222");
             // 替换:root 变为:host 支持沙盒不然 element css 不生效
             const originalContent = compilation.assets[filename].source();
-            const replacedContent = originalContent.replace(
+            //这node-sass 有buffer类型所以排除一下
+            const replacedContent = originalContent && !Buffer.isBuffer(originalContent) ? originalContent.replace(
               /:root\{/g,
               ":root,:host{"
-            );
+            ): originalContent;
 
             // 重写资源内容
             compilation.assets[filename] = {

+ 4 - 0
src/assets/css/default.less

@@ -0,0 +1,4 @@
+
+
+
+@bg-size: 100px

+ 79 - 0
src/assets/css/index.css

@@ -0,0 +1,79 @@
+
+* {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+}
+
+
+body,
+div,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+pre,
+code,
+form,
+fieldset,
+legend,
+input,
+button,
+textarea,
+p,
+blockquote,
+th,
+td a {
+    margin: 0;
+    padding: 0;
+}
+
+body {
+    font-family: "微软雅黑", "宋体", "Arial";
+    color: #333;
+}
+
+
+
+img,
+input {
+    border: none;
+}
+
+
+
+input,
+select,
+textarea {
+    outline: none;
+}
+
+select,
+input,
+img {
+    vertical-align: middle;
+}
+
+ul,
+ol,
+li {
+    list-style-type: none;
+}
+
+a {
+    text-decoration: none;
+    color: #72ace3;
+}
+
+a:focus {
+    outline: none;
+    -moz-outline: none
+}

BIN
src/assets/img/error.png


BIN
src/assets/img/reload.png


BIN
src/assets/img/success.png


BIN
src/assets/img/wating.png


BIN
src/assets/logo.png


+ 2 - 2
src/content/App.vue

@@ -1,10 +1,10 @@
 <template>
   <div data-root="true" class="root1">
-    <el-button type="primary" @click="handleOpen">点我点我</el-button>
+    <el-button type="primary" @click="handleOpen">点我点我2</el-button>
 
     <el-dialog
       v-model="dialogVisible"
-      title="我是标题"
+      title="我是标题2"
       width="30%"
       :before-close="handleClose"
     >

+ 9 - 6
src/content/index.js

@@ -11,13 +11,16 @@ import App from "./App.vue";
   const container = document.createElement("div");
   container.id = rootIdName;
   const root = document.createElement("div");
-  const styleEl = document.createElement("link");
   const shadowDOM = container.attachShadow({ mode: "open" }) || container;
-  styleEl.setAttribute("rel", "stylesheet");
-  let url = chrome.runtime.getURL("css/chunk-vendors.css");
-
-  styleEl.setAttribute("href", url);
-  shadowDOM.appendChild(styleEl);
+ const cssList = ["css/chunk-vendors.css",'css/content.css'];
+ for(let i=0;i<cssList.length;i++){
+   let styleEl = document.createElement("link");
+   styleEl.setAttribute("rel", "stylesheet");
+   let url = chrome.runtime.getURL(cssList[i]);
+   styleEl.setAttribute("href", url);
+   console.log(styleEl,'styleElstyleElstyleEl')
+   shadowDOM.appendChild(styleEl);
+ }
   shadowDOM.appendChild(root);
   document.body.appendChild(container);
 

+ 33 - 0
src/hooks/pagination.js

@@ -0,0 +1,33 @@
+import { ref, watch, reactive } from 'vue';
+
+/**
+ * 判断是否加载下一页的hooks
+ */
+const usePagination = () => {
+  const meta = ref<any>({
+    current_page: 0,
+    per_page: 10,
+    total: 0,
+  });
+
+  const tablePageOptions = reactive({
+    current: meta.value.current_page,
+    pageSize: meta.value.per_page,
+    total: meta.value.total,
+    showTotal: true,
+    showJumper: true,
+  });
+
+  watch(
+    () => meta.value,
+    () => {
+      tablePageOptions.current = meta.value.current_page;
+      tablePageOptions.pageSize = meta.value.per_page;
+      tablePageOptions.total = meta.value.total;
+    }
+  );
+
+  return { meta, tablePageOptions };
+};
+
+export default usePagination;

+ 19 - 22
src/manifest.json

@@ -1,40 +1,37 @@
 {
-  "manifest_version": 3,
-  "name": "视频下载插件",
-  "description": "chromeMV3",
+  "manifest_version": 2,
+  "name": "智投视频采集插件",
+  "description": "chromeMV2",
   "version": "1.0.0",
   "icons": {
     "48": "assets/logo.png",
     "128": "assets/logo.png"
   },
-  "action": {
-    "default_icon": {
-      "19": "assets/logo.png",
-      "38": "assets/logo.png"
-    },
-    "default_popup": "popup.html",
-    "default_title": "my-chrome-vue"
-  },
+  "browser_action": {
+		"default_title": "视频采集插件",
+		"default_icon": "assets/logo.png",
+		"default_popup": "popup.html"
+	},
   "background": {
     "service_worker": "js/background.js"
+    
   },
   "content_scripts": [
     {
       "matches": ["http://*/*", "https://*/*"],
       "js": ["js/content.js","js/chunk-vendors.js"],
       "css": ["css/content.css", "css/chunk-vendors.css"],
-      "run_at": "document_end"
+      "run_at": "document_idle"
     }
   ],
   "host_permissions": ["http://*/*", "https://*/*"],
-  "permissions": ["contextMenus", "tabs", "notifications", "storage"],
-  "content_security_policy": {
-    "extension_pages": "script-src 'self'; object-src 'self';style-src 'self'; "
-  },
-  "web_accessible_resources": [
-    {
-      "resources": ["js/content.js", "js/chunk-vendors.js","css/content.css","css/chunk-vendors.css"],
-      "matches": ["http://*/*", "https://*/*"]
-    }
-  ]
+  "permissions": [
+		"webRequest",
+    "webRequestBlocking",
+		"storage",
+    "http://*/*",
+    "https://*/*"
+	],
+  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
+  "web_accessible_resources": ["js/content.js", "js/chunk-vendors.js","css/content.css","css/chunk-vendors.css"]
 }

+ 199 - 11
src/popup/App.vue

@@ -1,20 +1,208 @@
 <template>
-  <div class="popup">
-    <el-button type="primary"  data-root="true" class="root222" @click="handleClick"
-      >快来点我~~</el-button
-    >
-    <div>{{ counter }}</div>
+  <div class="zt-popup">
+    <div class="zt-content__header">
+      <div class="zt-content__title">
+        <img src="../assets/logo.png" />
+        <span>灵感库{{ version }}</span>
+      </div>
+      <el-button type="primary" @click="handleClick" link size="small">
+        进入灵感库
+      </el-button>
+    </div>
+
+    <el-tabs v-model="activeTab" class="zt-tabs" @tab-click="handleClick">
+      <el-tab-pane label="收集中" name="collect"></el-tab-pane>
+      <el-tab-pane label="收集失败" name="fail"></el-tab-pane>
+      <el-tab-pane label="已完成" name="success"></el-tab-pane>
+    </el-tabs>
+
+    <div>
+      <ul
+        v-infinite-scroll="loadMore"
+        class="zt-materia__list"
+        style="overflow: auto"
+      >
+        <li
+          v-for="item in dataList"
+          :key="item.id"
+          class="zt-materia__list-item"
+        >
+          <p class="zt-materia__title">{{ item.title }}</p>
+          <el-button
+            type="primary"
+            link
+            bg
+            @click="goLink(item.url)"
+            size="small"
+          >
+            {{ item.url }}
+          </el-button>
+          <div class="zt-materia__status">
+            <div class="zt-materia__left">
+              <template v-if="item.status == 'fail'">
+                <img src="../assets/img/error.png" />
+                <span
+                  class="zt-materia__status-text"
+                  :class="{ 'is-error': item.status == 'fail' }"
+                  >采集错误</span
+                >
+              </template>
+              <template v-else-if="item.status == 'success'">
+                <img src="../assets/img/success.png" />
+                <span class="zt-materia__status-text">采集成功 </span>
+              </template>
+              <template v-esle>
+                <img src="../assets/img/wating.png" />
+                <span class="zt-materia__status-text"> 采集等待~ </span>
+              </template>
+            </div>
+            <div class="zt-materia__right" v-if="item.status == 'fail'">
+              <img src="../assets/img/reload.png" />
+              重试
+            </div>
+          </div>
+        </li>
+      </ul>
+    </div>
+    <div class="zt-empty">
+      <el-empty :image-size="40" description="暂无数据" />
+    </div>
   </div>
 </template>
 
 <script setup>
-import { ref } from 'vue'
-const counter = ref(10086)
+import { ref } from "vue";
+
+const activeTab = ref("fail");
+const version = require("../../package.json").version;
+
+//
+const dataList = ref([
+  {
+    title: "灵感1-抖音1008232抖音1008232抖音1008232抖音1008232",
+    url: "http://www.baidu.com",
+    status: "fail",
+    id: 1,
+  },
+  {
+    title: "灵感2",
+    url: "http://www.baidu.com",
+    status: "fail",
+    id: 2,
+  },
+  {
+    title: "灵感3",
+    url: "http://www.baidu.com",
+    status: "fail",
+    id: 3,
+  },
+  {
+    title: "灵感4",
+    url: "http://www.douyin.com",
+    status: "success",
+    id: 4,
+  },
+  {
+    title: "灵感5",
+    url: "http://www.bilibili.com",
+    status: "success",
+    id: 5,
+  },
+]);
+
+const handleClick = () => {
+  console.log("2222");
+};
+
+const goLink = (url) => {
+  window.open(url, "_blank");
+};
+
+//加在更多
+const loadMore = () => {};
 </script>
 
-<style scoped>
-.root222 {
-  font-size: 20px;
+<style scoped lang="less">
+.zt-popup {
+  padding: 10px 12px;
+  width: 350px;
+  .zt-content__header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .zt-content__title {
+      display: inline-flex;
+      flex: 1;
+      align-items: center;
+      > img {
+        width: 24px;
+        height: 24px;
+      }
+      > span {
+        margin-left: 8px;
+        font-size: 14px;
+        font-weight: bold;
+      }
+    }
+  }
+  .zt-tabs {
+    margin-top: 10px;
+    .el-tabs__header .el-tabs__item:nth-child(2) {
+      padding-left: 15px;
+    }
+    .el-tabs__header {
+      margin-bottom: 10px;
+    }
+  }
+}
+
+.zt-materia {
+  &__list {
+    .zt-materia__list-item {
+      background: #e6e6fa;
+      padding: 7px 9px;
+      margin-bottom: 10px;
+      border-radius: 4px;
+      .zt-materia__title {
+        font-weight: bold;
+        font-size: 13px;
+        margin-bottom: 2px;
+      }
+      .zt-materia__status {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-top: 3px;
+        .zt-materia__left,
+        .zt-materia__right {
+          display: flex;
+          align-items: center;
+          color: #409eff;
+        }
+
+        img {
+          width: 13px;
+          height: 13px;
+          margin-right: 4px;
+        }
+
+        .zt-materia__status-text {
+          color: #409eff;
+        }
 
+        .is-error {
+          color: #fd555d;
+        }
+      }
+      > p {
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+  }
 }
-</style>
+</style>

+ 1 - 1
src/popup/index.html

@@ -5,7 +5,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title>vue-chrome-extension</title>
+    <title>视频下载插件</title>
   </head>
   <body>
     <noscript>

+ 1 - 1
src/popup/index.js

@@ -1,4 +1,4 @@
 import { createApp } from 'vue'
 import App from './App.vue'
-
+import '@/assets/css/index.css'
 createApp(App).mount('#app')

+ 38 - 0
v2manifest.json

@@ -0,0 +1,38 @@
+{
+    "manifest_version": 2,
+    "name": "智投视频采集插件",
+    "description": "智投视频采集插件",
+    "version": "1.0.0",
+    "icons": {
+      "48": "assets/logo.png",
+      "128": "assets/logo.png"
+    },
+    "browser_action": {
+          "default_title": "视频采集插件",
+          "default_icon": "assets/logo.png",
+          "default_popup": "popup.html"
+      },
+    "background": {
+      "service_worker": "js/background.js"
+      
+    },
+    "content_scripts": [
+      {
+        "matches": ["http://*/*", "https://*/*"],
+        "js": ["js/content.js","js/chunk-vendors.js"],
+        "css": ["css/content.css", "css/chunk-vendors.css"],
+        "run_at": "document_idle"
+      }
+    ],
+    "host_permissions": ["http://*/*", "https://*/*"],
+    "permissions": [
+          "webRequest",
+      "webRequestBlocking",
+          "storage",
+      "http://*/*",
+      "https://*/*"
+      ],
+    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
+    "web_accessible_resources": ["js/content.js", "js/chunk-vendors.js","css/content.css","css/chunk-vendors.css"]
+  }
+  

+ 41 - 0
v3manifest.json

@@ -0,0 +1,41 @@
+{
+    "manifest_version": 3,
+    "name": "智投视频采集插件",
+    "description": "chromeMV2",
+    "version": "1.0.0",
+    "icons": {
+      "48": "assets/logo.png",
+      "128": "assets/logo.png"
+    },
+    "action": {
+      "default_icon": {
+        "19": "assets/logo.png",
+        "38": "assets/logo.png"
+      },
+      "default_popup": "popup.html",
+      "default_title": "智投视频采集插件"
+    },
+    "background": {
+      "service_worker": "js/background.js"
+    },
+    "content_scripts": [
+      {
+        "matches": ["http://*/*", "https://*/*"],
+        "js": ["js/content.js","js/chunk-vendors.js"],
+        "css": ["css/content.css", "css/chunk-vendors.css"],
+        "run_at": "document_end"
+      }
+    ],
+    "host_permissions": ["http://*/*", "https://*/*"],
+    "permissions": ["contextMenus", "tabs", "notifications", "storage"],
+    "content_security_policy": {
+      "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';style-src 'self'; "
+    },
+    "web_accessible_resources": [
+      {
+        "resources": ["js/content.js", "js/chunk-vendors.js","css/content.css","css/chunk-vendors.css"],
+        "matches": ["http://*/*", "https://*/*"]
+      }
+    ]
+  }
+  

+ 55 - 6
vue.config.js

@@ -2,9 +2,8 @@ const CopyWebpackPlugin = require("copy-webpack-plugin");
 const AutoImport = require("unplugin-auto-import/webpack");
 const Components = require("unplugin-vue-components/webpack");
 const { ElementPlusResolver } = require("unplugin-vue-components/resolvers");
-const MiniCssExtractPlugin = require("mini-css-extract-plugin");
-const webpack = require('webpack');
-const StringReplacePlugin = require("string-replace-webpack-plugin");
+const ExtReloader = require('webpack-ext-reloader');
+
 
 const ReplaceCssPlugin = require("./script/replaceCssPlugin.js");
 
@@ -28,7 +27,16 @@ const plugins = [
   new CopyWebpackPlugin({
     patterns: copyFiles,
   }),
-
+  //仅支持webpack4.x 不支持5.x 需要自己手动改造5.x版本
+  /* new ExtReloader({
+    port: 9091, // Which port use to create the server
+      reloadPage: true, // Force the reload of the page also
+      entries: { // The entries used for the content/background scripts or extension pages
+        contentScript: 'content',
+        background: 'background',
+        extensionPage: 'popup',
+      },
+  }), */
   new  ReplaceCssPlugin(),
   AutoImport({
     include: [
@@ -78,19 +86,32 @@ chromeName.forEach((name) => {
 });
 
 module.exports = {
+  
   pages,
   // 生产环境是否生成 sourceMap 文件
   productionSourceMap: false,
-
+  /* pluginOptions: {
+    'style-resources-loader': {
+      preProcessor: 'less',
+      patterns: [path.resolve(__dirname, './src/assets/css/default.less')]
+    }
+  }, */
   configureWebpack: {
     // 多入口打包
     entry: {
       content: "./src/content/index.js",
       background: "./src/background/index.js",
     },
+    resolve:{
+      alias:{
+        '@': path.resolve('src'),
+      }
+    },
+    
     output: {
       filename: "js/[name].js",
     },
+    
     plugins,
     optimization: {
       splitChunks: {
@@ -116,10 +137,38 @@ module.exports = {
       },
     },
   },
-  chainWebpack: (config) => {},
+
+  //配置less解析和浏览器自动补全前缀
+  chainWebpack: (config) => {
+    config.module.rule('less')
+      .test(/\.less$/)
+      .use('style-loader')
+        .loader('style-loader')
+      .end()
+      .use('css-loader')
+        .loader('css-loader')
+      .end()
+      .use('postcss-loader')
+      .loader('postcss-loader')
+    .end()
+      .use('less-loader')
+        .loader('less-loader')
+      .end()
+  },
   css: {
     extract: {
       filename: "css/[name].css",
     },
   },
+  /* devServer:{
+
+    host: '0.0.0.0', // 让你的服务器可以被外部访问
+    port: 8080, // 端口
+    https: false, // 不使用 HTTP 提供服务
+    hot: true, 
+    onBeforeSetupMiddleware: function(app, server,compiler) {
+      // 在服务器启动之前执行的函数
+      console.log(compiler,'compilercompilercompiler')
+    },
+  } */
 };