11 Commits

Author SHA1 Message Date
duanshuwen
f780cb9da0 feat: 合并lishaohua分支 2025-12-06 23:43:40 +08:00
duanshuwen
0fe4dbe2ab feat: 新增组件 2025-12-06 23:42:48 +08:00
duanshuwen
5dc7d73120 feat: 分页插件组件封装 2025-12-06 10:38:35 +08:00
duanshuwen
d0162e3349 feat: 新增分页组件 2025-12-05 13:44:27 +08:00
duanshuwen
6596106da9 feat: 新增UI组件插件 2025-12-05 10:53:27 +08:00
31b68f88a6 feat: 任务列表开发 2025-12-03 17:20:05 +08:00
duanshuwen
f0097b84d1 feat: 评价页面搭建 2025-12-02 22:42:15 +08:00
duanshuwen
008f262470 feat: 新增评价页面 2025-12-01 22:29:26 +08:00
duanshuwen
c1b6efc1e9 feat: 优化配置 2025-12-01 22:22:37 +08:00
duanshuwen
ae19c6c551 feat: 新增页面布局 2025-12-01 22:16:34 +08:00
duanshuwen
edd8b939d3 feat: 更新公司名称 2025-11-27 22:17:41 +08:00
34 changed files with 710 additions and 29 deletions

17
.editorconfig Normal file
View File

@@ -0,0 +1,17 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
tab_width = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
insert_final_newline = false

1
.npmrc
View File

@@ -1,2 +1,3 @@
# registry=https://registry.npmmirror.com
electron_mirror=https://npmmirror.com/mirrors/electron/ electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

160
package-lock.json generated
View File

@@ -14,6 +14,7 @@
"bytenode": "^1.5.7", "bytenode": "^1.5.7",
"crypto": "^1.0.1", "crypto": "^1.0.1",
"electron-squirrel-startup": "^1.0.1", "electron-squirrel-startup": "^1.0.1",
"element-plus": "^2.12.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"pinia": "^2.3.1", "pinia": "^2.3.1",
@@ -108,6 +109,15 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
"integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/@electron-forge/cli": { "node_modules/@electron-forge/cli": {
"version": "7.10.2", "version": "7.10.2",
"resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.10.2.tgz", "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.10.2.tgz",
@@ -935,6 +945,15 @@
"node": ">=14.14" "node": ">=14.14"
} }
}, },
"node_modules/@element-plus/icons-vue": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
"integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
"license": "MIT",
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.25.12", "version": "0.25.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
@@ -1440,6 +1459,31 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
} }
}, },
"node_modules/@floating-ui/core": {
"version": "1.7.3",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.3.tgz",
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.4",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.4.tgz",
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.7.3",
"@floating-ui/utils": "^0.2.10"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.10",
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz",
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
"license": "MIT"
},
"node_modules/@gar/promisify": { "node_modules/@gar/promisify": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
@@ -1885,6 +1929,17 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0" "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
} }
}, },
"node_modules/@popperjs/core": {
"name": "@sxzz/popperjs-es",
"version": "2.11.7",
"resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@remixicon/vue": { "node_modules/@remixicon/vue": {
"version": "4.7.0", "version": "4.7.0",
"resolved": "https://registry.npmjs.org/@remixicon/vue/-/vue-4.7.0.tgz", "resolved": "https://registry.npmjs.org/@remixicon/vue/-/vue-4.7.0.tgz",
@@ -2647,14 +2702,12 @@
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/lodash-es": { "node_modules/@types/lodash-es": {
"version": "4.17.12", "version": "4.17.12",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/lodash": "*" "@types/lodash": "*"
@@ -3604,6 +3657,12 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
"license": "MIT"
},
"node_modules/asynckit": { "node_modules/asynckit": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -4520,6 +4579,12 @@
"node": ">=4.0" "node": ">=4.0"
} }
}, },
"node_modules/dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
"license": "MIT"
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.4.3", "version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -5310,6 +5375,73 @@
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
}, },
"node_modules/element-plus": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.12.0.tgz",
"integrity": "sha512-M9YLSn2np9OnqrSKWsiXvGe3qnF8pd94+TScsHj1aTMCD+nSEvucXermf807qNt6hOP040le0e5Aft7E9ZfHmA==",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.2",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.17.20",
"@types/lodash-es": "^4.17.12",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.19",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.3",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/element-plus/node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==",
"license": "MIT"
},
"node_modules/element-plus/node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"license": "MIT",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -8249,7 +8381,6 @@
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash-es": { "node_modules/lodash-es": {
@@ -8258,6 +8389,17 @@
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
"license": "MIT",
"peerDependencies": {
"@types/lodash-es": "*",
"lodash": "*",
"lodash-es": "*"
}
},
"node_modules/lodash.get": { "node_modules/lodash.get": {
"version": "4.4.2", "version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
@@ -8523,6 +8665,12 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
"license": "MIT"
},
"node_modules/merge-stream": { "node_modules/merge-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -8935,6 +9083,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
"license": "BSD-3-Clause"
},
"node_modules/npm-run-path": { "node_modules/npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",

View File

@@ -54,6 +54,7 @@
"bytenode": "^1.5.7", "bytenode": "^1.5.7",
"crypto": "^1.0.1", "crypto": "^1.0.1",
"electron-squirrel-startup": "^1.0.1", "electron-squirrel-startup": "^1.0.1",
"element-plus": "^2.12.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"pinia": "^2.3.1", "pinia": "^2.3.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,30 @@
<template>
<div class="w-[80px] h-full box-border pt-[12px] pb-[12px] flex flex-col items-center justify-center">
<div :class="['flex flex-col gap-[16px]', {'mt-auto mb-[8px] shrink-1': item.id === 7}]" v-for="(item) in menus" :key="item.id">
<div :class="['cursor-pointer flex flex-col items-center justify-center']" @click="handleClick(item)">
<div :class="['box-border rounded-[16px] p-[8px]', {'bg-white': item.id === currentId}]">
<component :is="item.icon" :color="item.id === currentId ? item.activeColor : item.color" :class="['w-[32px] h-[32px]']" />
</div>
<div :class="['text-[14px] mt-[4px] mb-[8px]', item.id === currentId ? `text-[${item.activeColor}]` : item.color]">
{{ item.name }}
</div>
</div>
</div>
<div class="w-[48px] h-[48px] rounded-full overflow-hidden">
<img class="w-full h-full object-cover" src="@assets/images/login/black_logo.png" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { menus } from '@constant/menus'
const currentId = ref(null)
const handleClick = (item: any) => {
currentId.value = item.id
}
</script>
<style></style>

View File

@@ -0,0 +1,49 @@
<template>
<el-pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" class="mt-[15px]"
:pager-count="5" :page-sizes="pageSizes" :current-page="current" background :page-size="size" :layout="layout"
:total="total">
</el-pagination>
</template>
<script setup lang="ts" name="pagination">
const emit = defineEmits(['sizeChange', 'currentChange']);
const props = defineProps({
current: {
type: Number,
default: 1,
},
size: {
type: Number,
default: 10,
},
total: {
type: Number,
default: 0,
},
pageSizes: {
type: Array as () => number[],
default: () => {
return [10, 20, 50, 100, 200];
},
},
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper',
},
});
// 分页改变
const sizeChangeHandle = (val: number) => {
emit('sizeChange', val);
};
// 分页改变
const currentChangeHandle = (val: number) => {
emit('currentChange', val);
};
</script>
<style scoped>
:deep(.el-pagination__sizes) {
margin-left: auto;
}
</style>

View File

@@ -0,0 +1,9 @@
<template>
<div class="task-list w-[392px] h-full rounded-[16px] bg-white">
<slot></slot>
</div>
</template>
<script setup lang="ts"></script>
<style></style>

View File

@@ -0,0 +1,62 @@
import { RiHomeLine, RiFileListLine, RiHotelLine, RiChatQuoteLine, RiBarChartBoxAiLine, RiMoreLine, RiSettingsLine } from '@remixicon/vue'
// 菜单列表申明
export interface MenuItem {
id: number
name: string
icon: any
color: string
activeColor: string
}
export const menus: MenuItem[] = [
{
id: 1,
name: '首页',
icon: RiHomeLine,
color: '#525866',
activeColor: '#2B7FFF',
},
{
id: 2,
name: '订单',
icon: RiFileListLine,
color: '#525866',
activeColor: '#2B7FFF',
},
{
id: 3,
name: '库存',
icon: RiHotelLine,
color: '#525866',
activeColor: '#2B7FFF',
},
{
id: 4,
name: '评价',
icon: RiChatQuoteLine,
color: '#525866',
activeColor: '#2B7FFF',
},
{
id: 5,
name: '数据看板',
icon: RiBarChartBoxAiLine,
color: '#525866',
activeColor: '#2B7FFF',
},
{
id: 6,
name: '更多',
icon: RiMoreLine,
color: '#525866',
activeColor: '#2B7FFF',
},
{
id: 7,
name: '设置',
icon: RiSettingsLine,
color: '#525866',
activeColor: '#2B7FFF',
},
]

View File

@@ -0,0 +1,52 @@
import xc from '@assets/images/rate/xc.png'
import qne from '@assets/images/rate/qne.png'
import fz from '@assets/images/rate/fz.png'
import mt from '@assets/images/rate/mt.png'
import dy from '@assets/images/rate/dy.png'
// 菜单列表申明
interface Item {
id: number
name: string
icon: any
total: number,
score: number
}
export const channels: Item[] = [
{
id: 1,
name: '携程',
icon: xc,
total: 110,
score: 4.5
},
{
id: 2,
name: '去哪儿',
icon: qne,
total: 100,
score: 4.5
},
{
id: 3,
name: '飞猪',
icon: fz,
total: 90,
score: 4.5
},
{
id: 4,
name: '美团',
icon: mt,
total: 80,
score: 4.5
},
{
id: 5,
name: '抖音',
icon: dy,
total: 70,
score: 4.5
}
]

View File

@@ -1,2 +1,7 @@
declare module "@store/counter"; declare module "@store/counter";
declare module "@utils/request"; declare module "@utils/request";
declare module "@assets/images/*";
declare module "@constant/rate";
declare module "@constant/menus";
declare module "@remixicon/vue";
declare module "vue-router";

View File

@@ -6,3 +6,7 @@ body {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.bg {
background: linear-gradient( 180deg, #EFF6FF 0%, #F5F7FA 40%);
}

View File

@@ -0,0 +1,18 @@
<template>
<div class="bg box-border w-full h-screen flex pt-[8px] pb-[8px] pl-[8px]">
<div class="flex-1 h-full">
<slot></slot>
</div>
<TaskList>
<slot name="task"></slot>
</TaskList>
<Menus />
</div>
</template>
<script setup lang="ts" name="Layout">
import TaskList from '@/components/TaskList/index.vue'
import Menus from '@/components/Menus/index.vue'
</script>

View File

@@ -3,6 +3,10 @@ import { createApp } from "vue";
import { createPinia } from "pinia"; import { createPinia } from "pinia";
import router from "./router"; import router from "./router";
import App from "./App.vue"; import App from "./App.vue";
import Layout from "./layout/index.vue";
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
// 创建 Vue 应用实例 // 创建 Vue 应用实例
const app = createApp(App); const app = createApp(App);
@@ -10,8 +14,14 @@ const app = createApp(App);
// 使用 Pinia 状态管理 // 使用 Pinia 状态管理
app.use(createPinia()); app.use(createPinia());
// 注册 Layout 组件
app.component('Layout', Layout);
// 使用 Vue Router // 使用 Vue Router
app.use(router); app.use(router);
app.use(ElementPlus, {
locale,
})
// 挂载应用到 DOM // 挂载应用到 DOM
app.mount("#app"); app.mount("#app");

View File

@@ -12,6 +12,18 @@ const routes = [
component: () => import("@/views/browser/BrowserLayout.vue"), component: () => import("@/views/browser/BrowserLayout.vue"),
meta: { requiresAuth: true }, meta: { requiresAuth: true },
}, },
{
path: "/home",
name: "Home",
component: () => import("@/views/home/index.vue"),
meta: { requiresAuth: true },
},
{
path: "/rate",
name: "Rate",
component: () => import("@/views/rate/index.vue"),
meta: { requiresAuth: true },
},
{ {
path: "/about", path: "/about",
name: "About", name: "About",
@@ -24,16 +36,18 @@ const router = createRouter({
routes, routes,
}); });
router.beforeEach((to, _from, next) => { router.beforeEach((to: any, from: any, next: any) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
if (to.meta && (to.meta as any).requiresAuth && !token) { if (to.meta && (to.meta as any).requiresAuth && !token) {
next({ path: "/login" }); next({ path: "/login" });
return; return;
} }
if (token && to.path !== "/browser") {
next({ path: "/browser" }); if (token && to.path !== "/rate") {
next({ path: "/rate" });
return; return;
} }
next(); next();
}); });

View File

View File

@@ -0,0 +1,12 @@
export interface PaginationProps {
currentPage?: number
total: number
pageSize: number
pageSizes?: number[]
}
export interface EmitsProps {
(e: 'update:currentPage', value: number): void
(e: 'update:pageSize', value: string): void
(e: 'currentChange', value: number): void
}

View File

@@ -0,0 +1,3 @@
import { PaginationProps, EmitsProps } from './PaginationProps'
export { PaginationProps, EmitsProps }

View File

@@ -0,0 +1,51 @@
<template>
<div class="task p-[12px]">
<div class="flex border border-[#BEDBFF] h-[48px] p-[4px] rounded-[10px] bg-[#EFF6FF] task-tab">
<div v-for="item in tabs" :key="item.value" class="flex-1 flex text-center items-center h-full align-middle text" :class="active === item.value && 'active'" @click="changeTab(item.value)">
<div class="flex-1">{{ item.name }}<span v-if="item.total">{{`${item.total > 98 && item.total + '+' || item.total}`}}</span></div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
const tabs = reactive([{
name: '待处理',
value: 1,
total: 10,
},{
name: '已处理',
value: 2,
total: 99,
}])
const active = ref(1);
const changeTab = (val:number) => {
active.value = val;
};
</script>
<style scoped>
.task-tab .text {
color: #525866;
font-size: 14px;
cursor: pointer;
}
.task-tab .active {
position: relative;
color: #2B7FFF;
background: #FFFFFF;
border-radius: 8px;
}
.task-tab .active::after {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
content: '';
border-radius: 8px;
border: 1px solid #2B7FFF;
}
</style>

View File

@@ -1,23 +1,18 @@
<template> <template>
<div class="home"> <Layout>
<h2 class="text-2xl font-bold mb-4">欢迎使用智念科技 AI</h2> <template #task>
<div class="bg-white p-6"> <Task />
<button </template>
class="bg-blue-300 hover:bg-blue-500 text-white px-4 py-2 rounded mr-2" </Layout>
@click="openBaidu"
>
打开百度
</button>
</div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const openBaidu = () => { import Task from '../components/Task/index.vue'
(window as any).ipcAPI?.openBaidu()
// 发送日志 const openBaidu = () => {
(window as any).ipcAPI?.logToMain('info', '打开百度') (window as any).ipcAPI?.openBaidu()
// 发送日志
(window as any).ipcAPI?.logToMain('info', '打开百度')
} }
</script> </script>

View File

@@ -41,6 +41,19 @@
/> />
</div> </div>
<p v-if="errors.password" class="mt-1 text-xs text-red-500">{{ errors.password }}</p> <p v-if="errors.password" class="mt-1 text-xs text-red-500">{{ errors.password }}</p>
<!-- 验证码 -->
<div class="font-[14px] text-gray-700 mb-[8px] mt-[12px]">验证码</div>
<div class="flex items-center gap-2 border rounded-[10px] box-border px-[12px] py-[10px]">
<input
class="flex-1 focus-visible:outline-none"
type="text"
v-model.trim="form.code"
placeholder="请输入验证码"
@keyup.enter="onSubmit"
/>
<img class="w-[80px] h-[40px]" src="" />
</div>
<p v-if="errors.code" class="mt-1 text-xs text-red-500">{{ errors.code }}</p>
<!-- 记住密码|忘记密码 --> <!-- 记住密码|忘记密码 -->
<div class="flex items-center justify-between mb-[24px] mt-[24px]"> <div class="flex items-center justify-between mb-[24px] mt-[24px]">
@@ -79,7 +92,7 @@
<!-- Copy Right --> <!-- Copy Right -->
<div class="text-[14px] text-gray-500 text-center mt-[24px] mt-auto"> <div class="text-[14px] text-gray-500 text-center mt-[24px] mt-auto">
© 2025 智能体智能科技有限公司 版权所有 © 2025 贵州智念科技服务有限公司 版权所有
</div> </div>
</div> </div>
@@ -94,8 +107,8 @@ import { login as apiLogin } from "@/renderer/api/login";
import { RiUser3Fill , RiKey2Fill} from '@remixicon/vue' import { RiUser3Fill , RiKey2Fill} from '@remixicon/vue'
const router = useRouter(); const router = useRouter();
const form = reactive({ account: "", password: "", agreement: "" }); const form = reactive({ account: "", password: "", agreement: "", code: "" });
const errors = reactive<{ account?: string; password?: string }>({}); const errors = reactive<{ account?: string; password?: string; code?: string }>({});
const loading = ref(false); const loading = ref(false);
const showPwd = ref(false); const showPwd = ref(false);
@@ -118,7 +131,7 @@ const onSubmit = async () => {
// const token = res && (res.token || res.data?.token || res.access_token); // const token = res && (res.token || res.data?.token || res.access_token);
// if (!token) throw new Error("登录失败"); // if (!token) throw new Error("登录失败");
// localStorage.setItem("token", token); // localStorage.setItem("token", token);
await (window as any).ipcAPI.app.setFrameless('/browser') await (window as any).ipcAPI.app.setFrameless('/home')
} finally { } finally {
// loading.value = false; // loading.value = false;
} }

View File

@@ -0,0 +1,45 @@
<template>
<div class="box-border border-[1px] border-[#E5E8EE] rounded-[16px] p-[16px]">
<el-tabs v-model="activeName" class="demo-tabs">
<el-tab-pane :label="`${item.label}(${item.total})`" :name="item.name" v-for="item in tabs"
:key="item.label" />
</el-tabs>
<RateFilterSection />
<!-- 分页 -->
<Pagination v-model:current-page="queryParams.pageIndex" :page-size="queryParams.pageSize" :total="total" />
</div>
</template>
<script setup lang="ts" name="RateContentSection">
import { ref } from 'vue'
import Pagination from '@/components/Pagination/index.vue'
import RateFilterSection from '../RateFilterSection/index.vue'
const activeName = ref('all')
const tabs = ref([
{
label: '全部评价',
name: 'all',
total: 200,
},
{
label: '待回复',
name: 'second',
total: 100,
},
{
label: '差评',
name: 'third',
total: 50,
}
])
const total = ref(200)
const queryParams = ref({
pageIndex: 1,
pageSize: 10,
})
</script>
<style></style>

View File

@@ -0,0 +1,73 @@
<template>
<div class="flex items-center gap-[12px]">
<el-form ref="queryRef" :inline="true" :model="queryParams" @keyup.enter="handleQuery">
<el-form-item prop="dateRange">
<el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" style="width: 240px;" />
</el-form-item>
<el-form-item prop="channel">
<el-select v-model="queryParams.channel" placeholder="请选择渠道" style="width: 240px;">
<el-option v-for="item in channels" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang="ts" name="RateFilterSection">
import { ref, getCurrentInstance } from 'vue'
const { proxy }: any = getCurrentInstance()
const queryParams = ref({
pageIndex: 1,
pageSize: 10,
channel: '',
startDate: '',
endDate: '',
})
const dateRange = ref([])
const channels = [
{
label: '全部',
value: 'all',
},
{
label: '携程',
value: 'ctrip',
},
{
label: '飞猪',
value: 'flyingpig',
},
{
label: '抖音',
value: 'douyin',
},
]
const loading = ref(false)
const total = ref(0)
const queryRef = ref()
/** 查询评论列表 */
function getList() {
loading.value = true
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageIndex = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
dateRange.value = []
queryRef.value.resetFields()
handleQuery()
}
</script>

View File

@@ -0,0 +1,27 @@
<template>
<div class="grid grid-cols-5 gap-[15px] mb-[20px] select-none">
<div class="bg-[#F5F7FA] box-border flex flex-col p-[16px] rounded-[12px]" v-for="item in channels" :key="item.id">
<div class="flex items-center mb-[8px]">
<img :src="item.icon" class="w-[24px] h-[24px] mr-[8px]">
<span class="text-[16px] font-400 text-[#171717] leading-[24px]">
{{ item.name }}
</span>
</div>
<div class="text-[14px] font-400 text-[#171717] leading-[20px] mb-[4px]">
{{ item.total }}
</div>
<div class="flex items-center">
<RiStarFill :color="i <= item.score ? '#FA7319' : '#CACFD8'" class="w-[20px] h-[20px] mr-[2px]" v-for="i in 5"
:key="i" />
<span class="text-[14px] text-[#525866] leading-[20px] pl-[2px]">
{{ item.score }}
</span>
</div>
</div>
</div>
</template>
<script setup lang="ts" name="RatePanelSection">
import { channels } from '@constant/rate'
import { RiStarFill } from '@remixicon/vue'
</script>

View File

@@ -0,0 +1,14 @@
<template>
<div class="box-border border-b-[1px] border-b-[#E5E8EE] mb-[20px] pb-[20px]">
<span class="text-[24px] font-500 text-[#171717] leading-[32px] mr-[8px]">
评价
</span>
<span class="text-[12px] font-400 text-[#99A0AE] leading-[16px]">
评价数据智能整理精准优化服务
</span>
</div>
</template>
<script></script>
<style></style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,16 @@
<template>
<Layout>
<div class="bg-white box-border w-[936px] h-full rounded-[16px] p-[20px]">
<RateTitleSection />
<RatePanelSection />
<RateContentSection />
</div>
</Layout>
</template>
<script setup lang="ts" name="Rate">
import RateTitleSection from './components/RateTitleSection/index.vue'
import RatePanelSection from './components/RatePanelSection/index.vue'
import RateContentSection from './components/RateContentSection/index.vue'
</script>

View File

@@ -15,15 +15,19 @@
"strict": true, "strict": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"], "@/*": ["src/renderer/*"],
"@assets/*": ["src/assets/*"],
"@store/*": ["src/renderer/store/*"], "@store/*": ["src/renderer/store/*"],
"@constant/*": ["src/renderer/constant/*"],
"@utils/*": ["src/renderer/utils/*"], "@utils/*": ["src/renderer/utils/*"],
"@api/*": ["src/renderer/api/*"], "@api/*": ["src/renderer/api/*"],
"@/types": ["src/renderer/types/index.ts"],
"@modules/*": ["src/electron/main/modules/*"], "@modules/*": ["src/electron/main/modules/*"],
}, },
"outDir": "dist", "outDir": "dist",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"resolveJsonModule": true "resolveJsonModule": true,
"types": ["element-plus/global"]
}, },
"include": [ "include": [
"src/**/*", "src/**/*",

View File

@@ -16,8 +16,10 @@ export default defineConfig({
"@": resolve(__dirname, "./src/renderer"), "@": resolve(__dirname, "./src/renderer"),
"@assets": resolve(__dirname, "./src/assets"), "@assets": resolve(__dirname, "./src/assets"),
"@store": resolve(__dirname, "./src/renderer/store"), "@store": resolve(__dirname, "./src/renderer/store"),
"@constant": resolve(__dirname, "./src/renderer/constant"),
"@utils": resolve(__dirname, "./src/renderer/utils"), "@utils": resolve(__dirname, "./src/renderer/utils"),
"@api": resolve(__dirname, "./src/renderer/api"), "@api": resolve(__dirname, "./src/renderer/api"),
"@/types": resolve(__dirname, "./src/renderer/types"),
}, },
}, },
}); });