Compare commits
125 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
278f75cc16 | |
|
|
894f036ad2 | |
|
|
9dd4c25c41 | |
|
|
461aa0c691 | |
|
|
b71bc19188 | |
|
|
cf2b692c84 | |
|
|
685bcc76a8 | |
|
|
627d0b006a | |
|
|
ee1c73babe | |
|
|
4f1e973480 | |
|
|
b5c6256ed2 | |
|
|
13291799f9 | |
|
|
7912b37281 | |
|
|
15e307dbea | |
|
|
04c421ce39 | |
|
|
8e98e3d63a | |
|
|
a90946ef89 | |
|
|
add722882c | |
|
|
e20ed0c7db | |
|
|
032b7a1dab | |
|
|
d4cbc2c562 | |
|
|
a7a3a08ee3 | |
|
|
f80e614a15 | |
|
|
7bb4fe6b06 | |
|
|
4bd6a702aa | |
|
|
b21592025f | |
|
|
59b16f7323 | |
|
|
3c39e72230 | |
|
|
a96b1cc6ea | |
|
|
99e81b3721 | |
|
|
0154e114d9 | |
|
|
c1f96448f8 | |
|
|
0982eb45c2 | |
|
|
3b90800bc2 | |
|
|
a0ae694e84 | |
|
|
9934aba290 | |
|
|
71062c8e13 | |
|
|
37dee18a22 | |
|
|
6b6dc25dea | |
|
|
d3cfb99c62 | |
|
|
d09945c70c | |
|
|
d45e50f413 | |
|
|
f9c0f69cd6 | |
|
|
b0a3e38657 | |
|
|
4be150d344 | |
|
|
dba108f0e1 | |
|
|
ef818b9c22 | |
|
|
455aa810c2 | |
|
|
5ee56a3d24 | |
|
|
74954007ae | |
|
|
39236b6673 | |
|
|
29026bff71 | |
|
|
afe4f422c8 | |
|
|
c270557c29 | |
|
|
453936dd56 | |
|
|
a00988529d | |
|
|
f67fee4aa5 | |
|
|
2fcead28e6 | |
|
|
431cb67c12 | |
|
|
81c98ce3b2 | |
|
|
e4196bdc66 | |
|
|
34d2d5f895 | |
|
|
62a3180714 | |
|
|
1e56d7c8f9 | |
|
|
995f682ab8 | |
|
|
ea590f45b6 | |
|
|
6dcc946e1c | |
|
|
2b20a82484 | |
|
|
6a0db7df63 | |
|
|
8c3b5c825f | |
|
|
4c647c7d59 | |
|
|
967f2171c8 | |
|
|
718d74e41b | |
|
|
8dd919e8b0 | |
|
|
8bead115f5 | |
|
|
11a885d039 | |
|
|
3ab1dfae30 | |
|
|
d25f87a889 | |
|
|
a9eef0d69f | |
|
|
a464d256a2 | |
|
|
e6beded4de | |
|
|
365b770a50 | |
|
|
69aec22ab6 | |
|
|
c0a6629310 | |
|
|
258444e317 | |
|
|
9bbf2c10b3 | |
|
|
383db107da | |
|
|
19b2583c57 | |
|
|
69fffec976 | |
|
|
f91fc47e2a | |
|
|
6aed6ace2d | |
|
|
653f9a8f5e | |
|
|
f4ceec3c7a | |
|
|
18ed8d531a | |
|
|
680f074c37 | |
|
|
654b908f16 | |
|
|
0c9a07e76d | |
|
|
3129d239a6 | |
|
|
36d03f14f5 | |
|
|
b7f4539e63 | |
|
|
d1d09f76f9 | |
|
|
a775247a9f | |
|
|
8ce73d4bda | |
|
|
df0b47d766 | |
|
|
2a851c74a0 | |
|
|
28409ef3b2 | |
|
|
9c62ac9ca3 | |
|
|
ef3c530df5 | |
|
|
579f4c1390 | |
|
|
3a29305df7 | |
|
|
2e68592cf1 | |
|
|
f9bd02af3c | |
|
|
cabde71e62 | |
|
|
7d93c48a1e | |
|
|
643f49a72f | |
|
|
885109158d | |
|
|
725f4eb9af | |
|
|
9e2f08bbc2 | |
|
|
4f5682c80a | |
|
|
2204df2614 | |
|
|
bb5520b32c | |
|
|
fb9df08f1e | |
|
|
de20b194f0 | |
|
|
c2d8a180af | |
|
|
413d374786 |
|
|
@ -2,10 +2,14 @@
|
|||
ENV = development
|
||||
|
||||
# 本地环境接口地址
|
||||
# VITE_API_URL = http://123.60.153.169:8040/apih5
|
||||
# VITE_API_URL = https://4155gf93ll13.vicp.fun/apih5
|
||||
# 参考测试环境接口地址
|
||||
VITE_API_URL = http://123.60.153.169:8040/apih5
|
||||
# VITE_API_URL = http://4155gf93ll13.vicp.fun/apih5
|
||||
# VITE_API_URL = http://123.60.79.143:8041/apih5
|
||||
# VITE_API_URL =http://ukfba3.natappfree.cc/apih5
|
||||
VITE_API_URL = https://cankao.cs.com.cn/apih5
|
||||
|
||||
# VITE_API_URL =http://192.168.0.135:8040/apih5
|
||||
# 参考生产环境接口地址
|
||||
# VITE_API_URL = https://cankao.cs.com.cn/apih5
|
||||
# datav测试数据接口
|
||||
VITE_API_TEST_DATAV_URL = https://cankao.cs.com.cn/zzck_test
|
||||
# datav生产数据接口
|
||||
VITE_API_DATAV_URL = https://cankao.cs.com.cn/zzck_datav
|
||||
|
|
@ -5,7 +5,11 @@ ENV = production
|
|||
# VITE_API_URL = https://cankao.cs.com.cn/mini
|
||||
# VITE_API_URL = http://123.60.153.169:8040/apih5
|
||||
VITE_API_URL = https://cankao.cs.com.cn/apih5
|
||||
|
||||
# VITE_API_URL = http://123.60.79.143:8041/apih5
|
||||
|
||||
# datav测试环境接口地址,打包cankao.cs.com.cn生产环境请改成 https://cankao.cs.com.cn/zzck_datav
|
||||
# VITE_API_TEST_DATAV_URL = https://cankao.cs.com.cn/zzck_test
|
||||
VITE_API_TEST_DATAV_URL = https://cankao.cs.com.cn/zzck_datav
|
||||
|
||||
# datav生产数据接口
|
||||
VITE_API_DATAV_URL = https://cankao.cs.com.cn/zzck_datav
|
||||
BIN
caokao-h5.zip
37
index.html
|
|
@ -32,6 +32,43 @@
|
|||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<script>
|
||||
(function (w, d, s, q, i) {
|
||||
w[q] = w[q] || [];
|
||||
var f = d.getElementsByTagName(s)[0], j = d.createElement(s);
|
||||
j.async = true;
|
||||
j.id = 'beacon-aplus';
|
||||
j.src = 'https://d.alicdn.com/alilog/mlog/aplus/' + i + '.js';
|
||||
f.parentNode.insertBefore(j, f);
|
||||
})(window, document, 'script', 'aplus_queue', '203467608');
|
||||
|
||||
//集成应用的appKey
|
||||
aplus_queue.push({
|
||||
action: 'aplus.setMetaInfo',
|
||||
arguments: ['appKey', '68d7b06e8560e34872b9f3a7']
|
||||
});
|
||||
/************************以下内容为可选配置内容****************************/
|
||||
//sdk提供手动pv发送机制,启用手动pv(即关闭自动pv),需设置aplus-waiting=MAN;
|
||||
//注意:由于单页面路由改变时不会刷新页面,无法自动发送pv,所以对于单页应用,强烈建议您关闭自动PV, 手动控制PV事件
|
||||
aplus_queue.push({
|
||||
action: 'aplus.setMetaInfo',
|
||||
arguments: ['aplus-waiting', 'MAN']
|
||||
});
|
||||
//是否开启调试模式
|
||||
aplus_queue.push({
|
||||
action: 'aplus.setMetaInfo',
|
||||
arguments: ['DEBUG', true]
|
||||
});
|
||||
//是否指定用作计算umid的id类型,默认为cnaid,目前支持:
|
||||
//1. 微信和QQ: openid; 字节和百度 anonymousid; 支付宝 alipay_id
|
||||
//2. 微信、QQ、字节、百度平台的 unionid
|
||||
//3. 业务方自己生成的随机id uuid
|
||||
// aplus_queue.push({
|
||||
// action: 'aplus.setMetaInfo',
|
||||
// arguments: ['aplus-idtype', 'xxxx'] //取值参考见附表1
|
||||
// });
|
||||
</script>
|
||||
|
||||
<!-- <script type="text/javascript">
|
||||
var link = location.href.split("#")[0];
|
||||
console.log("🚀 ~ link:", link);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
"clipboard": "^2.0.11",
|
||||
"dayjs": "^1.11.9",
|
||||
"echarts": "^5.6.0",
|
||||
"element-plus": "^2.11.7",
|
||||
"js-cookie": "^3.0.5",
|
||||
"js-md5": "^0.8.3",
|
||||
"pinia": "^2.0.36",
|
||||
|
|
@ -1785,6 +1786,14 @@
|
|||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"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==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcloudio/types": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmmirror.com/@dcloudio/types/-/types-3.3.3.tgz",
|
||||
|
|
@ -2237,6 +2246,14 @@
|
|||
"vite": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.16.17",
|
||||
"resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
|
||||
|
|
@ -2567,6 +2584,28 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
|
||||
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
|
||||
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
|
||||
"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.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
|
||||
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
|
||||
},
|
||||
"node_modules/@intlify/core-base": {
|
||||
"version": "9.1.9",
|
||||
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.1.9.tgz",
|
||||
|
|
@ -3898,6 +3937,16 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
||||
|
|
@ -4073,6 +4122,19 @@
|
|||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA=="
|
||||
},
|
||||
"node_modules/@types/lodash-es": {
|
||||
"version": "4.17.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
|
||||
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/@types/node/-/node-24.0.4.tgz",
|
||||
|
|
@ -4106,6 +4168,11 @@
|
|||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "16.0.9",
|
||||
"resolved": "https://registry.npmmirror.com/@types/yargs/-/yargs-16.0.9.tgz",
|
||||
|
|
@ -4506,6 +4573,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"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/@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==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"dependencies": {
|
||||
"vue-demi": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz",
|
||||
|
|
@ -4925,6 +5025,11 @@
|
|||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||
"dev": true
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
|
||||
|
|
@ -5853,9 +5958,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.9",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
||||
"integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="
|
||||
},
|
||||
"node_modules/de-indent": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -6039,6 +6144,30 @@
|
|||
"integrity": "sha512-HE43yYdUUiJVjewV2A9EP8o89Kb4AqMKplMQP2IxEPUws1Etu/ZkdsgUDabUZ/WmbP4ZbvJDOcunvbBUPPIfmw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/element-plus": {
|
||||
"version": "2.11.7",
|
||||
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.11.7.tgz",
|
||||
"integrity": "sha512-Bh47wuzsqaNBNDkbtlOlZER1cGcOB8GsXp/+C9b95MOrk0wvoHUV4NKKK7xMkfYNFYdYysQ752oMhnExgAL6+g==",
|
||||
"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.18",
|
||||
"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/emittery": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmmirror.com/emittery/-/emittery-0.8.1.tgz",
|
||||
|
|
@ -9635,9 +9764,22 @@
|
|||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||
},
|
||||
"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==",
|
||||
"peerDependencies": {
|
||||
"@types/lodash-es": "*",
|
||||
"lodash": "*",
|
||||
"lodash-es": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
|
|
@ -9729,6 +9871,11 @@
|
|||
"node": ">= 0.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=="
|
||||
},
|
||||
"node_modules/merge": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/merge/-/merge-2.1.1.tgz",
|
||||
|
|
@ -9942,6 +10089,11 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "uni-preset-vue",
|
||||
"version": "0.0.1",
|
||||
"version": "2.0.2",
|
||||
"scripts": {
|
||||
"dev:h5": "uni",
|
||||
"build:h5": "uni build",
|
||||
|
|
@ -57,6 +57,7 @@
|
|||
"clipboard": "^2.0.11",
|
||||
"dayjs": "^1.11.9",
|
||||
"echarts": "^5.6.0",
|
||||
"element-plus": "^2.11.7",
|
||||
"js-cookie": "^3.0.5",
|
||||
"js-md5": "^0.8.3",
|
||||
"pinia": "^2.0.36",
|
||||
|
|
|
|||
|
|
@ -39,4 +39,9 @@ export const getListByTagIndustry = (data: any) => {
|
|||
// 概念标签
|
||||
export const getListByTag = (data: any) => {
|
||||
return request.get(`/news/list/tag?name=${data.name}`);
|
||||
};
|
||||
|
||||
// 拓展阅读新闻
|
||||
export const getDetailFurtherReadData = (news_id: string) => {
|
||||
return request.get(`/news/detail/${news_id}/furtherReadings`);
|
||||
};
|
||||
|
|
@ -55,10 +55,83 @@ export const getUnlockList = (data: any) => {
|
|||
return Request.post("/user/unlockList", data);
|
||||
};
|
||||
|
||||
|
||||
// 全文搜索
|
||||
//
|
||||
export const searchNews = (data: any) => {
|
||||
return Request.post("/news/search", data);
|
||||
};
|
||||
|
||||
// 已发布列表
|
||||
export const getReleaseList = (data: any) => {
|
||||
return Request.post("/news/top_news_release_h5_d", data);
|
||||
};
|
||||
|
||||
// 编辑精选接口
|
||||
export const editTopNews = (data: any) => {
|
||||
return Request.post("/news/list/published", data);
|
||||
};
|
||||
|
||||
// 编辑精选接口
|
||||
export const sendToken = (data: any) => {
|
||||
return Request.post("/common/forward/financial", data);
|
||||
};
|
||||
|
||||
// 退出登录
|
||||
export const doLogout = (data: any) => {
|
||||
console.log("🚀 ~ doLogout ~ data:", data);
|
||||
return Request.post("/common/logout", data);
|
||||
};
|
||||
|
||||
// 退出登录
|
||||
export const getEtfIndexList = (data: any) => {
|
||||
return Request.post("/news/etfIndexList", data);
|
||||
};
|
||||
|
||||
// 获取ETF详情
|
||||
export const fetchEtfDetail = (data: any) => {
|
||||
return Request.post("/news/etfList", data);
|
||||
};
|
||||
|
||||
// 海外先机
|
||||
export const getForeignList = (data: any) => {
|
||||
return Request.get("/news/exclusiveList", {params: data});
|
||||
};
|
||||
|
||||
// 编辑精选
|
||||
export const getRecommendList = (data: any) => {
|
||||
return Request.get("/news/curatedList", { params: data });
|
||||
};
|
||||
|
||||
// 宏观知微
|
||||
export const getMacroList = (data: any) => {
|
||||
return Request.get("/news/globalMacroList", { params: data });
|
||||
};
|
||||
|
||||
// 我关注的行业
|
||||
export const getMyIndustries = (data: any) => {
|
||||
return Request.get("/user/industries", { params: data });
|
||||
};
|
||||
|
||||
// 我关注的风口
|
||||
export const getMyTags = () => {
|
||||
return Request.get("/user/tags");
|
||||
};
|
||||
|
||||
// 配置我关注的行业
|
||||
export const updateMyIndustries = (data: any) => {
|
||||
return Request.post("/user/industries", data);
|
||||
};
|
||||
|
||||
// 配置我关注的风口
|
||||
export const updateMyTags = (data: any) => {
|
||||
return Request.post("/user/tags", data);
|
||||
};
|
||||
|
||||
// 热门行业
|
||||
export const getHotByTagIndustry = (data: any) => {
|
||||
return Request.get(`/news/hot/industry?name=${data.name}`);
|
||||
};
|
||||
|
||||
// 概念标签
|
||||
export const getHotByTag = (data: any) => {
|
||||
return Request.get(`/news/hot/tag?name=${data.name}`);
|
||||
};
|
||||
|
|
@ -15,9 +15,34 @@ export const getConceptCount = (data: any) => {
|
|||
return request.get("/news_info/concept/count", data);
|
||||
};
|
||||
|
||||
// 概念标签贴标
|
||||
export const getTopNewsDay = (params: any) => {
|
||||
// return request.get("/top_news_h5_period?start_date=" + data.start_date + "&end_date=" + data.end_date + "&limit_num=" + data.limit_num, data);
|
||||
return request.get("/top_news_h5_d", params);
|
||||
};
|
||||
|
||||
// 概念标签贴标
|
||||
export const getTopNews = (data: any) => {
|
||||
return request.get("/top_news_h5_d", data);
|
||||
return request.get(
|
||||
"/top_news_h5_period?start_date=" +
|
||||
data.start_date +
|
||||
"&end_date=" +
|
||||
data.end_date +
|
||||
"&limit_num=" +
|
||||
data.limit_num,
|
||||
data,
|
||||
);
|
||||
// return request.get("/top_news_h5_d", data);
|
||||
};
|
||||
// 概念标签贴标
|
||||
export const getTopNewsAll = (data: any) => {
|
||||
return request.get("/top_news_release_h5_all", data);
|
||||
// return request.get("/news_release_ratingrank_h5_d", data);
|
||||
};
|
||||
|
||||
// 概念标签贴标 release
|
||||
export const getTopNewsAllRelease = (data: any) => {
|
||||
return request.get("/news_release_ratingrank_h5_d?input_date=" + data.input_date + "&limit_num=10");
|
||||
};
|
||||
|
||||
// 热门行业top10:
|
||||
|
|
@ -34,3 +59,47 @@ export const getTopConcept_d = (data: any) => {
|
|||
export const getNews_cnt_d = (data: any) => {
|
||||
return request.get("/news_cnt_d", data);
|
||||
};
|
||||
|
||||
// 热门标签某时间段内topN列表(左边第一个)
|
||||
export const getTopConceptPeriod = (data: any) => {
|
||||
// return request.get("/top_concept_period?start_date=" + data.start_time + "&end_date=" + data.end_time + "&limit_num=" + data.limit_num, data);
|
||||
console.log("output >>>>> ", import.meta.env.MODE);
|
||||
return request({
|
||||
baseURL: import.meta.env.VITE_API_TEST_DATAV_URL,
|
||||
url: "/top_concept_period",
|
||||
method: "get",
|
||||
params: {
|
||||
start_date: data.start_time,
|
||||
end_date: data.end_time,
|
||||
limit_num: data.limit_num,
|
||||
},
|
||||
});
|
||||
};
|
||||
// 热门行业某时间段内topN列表(中间第二个)
|
||||
export const getTopIndustryPeriod = (data: any) => {
|
||||
// return request.get("/top_industry_period?start_date=" + data.start_time + "&end_date=" + data.end_time + "&limit_num=" + data.limit_num, data);
|
||||
|
||||
return request({
|
||||
baseURL: import.meta.env.VITE_API_TEST_DATAV_URL,
|
||||
url: "/top_industry_period",
|
||||
method: "get",
|
||||
params: {
|
||||
start_date: data.start_time,
|
||||
end_date: data.end_time,
|
||||
limit_num: data.limit_num,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 热门标签某时间段内topN列表(右边)
|
||||
export const getTopSourcePeriod = (data: any) => {
|
||||
return request.get(
|
||||
"/top_source_period?start_date=" +
|
||||
data.start_time +
|
||||
"&end_date=" +
|
||||
data.end_time +
|
||||
"&limit_num=" +
|
||||
data.limit_num,
|
||||
data,
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 304 KiB |
|
After Width: | Height: | Size: 310 KiB |
|
After Width: | Height: | Size: 782 KiB |
|
After Width: | Height: | Size: 684 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 610 B |
|
After Width: | Height: | Size: 933 B |
|
After Width: | Height: | Size: 983 B |
|
After Width: | Height: | Size: 949 B |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 669 B |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 760 B |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 721 KiB |
|
After Width: | Height: | Size: 219 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 917 B |
|
After Width: | Height: | Size: 488 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 949 B |
|
After Width: | Height: | Size: 6.6 KiB |
|
|
@ -6,7 +6,7 @@
|
|||
<text class="date">({{ dayjs(new Date().getTime()).format("MM/DD") }})</text>
|
||||
</view>
|
||||
|
||||
<text class="sub_title">评分80分以上精选咨洵数量</text>
|
||||
<text class="sub_title">覆盖行业、产业,风口的精选资讯数量</text>
|
||||
</view>
|
||||
<view class="right">
|
||||
<!-- <text class="num">{{ count }}</text> -->
|
||||
|
|
@ -45,8 +45,14 @@ watch(
|
|||
|
||||
<style scoped>
|
||||
.info-summary {
|
||||
background: #f5f8fe;
|
||||
border: 1rpx solid #e3ecfd;
|
||||
/* border: 1rpx solid #e3ecfd; */
|
||||
|
||||
|
||||
background: #FFFFFF;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #FFFFFF;
|
||||
border-image: linear-gradient(180deg, rgba(227, 236, 253, 1), rgba(245, 248, 254, 1)) 1 1;
|
||||
|
||||
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
|
|
@ -70,7 +76,7 @@ watch(
|
|||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
line-height: 33rpx;
|
||||
/* line-height: 33rpx; */
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
|
@ -95,4 +101,4 @@ watch(
|
|||
text-align: right;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,8 @@
|
|||
<template>
|
||||
<view class="news-rank-list">
|
||||
<u-skeleton
|
||||
rows="5"
|
||||
title
|
||||
loading
|
||||
style="margin-bottom: 30rpx"
|
||||
v-if="loading"
|
||||
></u-skeleton>
|
||||
<u-skeleton rows="5" title loading style="margin-bottom: 30rpx" v-if="loading"></u-skeleton>
|
||||
<view class="list" v-else>
|
||||
<view
|
||||
v-for="(item, index) in rankListLocal"
|
||||
:key="index"
|
||||
class="news-item"
|
||||
@click="goDetail(item, 0)"
|
||||
>
|
||||
<view v-for="(item, index) in rankListLocal" :key="index" class="news-item" @click="goDetail(item, 0)">
|
||||
<view class="rank-tag">
|
||||
<view v-if="index == 0" class="rank-text-top3">
|
||||
<img src="@/assets/zixun/ranking_icon_1.png" />
|
||||
|
|
@ -27,46 +16,63 @@
|
|||
<text class="rank-text" v-else>{{ index + 1 }}</text>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="news-content"
|
||||
:style="{ filter: Session.get('token') ? '' : 'blur(5px)' }"
|
||||
>
|
||||
<view class="news-content" :style="{ filter: Session.get('token') ? '' : 'blur(5px)' }">
|
||||
<text class="news-title">{{ item.title }}</text>
|
||||
<text class="news-desc">{{ item.summary }}</text>
|
||||
|
||||
<!-- 两个标签 start -->
|
||||
<view class="r_r_tags" v-if="hasTag">
|
||||
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 95vw">
|
||||
<view class="r_tags">
|
||||
<view class="tag" style="background-color: #fff9ec; color: #ffb100"
|
||||
v-for="(item, index) in item.conceptLabels" :key="index">{{
|
||||
item
|
||||
}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 100vw">
|
||||
<view class="r_tags">
|
||||
<view class="tag" style="background-color: #f5f8fe; color: #007aff"
|
||||
v-for="(item, index) in item.industryLabels" :key="index">{{
|
||||
item
|
||||
}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 两个标签 end -->
|
||||
|
||||
<view class="news-meta">
|
||||
<view>
|
||||
<text class="source">{{ item.source }}</text>
|
||||
<text class="time">{{
|
||||
dayjs(item.publish_time).format("YYYY-MM-DD HH:MM:ss")
|
||||
}}</text>
|
||||
<!-- <text class="time">{{ dayjs(item.publish_time).format("YYYY-MM-DD HH:MM:ss") }}</text> -->
|
||||
<!-- .format('YYYY-MM-DD HH:mm:ss'); -->
|
||||
<text class="time">
|
||||
{{ timeFormat(new Date(item.publish_time).getTime()) }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="score">
|
||||
<text class="score" v-if="needExp">
|
||||
<text v-if="index < 3">资讯评分:</text>
|
||||
{{ item.news_score }}</text
|
||||
>
|
||||
{{ item.news_score }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view @click="isExp = !isExp" class="r_exp">
|
||||
<view @click="isExp = !isExp" class="r_exp" v-if="needExp">
|
||||
<text v-if="isExp">收起</text>
|
||||
<text v-else>展开全部</text>
|
||||
<img src="@/assets/zixun/up_icon.png" class="exp_up" v-if="isExp" />
|
||||
<img src="@/assets/zixun/down_icon.png" class="exp_up" v-else />
|
||||
</view>
|
||||
|
||||
<LoginPopup
|
||||
:show="LoginShow"
|
||||
@handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback"
|
||||
@handlePopupErrorCallback="handlePopupErrorCallback"
|
||||
/>
|
||||
<LoginPopup :show="LoginShow" @handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback" @handlePopupErrorCallback="handlePopupErrorCallback" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { ref, watch, computed } from "vue";
|
||||
import dayjs from "dayjs/esm/index";
|
||||
import LoginPopup from "@/components/loginPopup/index.vue";
|
||||
import { Session } from "@/utils/storage";
|
||||
|
|
@ -83,8 +89,17 @@ watch(
|
|||
if (!isExp.value && index > 9) {
|
||||
return;
|
||||
}
|
||||
|
||||
rankListLocal.value.push(item);
|
||||
let concept_label = "";
|
||||
let industry_label = "";
|
||||
try {
|
||||
concept_label = JSON.parse(item.concept_label);
|
||||
industry_label = JSON.parse(item.industry_label);
|
||||
} catch (e) { }
|
||||
rankListLocal.value.push({
|
||||
...item,
|
||||
conceptLabels: concept_label,
|
||||
industryLabels: industry_label,
|
||||
});
|
||||
});
|
||||
|
||||
loading.value = false;
|
||||
|
|
@ -94,13 +109,26 @@ watch(
|
|||
watch(
|
||||
() => props.newsList,
|
||||
(newValue, oldValue) => {
|
||||
if (!props.needExp) {
|
||||
isExp.value = true;
|
||||
}
|
||||
rankListLocal.value = [];
|
||||
props.newsList.forEach((item, index) => {
|
||||
if (!isExp.value && index > 9) {
|
||||
return;
|
||||
}
|
||||
let concept_label = "";
|
||||
let industry_label = "";
|
||||
try {
|
||||
concept_label = JSON.parse(item.concept_label);
|
||||
industry_label = JSON.parse(item.industry_label);
|
||||
} catch (e) { }
|
||||
|
||||
rankListLocal.value.push(item);
|
||||
rankListLocal.value.push({
|
||||
...item,
|
||||
conceptLabels: concept_label,
|
||||
industryLabels: industry_label,
|
||||
});
|
||||
});
|
||||
loading.value = false;
|
||||
}
|
||||
|
|
@ -113,6 +141,14 @@ const props = defineProps({
|
|||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
needExp: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
hasTag: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const clickItem = ref({});
|
||||
|
|
@ -147,6 +183,54 @@ const handlePopupSuccessCallback = () => {
|
|||
const handlePopupErrorCallback = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 格式化时间
|
||||
* @param {String|Number} dateTime 需要格式化的时间戳
|
||||
* @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
|
||||
* @returns {string} 返回格式化后的字符串
|
||||
*/
|
||||
function timeFormat(dateTime = null, formatStr = "yyyy-mm-dd hh:MM:ss") {
|
||||
let date;
|
||||
// 若传入时间为假值,则取当前时间
|
||||
if (!dateTime) {
|
||||
date = new Date();
|
||||
}
|
||||
// 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
|
||||
else if (/^\d{10}$/.test(dateTime.toString().trim())) {
|
||||
date = new Date(dateTime * 1000);
|
||||
}
|
||||
// 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
|
||||
else if (typeof dateTime === "string" && /^\d+$/.test(dateTime.trim())) {
|
||||
date = new Date(Number(dateTime));
|
||||
}
|
||||
// 其他都认为符合 RFC 2822 规范
|
||||
else {
|
||||
// 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
|
||||
date = new Date(typeof dateTime === "string" ? dateTime.replace(/-/g, "/") : dateTime);
|
||||
}
|
||||
|
||||
const timeSource = {
|
||||
y: date.getFullYear().toString(), // 年
|
||||
m: (date.getMonth() + 1).toString().padStart(2, "0"), // 月
|
||||
d: date.getDate().toString().padStart(2, "0"), // 日
|
||||
h: date.getHours().toString().padStart(2, "0"), // 时
|
||||
M: date.getMinutes().toString().padStart(2, "0"), // 分
|
||||
s: date.getSeconds().toString().padStart(2, "0"), // 秒
|
||||
// 有其他格式化字符需求可以继续添加,必须转化成字符串
|
||||
};
|
||||
|
||||
for (const key in timeSource) {
|
||||
const [ret] = new RegExp(`${key}+`).exec(formatStr) || [];
|
||||
if (ret) {
|
||||
// 年可能只需展示两位
|
||||
const beginIndex = key === "y" && ret.length === 2 ? 2 : 0;
|
||||
formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex));
|
||||
}
|
||||
}
|
||||
|
||||
return formatStr;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
@ -223,11 +307,16 @@ const handlePopupErrorCallback = () => {
|
|||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
display: -webkit-box; /* 设置为WebKit内核的弹性盒子模型 */
|
||||
-webkit-box-orient: vertical; /* 垂直排列 */
|
||||
-webkit-line-clamp: 2; /* 限制显示三行 */
|
||||
overflow: hidden; /* 隐藏超出范围的内容 */
|
||||
text-overflow: ellipsis; /* 使用省略号 */
|
||||
display: -webkit-box;
|
||||
/* 设置为WebKit内核的弹性盒子模型 */
|
||||
-webkit-box-orient: vertical;
|
||||
/* 垂直排列 */
|
||||
-webkit-line-clamp: 2;
|
||||
/* 限制显示三行 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出范围的内容 */
|
||||
text-overflow: ellipsis;
|
||||
/* 使用省略号 */
|
||||
}
|
||||
|
||||
.news-meta {
|
||||
|
|
@ -277,4 +366,27 @@ const handlePopupErrorCallback = () => {
|
|||
align-items: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.r_r_tags {
|
||||
// margin-left: 20rpx;
|
||||
width: 85vw;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.r_tags {
|
||||
display: flex;
|
||||
gap: 10rpx;
|
||||
|
||||
.tag {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #3f80fa;
|
||||
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 10rpx;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,64 +1,181 @@
|
|||
<template>
|
||||
<view class="main">
|
||||
<view class="title">{{ props.data.title }}</view>
|
||||
<view class="author">
|
||||
<view class="name">
|
||||
<text class="text">来源:</text>
|
||||
<text class="text">{{ props.data.tag }}</text>
|
||||
</view>
|
||||
<view class="page-container">
|
||||
<view class="main">
|
||||
<view class="title" :class="{ mohu: isMask }">{{ props.data.title }}</view>
|
||||
<view class="author">
|
||||
<view class="name" :class="{ mohu: isMask }">
|
||||
<text class="text">来源:</text>
|
||||
<text class="text" v-if="intoType === 'etf'">中国证券报</text>
|
||||
<text class="text" v-else>
|
||||
{{ props.data.tag ? props.data.tag : "中国证券报" }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="name" v-if="props.data.editor">
|
||||
<!-- <view class="name" v-if="props.data.editor">
|
||||
<text class="text">编辑:</text>
|
||||
<text class="text">{{ props.data.editor }}</text>
|
||||
</view> -->
|
||||
<view class="time" :class="{ mohu: isMask }">{{ props.data.publishTime }}</view>
|
||||
</view>
|
||||
<view class="time">{{ props.data.publishTime }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 两个标签 start -->
|
||||
<view class="r_r_tags">
|
||||
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 95vw">
|
||||
<view class="r_tags">
|
||||
<view class="tag" style="background-color: #fff9ec; color: #ffb100"
|
||||
v-for="(item, index) in props.data.conceptLabels" :key="index">{{ item }}</view>
|
||||
<!-- 两个标签 start -->
|
||||
<view class="r_r_tags" :class="{ mohu: isMask }">
|
||||
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 95vw">
|
||||
<view class="r_tags">
|
||||
<view
|
||||
class="tag"
|
||||
style="background-color: #fff9ec; color: #ffb100"
|
||||
v-for="(item, index) in props.data.conceptLabels"
|
||||
:key="index"
|
||||
>{{ item }}</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 100vw">
|
||||
<view class="r_tags">
|
||||
<view
|
||||
class="tag"
|
||||
style="background-color: #f5f8fe; color: #007aff"
|
||||
v-for="(item, index) in props.data.industryLabels"
|
||||
:key="index"
|
||||
>{{ item }}</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 两个标签 end -->
|
||||
|
||||
<!-- 摘要 -->
|
||||
<view class="desc" v-if="props.data.summary" :class="{ mohu: isMask }">
|
||||
<!-- <view class="bill_icon"></view> -->
|
||||
<image :src="zhaiyaoImg" mode="scaleToFill" class="zhaiyao_icon" />
|
||||
<view>
|
||||
{{ props.data.summary }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="display: flex; margin-top: 20rpx; overflow-x: auto; width: 100vw">
|
||||
<view class="r_tags">
|
||||
<view class="tag" style="background-color: #f5f8fe; color: #007aff"
|
||||
v-for="(item, index) in props.data.industryLabels" :key="index">{{ item }}</view>
|
||||
</view>
|
||||
<view class="thumbnail" v-if="props.data.picture">
|
||||
<image :src="props.data.picture" mode="widthFix" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 两个标签 end -->
|
||||
|
||||
<!-- 摘要 -->
|
||||
<view class="desc" v-if="props.data.summary">
|
||||
<!-- <view class="bill_icon"></view> -->
|
||||
{{ props.data.summary }}
|
||||
</view>
|
||||
<view style="padding: 35rpx" :class="{ mohu: isMask }">
|
||||
<text
|
||||
class="articleDes"
|
||||
:class="props?.data?.needpay && 'needpay'"
|
||||
style="white-space: pre-wrap"
|
||||
v-html="content"
|
||||
>
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="thumbnail" v-if="props.data.picture">
|
||||
<image :src="props.data.picture" mode="widthFix" />
|
||||
</view>
|
||||
|
||||
<view style="padding: 35rpx;">
|
||||
<text class="articleDes" :class="props?.data?.needpay && 'needpay'" style="white-space: pre-wrap;"
|
||||
v-html="props.data.content">
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- <view
|
||||
<!-- <view
|
||||
class="articleDes"
|
||||
:class="props?.data?.needpay && 'needpay'"
|
||||
v-html="props.data.content"
|
||||
>
|
||||
</view> -->
|
||||
|
||||
<view class="author" style="justify-content: flex-start">
|
||||
<view class="name" v-if="props.data.editor">
|
||||
<text class="text">编辑:</text>
|
||||
<text class="text">{{ props.data.editor }}</text>
|
||||
</view>
|
||||
|
||||
<view class="name" style="margin-left: 40rpx" v-if="props.data.secondReviewer">
|
||||
<text class="text">二校:</text>
|
||||
<text class="text">{{ props.data.secondReviewer }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="company-tag" v-if="props.data.companyName">
|
||||
<text class="txt">{{ props.data.companyName }}</text>
|
||||
</view>
|
||||
|
||||
<!-- <view class="r_etf" style="margin-top: 80rpx" v-if="intoType == 'etf'">
|
||||
<text class="etf_title">AI关联标的</text>
|
||||
<view class="etfs">
|
||||
<view
|
||||
v-for="(item, index) in data.etfs"
|
||||
class="etf_item"
|
||||
:key="index"
|
||||
@click="goEtfDetail(item)"
|
||||
>
|
||||
{{ item.name }}
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 关联个股 -->
|
||||
<view
|
||||
class="r_etf"
|
||||
style="margin-top: 20rpx"
|
||||
v-if="data.stocks && data.stocks.length > 0"
|
||||
>
|
||||
<text class="etf_title">关联个股</text>
|
||||
<view class="etfs">
|
||||
<view v-for="(item, index) in data.stocks" class="stock_item" :key="index">
|
||||
<view class="name">{{ item.name }}</view>
|
||||
<view class="code">{{ item.code }}</view>
|
||||
<!-- 暂无涨跌数据,保留样式 -->
|
||||
<!-- <view>
|
||||
<view class="name">{{ item.name }}</view>
|
||||
<view class="code">{{ item.code }}</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="percent up">-0.28%</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<template v-if="intoType == 'etf'">
|
||||
<view
|
||||
v-for="(item, index) in data.etfs"
|
||||
class="etf_item"
|
||||
:key="index"
|
||||
@click="goEtfDetail(item)"
|
||||
>
|
||||
<view class="name">{{ item.name }}</view>
|
||||
<view class="code">{{ item.code }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 拓展阅读 -->
|
||||
<view
|
||||
:class="['more-news', { mohu: isMask }]"
|
||||
style="margin-top: 20rpx"
|
||||
v-if="furtherReadData.length > 0"
|
||||
>
|
||||
<text class="more-news-title">拓展阅读</text>
|
||||
<view class="more-news-list">
|
||||
<view
|
||||
class="news"
|
||||
v-for="item in furtherReadData"
|
||||
:ke="item.id"
|
||||
@click="goNewsDetail(item)"
|
||||
>
|
||||
<view class="title">{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="more-btn" v-if="!isMore">
|
||||
<view class="text" @click="getMoreNews">查看更多</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 登录弹窗 start -->
|
||||
<LoginDialog
|
||||
:show="LoginShow"
|
||||
@onSuccess="handleLoginSuccess"
|
||||
@onCancel="handleLoginCancel"
|
||||
@onError="handleLoginError"
|
||||
/>
|
||||
<!-- 登录弹窗 end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { computed, ref, toRefs } from "vue";
|
||||
import {
|
||||
onLaunch,
|
||||
onShow,
|
||||
|
|
@ -67,11 +184,25 @@ import {
|
|||
onShareTimeline,
|
||||
} from "@dcloudio/uni-app";
|
||||
import articleMock from "@/mock/article.js";
|
||||
import LoginDialog from "@/pages/realtimeInfo/components/LoginPopup/index.vue";
|
||||
import { Session } from "@/utils/storage";
|
||||
import zhaiyaoImg from "../../assets/zixun/zhaiyao_icon.png";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const emit = defineEmits(["getFurtherReadData"]);
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => { },
|
||||
default: () => {},
|
||||
},
|
||||
furtherReadData: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
access: {
|
||||
type: String,
|
||||
default: () => "",
|
||||
},
|
||||
});
|
||||
const tagList1 = ref([
|
||||
|
|
@ -85,6 +216,80 @@ const tagList1 = ref([
|
|||
name: "医药生物-医疗服务",
|
||||
},
|
||||
]);
|
||||
// 匹配第一个文本node
|
||||
function getFirstTextNode(node: any): any {
|
||||
// 文本节点
|
||||
if (node.nodeType === 3) {
|
||||
return node;
|
||||
}
|
||||
for (let i = 0; i < node.childNodes.length; i++) {
|
||||
const child = node.childNodes[i];
|
||||
const textNode = getFirstTextNode(child);
|
||||
if (textNode) {
|
||||
return textNode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = computed(() => {
|
||||
const content = props.data.content;
|
||||
|
||||
return content;
|
||||
|
||||
// 暂时不上线文案插入功能,后续如果有需要再打开
|
||||
// // 未发布文章直接返回 status = 2 已发布
|
||||
// if(!content || props.data.status !== 2) {
|
||||
// return content;
|
||||
// }
|
||||
|
||||
// // 插入文案
|
||||
// const insertText = `中证参考海外资讯${dayjs(props.data.publishTime).format('MM月DD日')}援引${props.data.source}`;
|
||||
// const dom = new DOMParser().parseFromString(content, "text/html");
|
||||
// const body = dom.querySelector("body");
|
||||
// const p = body?.childNodes;
|
||||
// for(let i = 0; i < p.length; i++){
|
||||
// const textNode = getFirstTextNode(p[i]);
|
||||
// console.log(textNode)
|
||||
// if(textNode){
|
||||
// textNode.textContent = insertText + textNode.textContent;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return body?.innerHTML;
|
||||
});
|
||||
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 未登录|试用,显示蒙层
|
||||
const isMask = computed(() => {
|
||||
return !userStore.isLogin || !isUserType.value;
|
||||
});
|
||||
// 判断入口是h5还是其他,h5入口需要判断账号是试用|正式
|
||||
const isUserType = computed(() => {
|
||||
return props.access === "h5" ? userStore.isUserType : true;
|
||||
});
|
||||
|
||||
// 登录弹框
|
||||
const LoginShow = ref(false);
|
||||
|
||||
// 显示弹框
|
||||
const handleShowLogin = () => {
|
||||
LoginShow.value = true;
|
||||
};
|
||||
|
||||
// 关闭弹框
|
||||
const handleLoginCancel = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录成功之后的回调
|
||||
const handleLoginSuccess = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录失败之后的回调
|
||||
const handleLoginError = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
|
||||
const tagList2 = ref([
|
||||
{
|
||||
|
|
@ -104,10 +309,23 @@ const handleClick = (value: any) => {
|
|||
show.value = value;
|
||||
};
|
||||
|
||||
const intoType = ref(null);
|
||||
onLoad((option) => {
|
||||
type.value = option?.type || "list";
|
||||
intoType.value = option?.intoType || null;
|
||||
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
}
|
||||
});
|
||||
|
||||
function goEtfDetail(item) {
|
||||
console.log("🚀 ~ goEtfDetail ~ item:", item);
|
||||
uni.navigateTo({
|
||||
url: `/pages/realtimeInfo/indexEtfInfo?name=${item.name}&code=${item.code}`,
|
||||
});
|
||||
}
|
||||
|
||||
const handleSub = () => {
|
||||
if (type.value === "list") {
|
||||
let mainItemId = uni.getStorageSync("mainItem");
|
||||
|
|
@ -155,12 +373,37 @@ const handleSub = () => {
|
|||
|
||||
show.value = false;
|
||||
};
|
||||
|
||||
// 拓展阅读跳转新闻详情
|
||||
const goNewsDetail = (item: any) => {
|
||||
if (props.access === "h5") {
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 拓展阅读更多
|
||||
const isMore = ref(false);
|
||||
const getMoreNews = () => {
|
||||
isMore.value = true;
|
||||
emit("getFurtherReadData");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
background-color: #f3f5f8;
|
||||
// padding-bottom: 80rpx;
|
||||
}
|
||||
.main {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
padding-bottom: 50rpx;
|
||||
|
||||
.title {
|
||||
padding-top: 16rpx;
|
||||
|
|
@ -201,15 +444,16 @@ const handleSub = () => {
|
|||
.desc {
|
||||
padding: 12rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #f2f4fa;
|
||||
width: 700rpx;
|
||||
margin: 30rpx auto;
|
||||
color: rgba(51, 51, 51, 0.6);
|
||||
color: #666666;
|
||||
// font-size: 28rpx;
|
||||
font-size: var(--h2-font-size);
|
||||
// text-indent: 0.5em;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: break-word;
|
||||
line-height: 40rpx;
|
||||
|
||||
/* 在必要时单词内部断行 */
|
||||
.bill_icon {
|
||||
|
|
@ -273,7 +517,9 @@ const handleSub = () => {
|
|||
gap: 10rpx;
|
||||
|
||||
.tag {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #3f80fa;
|
||||
|
|
@ -284,4 +530,204 @@ const handleSub = () => {
|
|||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.mohu {
|
||||
filter: blur(4px);
|
||||
}
|
||||
|
||||
.zhaiyao_icon {
|
||||
width: 72rpx;
|
||||
height: 51rpx;
|
||||
margin-top: 10rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.r_etf {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
|
||||
.etfs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.etf_title {
|
||||
padding-left: 53rpx;
|
||||
background-image: url("@/assets/images/page/page_icon_1@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 40rpx 40rpx;
|
||||
background-position: 0 center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #222222;
|
||||
line-height: 42rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.etf_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx;
|
||||
background: rgba(240, 247, 255, 1);
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.name {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #222222;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
.code {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 30rpx;
|
||||
text-align: right;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.stock_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx;
|
||||
background: rgba(240, 247, 255, 1);
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.name {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #222222;
|
||||
line-height: 30rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
.code {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 30rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.percent {
|
||||
padding-right: 25rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
color: #2fa054;
|
||||
line-height: 33rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
&.up {
|
||||
color: #e6253b;
|
||||
background: url("@/assets/images/page/up2_icon@2x.png") no-repeat right center;
|
||||
background-size: 20rpx 12rpx;
|
||||
}
|
||||
&.down {
|
||||
color: #2fa054;
|
||||
background: url("@/assets/images/page/down2_icon@2x.png") no-repeat right center;
|
||||
background-size: 20rpx 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.company-tag {
|
||||
padding: 30rpx 40rpx 0;
|
||||
display: flex;
|
||||
.txt {
|
||||
margin-right: 16rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #d6a68c;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.more-news {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.more-news-title {
|
||||
padding-left: 53rpx;
|
||||
background-image: url("@/assets/images/page/page_icon_2@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 40rpx 40rpx;
|
||||
background-position: 0 center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #222222;
|
||||
line-height: 42rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.more-news-list {
|
||||
margin-top: 30rpx;
|
||||
|
||||
.news {
|
||||
padding: 30rpx 0;
|
||||
border-bottom: 2rpx solid #f3f3f5;
|
||||
.title {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
margin-top: 22rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.text {
|
||||
padding-right: 31rpx;
|
||||
background: url("@/assets/images/page/grey_down@2x.png") no-repeat right center;
|
||||
background-size: 21rpx 11rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.aaa{
|
||||
float: left;
|
||||
margin-top: 36rpx;
|
||||
font-size: var(--h2-font-size);
|
||||
color: #333;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,326 @@
|
|||
<template>
|
||||
<view class="list" v-if="data.length">
|
||||
<view class="listItem" v-for="item in props.data" :key="item.id" @click="handleClick(item)">
|
||||
<view class="listItemHeader">
|
||||
<view class="ListItemImg" v-if="item.picture">
|
||||
<image :src="item.picture" class="ListItemImage" mode="widthFix" style="width: 204rpx" />
|
||||
<image class="ListItemBg" :src="item.picture" style="width: 100%; height: 100%" />
|
||||
<view class="tag" v-if="item.newType !== 'search'">{{ item.tag }}</view>
|
||||
</view>
|
||||
<view class="listItemHeaderContent">
|
||||
<view v-if="!isLogin">
|
||||
<div :class="['listItemTitle']" v-html="item.title"></div>
|
||||
<!-- <text :class="['listItemTitle']">{{ item.title.slice(0, 3) }}</text>
|
||||
<text :class="['listItemTitle', isLogin ? '' : 'mohu']">
|
||||
{{ item.title.slice(3, item.title.length) }}
|
||||
</text> -->
|
||||
</view>
|
||||
<view v-else>
|
||||
<view :class="['listItemTitle1']" v-html="item.title"> </view>
|
||||
</view>
|
||||
<view :class="['listItemAbstract', isLogin ? '' : 'mohu']" v-if="item.newType !== 'search'"
|
||||
v-html="item.summary"></view>
|
||||
<view :class="['listItemAbstract', isLogin ? '' : 'mohu']" v-else
|
||||
v-html="item.MarkInRedContent || item.abstract"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="tabContainer">
|
||||
<view class="tag">{{ item.tag }}</view>
|
||||
</view> -->
|
||||
<!--
|
||||
<view :class="['listItemContent', isLogin ? '' : 'mohu']">
|
||||
<view style="display: flex">
|
||||
<view class="tag">{{ item.tag }}</view>
|
||||
<view class="listItemTime" style="margin-left: 10rpx">{{ item.time }}</view>
|
||||
</view>
|
||||
|
||||
<view class="r_option">
|
||||
<image class="option_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/eye_icon%402x.png"></image>
|
||||
<text class="option_text">{{ item.readNums }}</text>
|
||||
|
||||
<image class="option_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/like_icon%402x.png"></image>
|
||||
<text class="option_text">{{ item.likeNums }}</text>
|
||||
|
||||
<image class="option_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/share_icon%402x.png"></image>
|
||||
<text class="option_text">{{ item.shareNums }}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- <view class="listItemFooter" v-if="item.needpay"></view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-empty mode="news" v-else> </u-empty>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { Session } from "@/utils/storage";
|
||||
|
||||
const emit = defineEmits(["handleListJump", "onClick"]);
|
||||
// const isLogin = ref(uni.getStorageSync("token"));
|
||||
const isLogin = ref(Session.get("token"));
|
||||
|
||||
const props = defineProps({
|
||||
// 列表内容
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
console.log("props ===>", props.data);
|
||||
const handleListJump = (item) => {
|
||||
emit("handleListJump", item);
|
||||
};
|
||||
|
||||
// 点击新闻传给父组件
|
||||
const handleClick = (item: any) => {
|
||||
emit("onClick", item);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list {
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
padding: 0 40rpx 30rpx 40rpx;
|
||||
border-radius: 10rpx;
|
||||
font-family: "SourceHanSansCN-Regular";
|
||||
|
||||
.listItem {
|
||||
border-bottom: 2rpx solid rgba(51, 51, 51, 0.1);
|
||||
box-sizing: border-box;
|
||||
padding: 30rpx 0;
|
||||
|
||||
.listItemHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.ListItemImg {
|
||||
width: 204rpx;
|
||||
height: 204rpx;
|
||||
border-radius: 9rpx;
|
||||
overflow: hidden;
|
||||
background-color: #c4c4c4;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
margin-right: 12rpx;
|
||||
|
||||
.ListItemImage {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.ListItemBg {
|
||||
filter: blur(30rpx);
|
||||
}
|
||||
|
||||
.tag {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
background-color: #e7303f;
|
||||
// font-size: 20rpx;
|
||||
font-size: var(--h6-font-size);
|
||||
color: #fff;
|
||||
z-index: 9;
|
||||
}
|
||||
}
|
||||
|
||||
.listItemHeaderContent {
|
||||
// width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-left: 0rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.listItemTitle1 {
|
||||
font-size: 32rpx;
|
||||
font-size: var(--h1-font-size);
|
||||
color: #333;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
color: #192236;
|
||||
line-height: 45rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.listItemTitle {
|
||||
// font-size: 32rpx;
|
||||
// font-size: var(--h1-font-size);
|
||||
// color: #333;
|
||||
// display: -webkit-box;
|
||||
// -webkit-box-orient: vertical;
|
||||
// -webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
color: #192236;
|
||||
line-height: 45rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
// text-align: left;
|
||||
&.noAbstract {
|
||||
-webkit-line-clamp: 4;
|
||||
}
|
||||
|
||||
.isVip {
|
||||
display: inline-block;
|
||||
width: 50rpx;
|
||||
height: 29rpx;
|
||||
background-image: url(https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/icon_vip.png);
|
||||
background-size: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.listItemTitleContent {
|
||||
// font-size: 32rpx;
|
||||
font-size: var(--h1-font-size);
|
||||
// color: #333;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
// font-weight: bold;
|
||||
|
||||
.isVip {
|
||||
display: inline-block;
|
||||
width: 50rpx;
|
||||
height: 29rpx;
|
||||
background-image: url(https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/icon_vip.png);
|
||||
background-size: cover;
|
||||
box-sizing: border-box;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.listItemAbstract {
|
||||
box-sizing: border-box;
|
||||
padding-top: 12rpx;
|
||||
// font-size: 26rpx;
|
||||
font-size: var(--h3-font-size);
|
||||
color: rgba(51, 51, 51, 0.6);
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #2d3849;
|
||||
line-height: 33rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.listItemContent {
|
||||
// font-size: 20rpx;
|
||||
font-size: var(--h6-font-size);
|
||||
color: #b9b9b9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
padding: 21rpx 0 0 0;
|
||||
|
||||
.listItemData {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.dataItem {
|
||||
margin-right: 12rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tabContainer {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
padding-top: 21rpx;
|
||||
|
||||
.tag {
|
||||
box-sizing: border-box;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
background-color: #e7303f;
|
||||
// font-size: 20rpx;
|
||||
font-size: var(--h6-font-size);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.listItemFooter {
|
||||
height: 74rpx;
|
||||
margin-top: 15rpx;
|
||||
background-image: url(https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/vip_sub_2.png);
|
||||
background-size: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.listItemTitleContentText {
|
||||
font-family: "SourceHanSansCN-Medium";
|
||||
}
|
||||
|
||||
.r_option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
|
||||
.option_icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
}
|
||||
|
||||
.option_text {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #192236;
|
||||
line-height: 33rpx;
|
||||
text-align: justify;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.mohu {
|
||||
filter: blur(7rpx);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -28,7 +28,7 @@ const colorList = ["#F05040", "#696BBE", "#93CFED", "#FE9F19", "#3C74F1"];
|
|||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => { },
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -42,8 +42,8 @@ watch(
|
|||
keys.value.push(item.key);
|
||||
values.value.push(item.doc_count);
|
||||
});
|
||||
keys.value.reverse()
|
||||
values.value.reverse()
|
||||
keys.value.reverse();
|
||||
values.value.reverse();
|
||||
initChart();
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
<template>
|
||||
<view>
|
||||
<div ref="chartDom" style="width: 100vw; height: 700rpx"></div>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch, onMounted, reactive, ref } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { newsInfoScore } from "@/api/newsInfo";
|
||||
|
||||
const chartDom = ref(null);
|
||||
let myChart = null;
|
||||
|
||||
const data = reactive({});
|
||||
const keys = ref([]);
|
||||
const values = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
barColor: {
|
||||
type: String,
|
||||
default: "#3C74F1",
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
initChart();
|
||||
}
|
||||
}
|
||||
);
|
||||
const colorList = ["#F05040", "#696BBE", "#93CFED", "#FE9F19", "#3C74F1", "#F05040", "#696BBE", "#93CFED", "#FE9F19", "#3C74F1"];
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
myChart = echarts.init(chartDom.value);
|
||||
|
||||
const builderJson = {
|
||||
all: 10887,
|
||||
charts: {},
|
||||
components: {
|
||||
geo: 2788,
|
||||
title: 9575,
|
||||
legend: 9400,
|
||||
tooltip: 9466,
|
||||
grid: 9266,
|
||||
markPoint: 3419,
|
||||
markLine: 2984,
|
||||
timeline: 2739,
|
||||
dataZoom: 2744,
|
||||
visualMap: 2466,
|
||||
toolbox: 3034,
|
||||
polar: 1945,
|
||||
},
|
||||
ie: 9743,
|
||||
};
|
||||
// 查找value最大的项
|
||||
const maxItem = props.data.reduce((prev, current) => {
|
||||
// 比较当前项和上一项的value,返回较大的那个
|
||||
return current.value > prev.value ? current : prev;
|
||||
}, props.data[0]); // 初始值设为数组的第一个元素
|
||||
|
||||
props.data.forEach((item) => {
|
||||
builderJson.charts[item.content] = item.value;
|
||||
});
|
||||
builderJson.all = maxItem.value;
|
||||
|
||||
const waterMarkText = "ECHARTS";
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
// canvas.width = canvas.height = 100;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.globalAlpha = 0.08;
|
||||
ctx.font = "20px Microsoft Yahei";
|
||||
ctx.translate(50, 50);
|
||||
ctx.rotate(-Math.PI / 4);
|
||||
ctx.fillText(waterMarkText, 0, 0);
|
||||
let option = {
|
||||
// backgroundColor: {
|
||||
// type: "pattern",
|
||||
// image: canvas,
|
||||
// repeat: "repeat",
|
||||
// },
|
||||
tooltip: {},
|
||||
title: [],
|
||||
grid: [
|
||||
{
|
||||
top: 0,
|
||||
width: "90%",
|
||||
top: "5%",
|
||||
bottom: "10%",
|
||||
left: 10,
|
||||
containLabel: true,
|
||||
},
|
||||
],
|
||||
xAxis: [
|
||||
{
|
||||
type: "value",
|
||||
max: builderJson.all,
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: Object.keys(builderJson.charts),
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
rotate: 30,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: "bar",
|
||||
stack: "chart",
|
||||
z: 3,
|
||||
label: {
|
||||
position: "right",
|
||||
show: true,
|
||||
},
|
||||
itemStyle: {
|
||||
color: props.barColor,
|
||||
normal: {
|
||||
borderRadius: [0, 4, 4, 0],
|
||||
color: props.barColor,
|
||||
// color: function (params) {
|
||||
// return colorList[params.dataIndex];
|
||||
// },
|
||||
},
|
||||
},
|
||||
data: Object.keys(builderJson.charts).map(function (key) {
|
||||
return builderJson.charts[key];
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
//使用配置
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// setInterval(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// }, 5000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<template>
|
||||
<view>
|
||||
<div ref="chartDom" style="width: 100vw; height: 700rpx"></div>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch, onMounted, reactive, ref } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
import { newsInfoScore } from "@/api/newsInfo";
|
||||
|
||||
const chartDom = ref(null);
|
||||
let myChart = null;
|
||||
|
||||
const data = reactive({});
|
||||
const keys = ref([]);
|
||||
const values = ref([]);
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
barColor: {
|
||||
type: String,
|
||||
default: "#3C74F1",
|
||||
},
|
||||
});
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
myChart = echarts.init(chartDom.value);
|
||||
let source = [];
|
||||
source.push(["score", "amount", "product"]);
|
||||
props.data.forEach((item) => {
|
||||
source.push([item.value, item.value, item.content]);
|
||||
});
|
||||
|
||||
let option = {
|
||||
dataset: {
|
||||
source: source,
|
||||
// [
|
||||
// ["score", "amount", "product"],
|
||||
// [89.3, 58212, "Matcha Latte"],
|
||||
// [57.1, 78254, "Milk Tea"],
|
||||
// [74.4, 41032, "Cheese Cocoa"],
|
||||
// [50.1, 12755, "Cheese Brownie"],
|
||||
// [89.7, 20145, "Matcha Cocoa"],
|
||||
// [68.1, 79146, "Tea"],
|
||||
// [19.6, 91852, "Orange Juice"],
|
||||
// [10.6, 101852, "Lemon Juice"],
|
||||
// [32.7, 20112, "Walnut Brownie"],
|
||||
// ],
|
||||
},
|
||||
grid: {
|
||||
top: 0,
|
||||
width: "90%",
|
||||
top: "5%",
|
||||
bottom: "10%",
|
||||
left: 10,
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "category",
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
rotate: 30,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
// visualMap: {
|
||||
// show: false,
|
||||
// orient: "horizontal",
|
||||
// left: "center",
|
||||
// min: 1,
|
||||
// max: 100,
|
||||
// text: ["High Score", "Low Score"],
|
||||
// // Map the score column to color
|
||||
// dimension: 0,
|
||||
// inRange: {
|
||||
// color: ["#65B581", "#FFCE34", "#FD665F"],
|
||||
// },
|
||||
// },
|
||||
series: [
|
||||
{
|
||||
type: "bar",
|
||||
label: {
|
||||
position: "right",
|
||||
show: true,
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#FFCE34",
|
||||
normal: {
|
||||
borderRadius: [0, 4, 4, 0],
|
||||
color: props.barColor,
|
||||
// color: function (params) {
|
||||
// return colorList[params.dataIndex];
|
||||
// },
|
||||
},
|
||||
},
|
||||
encode: {
|
||||
// Map the "amount" column to X axis.
|
||||
x: "amount",
|
||||
// Map the "product" column to Y axis
|
||||
y: "product",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
//使用配置
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
initChart();
|
||||
}
|
||||
}
|
||||
);
|
||||
onMounted(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// setInterval(async () => {
|
||||
// await getData();
|
||||
// initChart();
|
||||
// }, 5000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<div ref="chatRef" class="chat-box"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
const chatRef = ref(null);
|
||||
let myChart = null;
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
myChart = echarts.init(chatRef.value);
|
||||
|
||||
let option = {
|
||||
color: ["#4681FF"],
|
||||
radar: {
|
||||
// shape: 'circle',
|
||||
startAngle: 90,
|
||||
axisNameGap: 10,
|
||||
indicator: [
|
||||
{ name: "资本市场相关", max: 100 },
|
||||
{ name: "潜在信号", max: 100 },
|
||||
{ name: "产业政策", max: 100 },
|
||||
{ name: "地缘影响", max: 100 },
|
||||
{ name: "风险性", max: 100 },
|
||||
{ name: "话题性", max: 100 },
|
||||
{ name: "历史溯洄", max: 100 },
|
||||
{ name: "行业导向", max: 100 },
|
||||
{ name: "媒体影响力", max: 100 },
|
||||
{ name: "资讯质量", max: 100 },
|
||||
],
|
||||
axisName: {
|
||||
color: "#666666",
|
||||
fontSize: 12,
|
||||
fontWeight: 400,
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: "rgba(234, 234, 236, 1)",
|
||||
},
|
||||
},
|
||||
splitNumber: 5
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "radar",
|
||||
areaStyle: { color: "rgba(62, 122, 252, 0.20)" },
|
||||
data: [
|
||||
{
|
||||
value: [90, 75, 72, 98, 70, 75, 80, 95, 90, 60],
|
||||
name: "AI追踪海外资讯",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
//使用配置
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => chatRef.value,
|
||||
() => {
|
||||
if (!chatRef.value) return;
|
||||
initChart();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.chat-box {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,44 +1,25 @@
|
|||
<template>
|
||||
<view class="comment">
|
||||
<Tips v-if="messageShow" />
|
||||
<view class="comment-input">
|
||||
<input
|
||||
type="text"
|
||||
confrim-type="done"
|
||||
placeholder="输入评论内容……"
|
||||
class="input-field"
|
||||
v-model="comment"
|
||||
@confirm="handleSubmit"
|
||||
/>
|
||||
|
||||
<!-- <view class="input-field">输入评论内容……</view> -->
|
||||
</view>
|
||||
<view class="comment-count">
|
||||
<view class="count" @click="handleClickLike">
|
||||
<image :src="props.data.isLike ? IconLikeActive : IconLike" class="icon" />
|
||||
<text class="num">{{ props.data.likeNums }}</text>
|
||||
<view class="count zan" @click="handleClickLike">
|
||||
<view :class="['icon', { active: props.data.isLike }]" />
|
||||
<text class="num">点赞</text>
|
||||
</view>
|
||||
<view class="count" @click="handleClickStar">
|
||||
<image :src="props.data.isFav ? IconStarActive : IconStar" class="icon" />
|
||||
<text class="num">{{ props.data.favNums }}</text>
|
||||
<view class="count fav" @click="handleClickStar">
|
||||
<view :class="['icon', { active: props.data.isFav }]" />
|
||||
<text class="num">收藏</text>
|
||||
</view>
|
||||
<!-- <view class="count">
|
||||
<image src="@/static/icon_message.png" class="icon" />
|
||||
<text class="num">{{
|
||||
props.data.comment > 1000 ? "999+" : props.data.comment
|
||||
}}</text>
|
||||
</view> -->
|
||||
<!-- <button class="count" style="background-color: transparent;" open-type="share">
|
||||
<image src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/share_icon%402x.png" class="icon" />
|
||||
<text class="num">分享</text>
|
||||
</button> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
// import { likeNews } from "@/api";
|
||||
import IconLike from "@/static/icon_like.png";
|
||||
import IconStar from "@/static/icon_star.png";
|
||||
import IconLikeActive from "@/static/icon_like_active.png";
|
||||
import IconStarActive from "@/static/icon_star_active.png";
|
||||
|
||||
const emit = defineEmits(["handleClickLike", "handleClickStar"]);
|
||||
const messageShow = ref(false);
|
||||
const props = defineProps({
|
||||
|
|
@ -78,17 +59,19 @@ const handleSubmit = () => {
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 112rpx;
|
||||
height: 80rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 10rpx rgba(51, 51, 51, 0.3);
|
||||
// box-shadow: 0 0 10rpx rgba(51, 51, 51, 0.3);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 24rpx;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px -1px 0px 0px #dfdfe0;
|
||||
|
||||
.comment-input {
|
||||
width: 100%;
|
||||
|
||||
.input-field {
|
||||
height: 72rpx;
|
||||
background-color: #f5f5f5;
|
||||
|
|
@ -100,6 +83,7 @@ const handleSubmit = () => {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-placeholder {
|
||||
color: rgba(51, 51, 51, 0.6);
|
||||
}
|
||||
|
|
@ -107,25 +91,58 @@ const handleSubmit = () => {
|
|||
|
||||
.comment-count {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
width: 100vw;
|
||||
|
||||
.count {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: 24rpx;
|
||||
width: 100%;
|
||||
|
||||
.num {
|
||||
margin-left: 12rpx;
|
||||
// font-size: 24rpx;
|
||||
font-size: var(--h4-font-size);
|
||||
color: #333;
|
||||
margin-left: 15rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
.icon {
|
||||
width: 33rpx;
|
||||
height: 34rpx;
|
||||
}
|
||||
|
||||
&.zan {
|
||||
.icon {
|
||||
background-image: url("@/assets/images/page/icon_zan@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 33rpx 34rpx;
|
||||
|
||||
&.active {
|
||||
background-image: url("@/assets/images/page/icon_zan_press@2x.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.fav {
|
||||
.icon {
|
||||
background-image: url("@/assets/images/page/shoucang_icon@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 33rpx 34rpx;
|
||||
|
||||
&.active {
|
||||
background-image: url("@/assets/images/page/shoucang_icon_press@2x.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,56 +1,29 @@
|
|||
<template>
|
||||
<!-- <view class="loginPopup"> -->
|
||||
<u-popup
|
||||
class="loginPopup"
|
||||
:show="props.show"
|
||||
closeable
|
||||
:mode="props.mode"
|
||||
round="12"
|
||||
:closeOnClickOverlay="false"
|
||||
@close="handlePopupClose"
|
||||
>
|
||||
<u-popup class="loginPopup" :show="props.show" closeable :mode="props.mode" round="12" :closeOnClickOverlay="false"
|
||||
@close="handlePopupClose">
|
||||
<view class="loginPopupContent">
|
||||
<view class="loginTitle">登录后掌握更多优质财经内容</view>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<view class="loginForm">
|
||||
<u--form :model="state.loginForm" ref="uForm">
|
||||
<u-form-item
|
||||
style="padding: 0"
|
||||
class="loginFormItem"
|
||||
prop="userInfo.name"
|
||||
borderBottom
|
||||
ref="item1"
|
||||
>
|
||||
<u--input
|
||||
class="loginFormInput"
|
||||
placeholder="请输入您的手机号"
|
||||
v-model="state.loginForm.phone"
|
||||
border="none"
|
||||
></u--input>
|
||||
<u-form-item style="padding: 0" class="loginFormItem" prop="userInfo.name" borderBottom ref="item1">
|
||||
<u--input class="loginFormInput" placeholder="请输入您的手机号" v-model="state.loginForm.phone"
|
||||
border="none"></u--input>
|
||||
</u-form-item>
|
||||
<u-form-item
|
||||
class="loginFormItem"
|
||||
prop="userInfo.name"
|
||||
borderBottom
|
||||
ref="item1"
|
||||
>
|
||||
<u--input
|
||||
class="loginFormInput"
|
||||
placeholder="请输入短信验证码"
|
||||
v-model="state.loginForm.code"
|
||||
border="none"
|
||||
></u--input>
|
||||
<u-form-item class="loginFormItem" prop="userInfo.name" borderBottom ref="item1">
|
||||
<u--input class="loginFormInput" placeholder="请输入短信验证码" v-model="state.loginForm.code"
|
||||
border="none"></u--input>
|
||||
<view class="getCode" @click="captcha">{{ codeText }}</view>
|
||||
</u-form-item>
|
||||
</u--form>
|
||||
<u-button class="loginFormBtn" text="登录" @click="Login"></u-button>
|
||||
</view>
|
||||
<!-- 用户协议 -->
|
||||
<view class="tips"
|
||||
>登录即代表已经阅读并同意
|
||||
<view class="userAgreement">《用户协议》</view></view
|
||||
>
|
||||
<view class="tips">登录即代表已经阅读并同意
|
||||
<view class="userAgreement">《用户协议》</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<!-- </view> -->
|
||||
|
|
@ -130,6 +103,8 @@ const handlePopupSuccessCallback = () => {
|
|||
const handlePopupErrorCallback = () => {
|
||||
emit("handlePopupErrorCallback");
|
||||
};
|
||||
const { aplus_queue } = window;
|
||||
|
||||
// 登录
|
||||
const Login = async () => {
|
||||
if (!validatePhoneNumber(state.loginForm.phone)) {
|
||||
|
|
@ -155,6 +130,14 @@ const Login = async () => {
|
|||
});
|
||||
console.log(code, "<=== code");
|
||||
if (code === 200) {
|
||||
aplus_queue.push({
|
||||
action: 'aplus.record',
|
||||
arguments: ['login', 'CLK', {
|
||||
phone: data.phone,
|
||||
}]
|
||||
});
|
||||
|
||||
|
||||
uni.hideLoading();
|
||||
Session.set("token", data.token);
|
||||
Session.set("userPhone", data.phone);
|
||||
|
|
@ -163,6 +146,7 @@ const Login = async () => {
|
|||
icon: "success",
|
||||
});
|
||||
handlePopupSuccessCallback();
|
||||
|
||||
} else {
|
||||
console.log(msg, "<=== msg");
|
||||
handlePopupErrorCallback();
|
||||
|
|
@ -188,6 +172,7 @@ const handlePopupClose = () => {
|
|||
width: 100%;
|
||||
height: 786rpx;
|
||||
}
|
||||
|
||||
.u-popup__content__close {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
|
@ -223,11 +208,13 @@ const handlePopupClose = () => {
|
|||
&:nth-child(2) {
|
||||
margin: 32rpx 0;
|
||||
}
|
||||
|
||||
::v-deep {
|
||||
.u-form-item__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.loginFormInput {
|
||||
width: 100%;
|
||||
height: 100rpx !important;
|
||||
|
|
@ -244,6 +231,7 @@ const handlePopupClose = () => {
|
|||
font-size: var(--h1-font-size);
|
||||
color: rgba(51, 51, 51, 0.6);
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
|
|
@ -263,6 +251,7 @@ const handlePopupClose = () => {
|
|||
border: none;
|
||||
background-color: #e7303f;
|
||||
color: #fff;
|
||||
|
||||
::v-deep {
|
||||
.u-button__text {
|
||||
font-size: var(--h1-font-size) !important;
|
||||
|
|
@ -277,6 +266,7 @@ const handlePopupClose = () => {
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
color: #717171;
|
||||
|
||||
.userAgreement {
|
||||
color: #333;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,7 @@
|
|||
<view class="userContainer">
|
||||
<u-avatar :src="avatarImg" size="60"></u-avatar>
|
||||
<view class="userData">
|
||||
<text class="phone">{{
|
||||
!isLoginStatus
|
||||
? "未登录用户"
|
||||
: maskPhoneNumber(Session.get("userPhone"))
|
||||
}}</text>
|
||||
<text class="phone">{{ !isLoginStatus ? "未登录用户" : maskPhoneNumber(Session.get("userPhone")) }}</text>
|
||||
<!-- <view class="setUserData">
|
||||
编辑我的个人资料
|
||||
<u-icon size="12" name="arrow-right"></u-icon>
|
||||
|
|
@ -98,9 +94,7 @@
|
|||
|
||||
<!-- 退出登录的按钮 -->
|
||||
<view class="loginOut" :class="!isLoginStatus && 'loginBtn'">
|
||||
<u-button type="danger" size="large" @click="loginBtnStatus">{{
|
||||
!isLoginStatus ? "点击登录" : "退出登录"
|
||||
}}</u-button>
|
||||
<u-button type="danger" size="large" @click="loginBtnStatus">{{ !isLoginStatus ? "点击登录" : "退出登录" }}</u-button>
|
||||
</view>
|
||||
|
||||
<!-- 登录弹框 -->
|
||||
|
|
@ -127,6 +121,8 @@ import like from "@/assets/images/like.png";
|
|||
import time from "@/assets/images/time.png";
|
||||
import vip from "@/assets/images/vip.png";
|
||||
import { useShareStore } from "@/stores/shareStore";
|
||||
import { doLogout } from "@/api";
|
||||
|
||||
const stores = useShareStore();
|
||||
const curPages = getCurrentPages();
|
||||
|
||||
|
|
@ -177,6 +173,9 @@ const loginOut = () => {
|
|||
icon: "none",
|
||||
duration: 1500,
|
||||
});
|
||||
doLogout({
|
||||
financialAccount: Session.get("userPhone"),
|
||||
});
|
||||
// 清除 cookie
|
||||
Session.clear();
|
||||
uni.removeStorageSync("subStatus");
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@ import pinia from "@/stores/index";
|
|||
import App from "./App.vue";
|
||||
import uviewPlus from "@/uni_modules/uview-plus";
|
||||
import "@/assets/fonts/font.css";
|
||||
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App);
|
||||
app.use(pinia).use(uviewPlus);
|
||||
app.use(ElementPlus)
|
||||
return {
|
||||
app,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,6 +19,15 @@
|
|||
{
|
||||
"path": "pages/mine/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/realtimeInfo/indexRelease"
|
||||
},
|
||||
{
|
||||
"path": "pages/realtimeInfo/indexEtf"
|
||||
},
|
||||
{
|
||||
"path": "pages/realtimeInfo/indexEtfInfo"
|
||||
},
|
||||
{
|
||||
"path": "pages/sreachReq/index"
|
||||
},
|
||||
|
|
@ -66,6 +75,24 @@
|
|||
},
|
||||
{
|
||||
"path": "pages/realtimeInfo/pc/indexPC"
|
||||
},
|
||||
{
|
||||
"path": "pages/foreign/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/recommend/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/macroscopic/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/industry/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/concept/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/topNews/index"
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
|
@ -82,4 +109,4 @@
|
|||
"allowsBounceVertical": "YES"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,451 @@
|
|||
<template>
|
||||
<view class="custom-container" @click.stop>
|
||||
<!-- 导航栏 start -->
|
||||
<view class="custom-bav-bar">
|
||||
<view class="left">
|
||||
<u-icon name="arrow-left" color="#666" size="36rpx" @click="handleBack" />
|
||||
</view>
|
||||
<view class="center"> 添加自选风口概念 </view>
|
||||
</view>
|
||||
<!-- 导航栏 end -->
|
||||
|
||||
<!-- 搜搜 start -->
|
||||
<view class="page-search">
|
||||
<u-input
|
||||
v-model="input"
|
||||
type="text"
|
||||
placeholder="输入概念名称查找"
|
||||
prefixIcon="search"
|
||||
fontSize="28rpx"
|
||||
prefixIconStyle="font-size: 40rpx;color: #BDC1C7;"
|
||||
:customStyle="{
|
||||
borderRadius: '36rpx',
|
||||
background: '#F3F5F8',
|
||||
}"
|
||||
clearable
|
||||
@confirm="handleSearchTag"
|
||||
/>
|
||||
</view>
|
||||
<!-- 搜搜 end -->
|
||||
|
||||
<view class="custom-main">
|
||||
<view class="my-industry">
|
||||
<view class="my-industry-top">
|
||||
<view class="label">我的风口</view>
|
||||
<view class="label-count">
|
||||
<text>已选</text>
|
||||
<text class="color">{{ myTagList.length }}</text>
|
||||
<text>/10</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="my-industry-list" v-if="myTagList.length > 0">
|
||||
<view class="industry-item" v-for="(item, index) in myTagList">
|
||||
<view class="industry-name">{{ item.name.split("-")[1] }}</view>
|
||||
<view class="industry-btn" @click="handleDeleteTag(index)"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="my-industry-empty" v-else> 暂无自选,请从下方添加 </view>
|
||||
</view>
|
||||
<view class="recommend-industry">
|
||||
<view class="recommend-industry-top">
|
||||
<view class="label">预期风口</view>
|
||||
<view class="right" @click="handleChange">
|
||||
<view class="icon"></view>
|
||||
<view class="text">换一换</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="recommend-industry-list" v-if="industryList.length > 0">
|
||||
<view
|
||||
v-for="(item, index) in industryList"
|
||||
:key="index"
|
||||
:class="['industry-item', { active: isSelected(item.content) }]"
|
||||
@click="handleAddTag(item.content)"
|
||||
>
|
||||
<view class="industry-name">{{ item.content.split("-")[1] }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="no-data"> <u-empty /></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="custom-footer">
|
||||
<view class="btn-clear" @click="handleClear">清空</view>
|
||||
<view class="btn-done" @click="handleComplete">完成配置</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getTopConceptPeriod } from "@/api/newsInfo";
|
||||
import dayjs from "dayjs";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
tagList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
allTagList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["onChange", "onBack"]);
|
||||
|
||||
const input = ref("");
|
||||
|
||||
// 导航栏路由返回
|
||||
const handleBack = () => {
|
||||
if (props.tagList.length === 0) {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
} else {
|
||||
emit("onBack");
|
||||
}
|
||||
};
|
||||
|
||||
const myTagList = ref([]);
|
||||
const industryList = ref([]);
|
||||
const page = ref(0);
|
||||
|
||||
const getTagList = () => {
|
||||
return [...props.allTagList].splice(page.value, 10);
|
||||
};
|
||||
|
||||
const handleChange = () => {
|
||||
page.value = page.value ? 0 : 10;
|
||||
industryList.value = getTagList();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.allTagList,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
industryList.value = getTagList();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
// 是否选中
|
||||
function isSelected(tag) {
|
||||
const index = myTagList.value.findIndex((item) => item.name === tag);
|
||||
return index === -1 ? false : true;
|
||||
}
|
||||
// 添加标签
|
||||
function handleAddTag(tag) {
|
||||
if (isSelected(tag)) return;
|
||||
if (myTagList.value.length >= 10) {
|
||||
uni.showToast({
|
||||
title: "最多添加10个标签",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
myTagList.value.push({
|
||||
name: tag,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除标签
|
||||
function handleDeleteTag(index: number) {
|
||||
myTagList.value.splice(index, 1);
|
||||
}
|
||||
|
||||
// 搜索标签
|
||||
function handleSearchTag() {
|
||||
if (!input.value) {
|
||||
return;
|
||||
}
|
||||
industryList.value = props.allTagList.filter((item) => {
|
||||
if (!item || !item.content) return false;
|
||||
|
||||
return item.content.includes(input.value);
|
||||
});
|
||||
}
|
||||
|
||||
// 完成配置
|
||||
function handleComplete() {
|
||||
if (myTagList.value.length < 1) {
|
||||
uni.showToast({
|
||||
title: "请先选择标签",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
emit("onChange", myTagList.value);
|
||||
}
|
||||
// 清除
|
||||
function handleClear() {
|
||||
myTagList.value = [];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.tagList,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
myTagList.value = [...newVal];
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-container {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
z-index: 9;
|
||||
padding-bottom: 80rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.custom-bav-bar {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.back_icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.logo_icon {
|
||||
width: 168rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #222222;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-search {
|
||||
position: relative;
|
||||
margin-top: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 0 30rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.custom-main {
|
||||
width: 100%;
|
||||
height: calc(100% - 250rpx);
|
||||
padding: 33rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
|
||||
.my-industry {
|
||||
margin-bottom: 80rpx;
|
||||
.my-industry-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
.label {
|
||||
margin-right: 13rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #111111;
|
||||
}
|
||||
|
||||
.label-count {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
.color {
|
||||
color: #ffa800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-industry-list {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.industry-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 18rpx 30rpx;
|
||||
background: #fff9ec;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.industry-name {
|
||||
margin-right: 20rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #ffa800;
|
||||
}
|
||||
.industry-btn {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: url("@/assets/images/page/icon_close@2x.png") no-repeat;
|
||||
background-size: 20rpx 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-industry-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100rpx;
|
||||
background: #f7f8fa;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #e4e9f0;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #cccccc;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend-industry {
|
||||
.recommend-industry-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.label {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #111111;
|
||||
}
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: url("@/assets/images/page/icon_change@2x.png") no-repeat 0 3rpx;
|
||||
background-size: 32rpx 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.text {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recommend-industry-list {
|
||||
display: grid;
|
||||
gap: 20rpx;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
||||
.industry-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 18rpx 0;
|
||||
background-color: #f3f5f8;
|
||||
border-radius: 8px;
|
||||
|
||||
&.active {
|
||||
background-color: #fff9ec;
|
||||
.industry-name {
|
||||
color: #ffa800;
|
||||
}
|
||||
}
|
||||
|
||||
.industry-name {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-data {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16rpx 24rpx;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px -4px 12px 0px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
|
||||
.btn-clear {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 239rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
background: #fff;
|
||||
border: 2rpx solid #979797;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #656565;
|
||||
line-height: 45rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-done {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 437rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
background: #ffa800;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
line-height: 45rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 导航栏 start -->
|
||||
<view class="custom-bav-bar">
|
||||
<view class="left">
|
||||
<u-icon name="arrow-left" color="#666" size="36rpx" @click="handleBack" />
|
||||
</view>
|
||||
<view class="center"> 风口概念 </view>
|
||||
<view class="right" v-if="userStore.isLogin" @click="handleShowCustom">管理</view>
|
||||
</view>
|
||||
<!-- 导航栏 end -->
|
||||
|
||||
<!-- tabs start -->
|
||||
<view class="page-nav-tabs">
|
||||
<u-tabs
|
||||
:list="tagList"
|
||||
lineWidth="28rpx"
|
||||
lineColor="#222222"
|
||||
:current="current"
|
||||
:activeStyle="{
|
||||
color: '#222',
|
||||
fontWeight: '500',
|
||||
fontFamily: 'PingFangSC, PingFang SC',
|
||||
}"
|
||||
:inactiveStyle="{
|
||||
color: '#666',
|
||||
fontWeight: '400',
|
||||
fontFamily: 'PingFangSC, PingFang SC',
|
||||
}"
|
||||
itemStyle="padding-left: 15px; padding-right: 15px; height: 70rpx;"
|
||||
keyName="content"
|
||||
@change="handleChangeTag"
|
||||
>
|
||||
</u-tabs>
|
||||
</view>
|
||||
<!-- tabs end -->
|
||||
|
||||
<view class="page-main">
|
||||
<view class="banner">
|
||||
<view class="text-1">{{ tagList[current]?.content }}</view>
|
||||
<view class="text-2" v-if="tagList[current]?.index">风口概念近一个月排名{{ tagList[current]?.index }}</view>
|
||||
</view>
|
||||
|
||||
<view class="news-list">
|
||||
<u-loading-icon v-if="loading"></u-loading-icon>
|
||||
<template v-else-if="data?.length > 0">
|
||||
<view
|
||||
:class="['news-item', { mask: !userStore.isLogin }]"
|
||||
v-for="item in data"
|
||||
:key="item.id"
|
||||
@click="goDetail(item)"
|
||||
>
|
||||
<view class="title">
|
||||
<view class="name">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['content', { mask: isMask }]">
|
||||
{{ item.summary }}
|
||||
</view>
|
||||
<view :class="['source', { mask: isMask }]">
|
||||
<view>{{ item.tag }}</view>
|
||||
<view>{{ item.time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<u-empty v-else />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { getListByTag } from "@/api/detail";
|
||||
|
||||
const props = defineProps({
|
||||
tagList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["onShow", "onShowCustom"]);
|
||||
|
||||
const loading = ref(false);
|
||||
const activeTag = ref("");
|
||||
const current = computed(() => {
|
||||
return props.tagList.findIndex((item) => item.name === activeTag.value);
|
||||
});
|
||||
|
||||
const handleChangeTag = (item: any) => {
|
||||
activeTag.value = item.name;
|
||||
getList(item.name);
|
||||
};
|
||||
|
||||
// 导航栏路由返回
|
||||
const handleBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 未登录|试用,显示蒙层
|
||||
const isMask = computed(() => {
|
||||
return !userStore.isUserType;
|
||||
});
|
||||
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
}
|
||||
|
||||
// 数据列表
|
||||
const data = ref([]);
|
||||
// 新闻列表
|
||||
const getList = async (name: string) => {
|
||||
loading.value = true;
|
||||
const result = await getListByTag({ name });
|
||||
loading.value = false;
|
||||
if (result.code === 200) {
|
||||
data.value = result.data;
|
||||
} else {
|
||||
data.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.tagList,
|
||||
(newVal) => {
|
||||
if (newVal?.length > 0) {
|
||||
activeTag.value = newVal[0]?.name || "";
|
||||
getList(activeTag.value);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
const handleShowCustom = () => {
|
||||
emit("onShowCustom");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.custom-bav-bar {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.back_icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.logo_icon {
|
||||
width: 168rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #222222;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: absolute;
|
||||
top: 22rpx;
|
||||
right: 30rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-nav-tabs {
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.page-main {
|
||||
padding-top: 30rpx;
|
||||
background-color: #f3f5f8;
|
||||
|
||||
.banner {
|
||||
width: 690rpx;
|
||||
height: 113rpx;
|
||||
margin: 0 30rpx 30rpx;
|
||||
padding: 15rpx 30rpx;
|
||||
border-radius: 10rpx;
|
||||
background-image: url("@/assets/images/page/page_5_1@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 690rpx 113rpx;
|
||||
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.12);
|
||||
box-sizing: border-box;
|
||||
|
||||
.text-1 {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #ffa800;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
.text-2 {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.news-list {
|
||||
width: 100%;
|
||||
padding: 30rpx 30rpx 0;
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0px 0px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
.mask {
|
||||
filter: blur(5px);
|
||||
}
|
||||
|
||||
.news-item {
|
||||
width: 100%;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 2rpx solid #f3f3f5;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
width: 564rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
margin-bottom: 16rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
|
||||
.source {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 自定义配置 start -->
|
||||
<CustomView
|
||||
v-if="isShowCustom && userStore.isLogin"
|
||||
:tagList="tagList"
|
||||
:allTagList="allTagList"
|
||||
@onChange="handleChangeTag"
|
||||
@onBack="handleHideCustom"
|
||||
/>
|
||||
<!-- 自定义配置 end -->
|
||||
|
||||
<List
|
||||
v-show="!isShowCustom"
|
||||
:tagList="tagList"
|
||||
@onShow="handleShowLogin"
|
||||
@onShowCustom="handleShowCustom"
|
||||
/>
|
||||
|
||||
<!-- 登录弹窗 start -->
|
||||
<LoginDialog
|
||||
:show="LoginShow"
|
||||
@onSuccess="handleLoginSuccess"
|
||||
@onCancel="handleLoginCancel"
|
||||
@onError="handleLoginError"
|
||||
/>
|
||||
<!-- 登录弹窗 end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import LoginDialog from "@/pages/realtimeInfo/components/LoginPopup/index.vue";
|
||||
import CustomView from "./components/CustomView.vue";
|
||||
import List from "./components/List.vue";
|
||||
import { getMyTags, updateMyTags } from "@/api";
|
||||
import { getTopConceptPeriod } from "@/api/newsInfo";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
|
||||
const allTagList = ref([]);
|
||||
const start_time = dayjs().subtract(1, "month").format("YYYY-MM-DD");
|
||||
const end_time = dayjs().format("YYYY-MM-DD");
|
||||
const limit_num = 20;
|
||||
// 热门行业top10
|
||||
async function getTopIndustry_dFn() {
|
||||
allTagList.value = await getTopConceptPeriod({
|
||||
start_time: start_time,
|
||||
end_time: end_time,
|
||||
limit_num: limit_num,
|
||||
});
|
||||
}
|
||||
|
||||
const isShowCustom = ref(false);
|
||||
|
||||
const handleChangeTag = async (item: any) => {
|
||||
const params = item.map((tag: any) => {
|
||||
const _tag = tag.name.split("-");
|
||||
return {
|
||||
primaryName: _tag[0],
|
||||
secondaryName: _tag[1],
|
||||
};
|
||||
});
|
||||
const result = await updateMyTags(params);
|
||||
if (result.code === 200) {
|
||||
getTagList();
|
||||
handleHideCustom();
|
||||
}
|
||||
};
|
||||
|
||||
const handleShowCustom = () => {
|
||||
isShowCustom.value = true;
|
||||
};
|
||||
const handleHideCustom = () => {
|
||||
isShowCustom.value = false;
|
||||
};
|
||||
|
||||
const tagList = ref([]);
|
||||
|
||||
const getTagList = async () => {
|
||||
const result = await getMyTags();
|
||||
if (result.code === 200) {
|
||||
tagList.value = result.data.map((item: any) => {
|
||||
const name = item.primaryName + "-" + item.secondaryName;
|
||||
const content = item.secondaryName;
|
||||
const index = allTagList.value.findIndex((tag: any) => tag.content === name);
|
||||
return {
|
||||
name,
|
||||
content,
|
||||
index: index + 1,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
tagList.value = [];
|
||||
}
|
||||
|
||||
if (tagList.value.length === 0) {
|
||||
handleShowCustom();
|
||||
}
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const LoginShow = ref(false);
|
||||
// 显示弹框
|
||||
const handleShowLogin = () => {
|
||||
LoginShow.value = true;
|
||||
};
|
||||
|
||||
// 关闭弹框
|
||||
const handleLoginCancel = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录成功之后的回调
|
||||
const handleLoginSuccess = () => {
|
||||
LoginShow.value = false;
|
||||
getTagList();
|
||||
};
|
||||
// 登录失败之后的回调
|
||||
const handleLoginError = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
return;
|
||||
}
|
||||
await getTopIndustry_dFn();
|
||||
await getTagList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -11,9 +11,15 @@
|
|||
</view>
|
||||
|
||||
<!-- 文章正文 start -->
|
||||
<Article :data="data" />
|
||||
<Article
|
||||
:data="data"
|
||||
:furtherReadData="furtherReadData"
|
||||
:access="access"
|
||||
@getFurtherReadData="getFurtherReadData"
|
||||
/>
|
||||
|
||||
<!-- 分割 -->
|
||||
<view class="line"></view>
|
||||
<!-- <view class="line"></view> -->
|
||||
<!-- 推荐栏目 -->
|
||||
<!-- <Column
|
||||
:data="columnList"
|
||||
|
|
@ -32,13 +38,14 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { onReachBottom } from "@dcloudio/uni-app";
|
||||
import {
|
||||
fetchArticleDetail,
|
||||
fetchArticleLike,
|
||||
fetchArticleFavorate,
|
||||
getDetailFurtherReadData,
|
||||
} from "@/api/detail";
|
||||
import { getNewsList } from "@/api";
|
||||
import Article from "@/components/article/indexNewsInfo.vue";
|
||||
|
|
@ -53,31 +60,12 @@ const data = ref<any>({});
|
|||
const newType = ref<any>("");
|
||||
const columnList = ref<any>([]);
|
||||
const columnName = ref("");
|
||||
const furtherReadData = ref<any[]>([]);
|
||||
|
||||
onReachBottom(() => {
|
||||
console.log("🚀 ~ onReachBottom ~ onReachBottom:");
|
||||
});
|
||||
|
||||
onLoad(async (option: any) => {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
});
|
||||
newType.value = option.type || 14;
|
||||
const res = await fetchArticleDetail({
|
||||
id: option.id,
|
||||
});
|
||||
|
||||
if (res.code === 200) {
|
||||
data.value = res.data;
|
||||
|
||||
res.data.content = res.data.content.replace(/\n{3,}/g, '\n');
|
||||
|
||||
columnName.value = res.data.columnName1;
|
||||
newList(res.data.columnId1);
|
||||
wxShare();
|
||||
}
|
||||
});
|
||||
|
||||
const newList = async (columnId: number) => {
|
||||
const res = await getNewsList({
|
||||
type: 99,
|
||||
|
|
@ -85,7 +73,6 @@ const newList = async (columnId: number) => {
|
|||
page: 1,
|
||||
size: 5,
|
||||
});
|
||||
|
||||
if (res.code === 200) {
|
||||
// console.log(res.data)
|
||||
columnList.value = res.data;
|
||||
|
|
@ -94,6 +81,35 @@ const newList = async (columnId: number) => {
|
|||
|
||||
// 点赞
|
||||
const handleClickLike = async () => {
|
||||
console.log("🚀 ~ handleClickLike ~ data.value.isLike:", data.value.isLike);
|
||||
if (data.value.isLike == 1) {
|
||||
// 取消点赞
|
||||
aplus_queue.push({
|
||||
action: "aplus.record",
|
||||
arguments: [
|
||||
"canncelLike",
|
||||
"CLK",
|
||||
{
|
||||
param1: data.value.id,
|
||||
param2: data.value.title,
|
||||
},
|
||||
],
|
||||
});
|
||||
} else {
|
||||
// 点赞
|
||||
aplus_queue.push({
|
||||
action: "aplus.record",
|
||||
arguments: [
|
||||
"doLike",
|
||||
"CLK",
|
||||
{
|
||||
param1: data.value.id,
|
||||
param2: data.value.title,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// console.log("=== 点赞 ===")
|
||||
const res = await fetchArticleLike({
|
||||
id: data.value.id,
|
||||
|
|
@ -128,7 +144,7 @@ const wxShare = () => {
|
|||
JSON.stringify({
|
||||
id: data.value.id,
|
||||
type: newType.value,
|
||||
})
|
||||
}),
|
||||
);
|
||||
link += `?path=${path}&query=${query}`;
|
||||
// console.log("🚀 ~ WXconfig ~ link:", link);
|
||||
|
|
@ -175,6 +191,8 @@ const jumpAll = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const { aplus_queue } = window;
|
||||
|
||||
// 跳转详情
|
||||
const jumpDetail = (item: any) => {
|
||||
// console.log(item)
|
||||
|
|
@ -182,10 +200,72 @@ const jumpDetail = (item: any) => {
|
|||
url: `/pages/detail/index?id=${item.id}`,
|
||||
});
|
||||
};
|
||||
|
||||
// 新闻id
|
||||
const news_id = ref("");
|
||||
// 获取更多拓展阅读
|
||||
const getFurtherReadData = () => {
|
||||
getDetailFurtherReadData(news_id.value).then((res: any) => {
|
||||
if (res.data.length > 0) {
|
||||
furtherReadData.value = res.data;
|
||||
} else {
|
||||
furtherReadData.value = [...furtherReadData.value, ...res.data];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 判断区分入口是h5和其他,h5入口需要判断账号是否【正式|试用】
|
||||
const access = ref("");
|
||||
|
||||
onLoad(async (option: any) => {
|
||||
// 判断区分入口是h5和其他,h5入口需要判断账号是否【正式|试用】
|
||||
access.value = option.access || '';
|
||||
|
||||
news_id.value = option.id;
|
||||
aplus_queue.push({
|
||||
action: "aplus.sendPV",
|
||||
arguments: [{ is_auto: false }], // 此处上报的数据暂时在后台没有展示
|
||||
});
|
||||
//一个简单的demo
|
||||
aplus_queue.push({
|
||||
action: "aplus.record",
|
||||
arguments: [
|
||||
"goDetail",
|
||||
"CLK",
|
||||
{
|
||||
id: data.value.id,
|
||||
title: data.value.title,
|
||||
},
|
||||
],
|
||||
});
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
});
|
||||
newType.value = option.type || 14;
|
||||
const res = await fetchArticleDetail({
|
||||
id: option.id,
|
||||
});
|
||||
|
||||
if (res.code === 200) {
|
||||
data.value = res.data;
|
||||
|
||||
res.data.content = res.data.content.replace(/\n{3,}/g, "\n");
|
||||
|
||||
columnName.value = res.data.columnName1;
|
||||
|
||||
furtherReadData.value = res.data.furtherReadings || [];
|
||||
|
||||
newList(res.data.columnId1);
|
||||
wxShare();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
min-height: 100vh;
|
||||
|
||||
.line {
|
||||
|
|
@ -232,7 +312,7 @@ const jumpDetail = (item: any) => {
|
|||
|
||||
.container {
|
||||
// background-color: #f5f5f5;
|
||||
padding-bottom: 112rpx;
|
||||
box-sizing: border-box;
|
||||
// padding-bottom: 112rpx;
|
||||
// box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,483 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 导航栏 start -->
|
||||
<view class="custom-bav-bar">
|
||||
<view class="left">
|
||||
<u-icon name="arrow-left" color="#fff" size="36rpx" @click="handleBack" />
|
||||
</view>
|
||||
<view class="center"> 海外先机 </view>
|
||||
</view>
|
||||
<!-- 导航栏 end -->
|
||||
|
||||
<!-- 标题 start -->
|
||||
<view class="page-title">
|
||||
<view class="hide">挖掘核心投资资产 提供决策先手信息</view>
|
||||
<view class="desc">24小时全球市场实时独家监控</view>
|
||||
</view>
|
||||
<!-- 标题 end -->
|
||||
|
||||
<view :class="['page-main']">
|
||||
<!-- 搜索 start -->
|
||||
<view class="page-search">
|
||||
<u-input
|
||||
v-model="keyword"
|
||||
type="text"
|
||||
placeholder="搜索资讯"
|
||||
prefixIcon="search"
|
||||
fontSize="28rpx"
|
||||
prefixIconStyle="font-size: 40rpx;color: #BDC1C7;"
|
||||
:customStyle="{
|
||||
borderRadius: '36rpx',
|
||||
background: '#F3F5F8',
|
||||
}"
|
||||
@confirm="handleSearch"
|
||||
/>
|
||||
</view>
|
||||
<view :class="['timeline', { mask: isMask }]" v-for="item in data" :key="item.day">
|
||||
<view class="line"></view>
|
||||
<view class="content">
|
||||
<view class="date">{{ item.day }}</view>
|
||||
<view class="news-list">
|
||||
<view
|
||||
class="news"
|
||||
v-for="news in item.list"
|
||||
:key="news.id"
|
||||
@click="goDetail(news)"
|
||||
>
|
||||
<view class="news-top">
|
||||
<view class="time">{{ news.timeStr }}</view>
|
||||
<view class="source">
|
||||
<view class="t-1">来自</view>
|
||||
<view class="t-2">中国证券报</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="news-title">
|
||||
<view class="icon-hot"></view>
|
||||
<view class="name">
|
||||
<text class="text">{{ news.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="news-content">
|
||||
{{ news.summary }}
|
||||
</view>
|
||||
<view class="tags">
|
||||
<text class="tag">{{ news.companyName }}</text>
|
||||
</view>
|
||||
<view class="stocks" v-if="news.stocks?.length > 0">
|
||||
<template v-for="(stock, index) in news.stocks" :key="index">
|
||||
<view class="stock" v-if="index < 2">
|
||||
<text class="name">{{ stock.name }}</text>
|
||||
<text class="code">{{ stock.code }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-loading-icon
|
||||
v-if="!isBottom && loading"
|
||||
mode="circle"
|
||||
text="加载中..."
|
||||
textSize="26rpx"
|
||||
textColor="#999999"
|
||||
color="rgba(23, 119, 255, 1)"
|
||||
size="28rpx"
|
||||
></u-loading-icon>
|
||||
</view>
|
||||
|
||||
<!-- 登录弹窗 start -->
|
||||
<LoginDialog
|
||||
:show="LoginShow"
|
||||
@onSuccess="handleLoginSuccess"
|
||||
@onCancel="handleLoginCancel"
|
||||
@onError="handleLoginError"
|
||||
/>
|
||||
<!-- 登录弹窗 end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getForeignList } from "@/api";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import LoginDialog from "@/pages/realtimeInfo/components/LoginPopup/index.vue";
|
||||
import { onReachBottom } from "@dcloudio/uni-app";
|
||||
|
||||
// 导航栏路由返回
|
||||
const handleBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 未登录|试用,显示蒙层
|
||||
const isMask = computed(() => {
|
||||
return !userStore.isLogin || !userStore.isUserType;
|
||||
});
|
||||
|
||||
const LoginShow = ref(false);
|
||||
// 显示弹框
|
||||
const handleShowLogin = () => {
|
||||
LoginShow.value = true;
|
||||
};
|
||||
|
||||
// 关闭弹框
|
||||
const handleLoginCancel = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录成功之后的回调
|
||||
const handleLoginSuccess = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录失败之后的回调
|
||||
const handleLoginError = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
}
|
||||
|
||||
const data = ref([]);
|
||||
const loading = ref(false);
|
||||
const keyword = ref("");
|
||||
const isBottom = ref(false);
|
||||
const pages = reactive({
|
||||
page: 1,
|
||||
size: 20,
|
||||
total: 0,
|
||||
});
|
||||
const getList = async () => {
|
||||
const result = await getForeignList({
|
||||
keyword: keyword.value,
|
||||
page: pages.page,
|
||||
size: pages.size,
|
||||
});
|
||||
if (result.code === 200) {
|
||||
const { list, total } = result.data;
|
||||
data.value = [...data.value, ...list];
|
||||
pages.total = Math.ceil(total / pages.size);
|
||||
isBottom.value = pages.page >= pages.total;
|
||||
} else {
|
||||
data.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
getList();
|
||||
};
|
||||
|
||||
onReachBottom(() => {
|
||||
if (isBottom.value) return;
|
||||
pages.page++;
|
||||
getList();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
}
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
width: 100%;
|
||||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
background-image: url("@/assets/images/page/page_1@2x.png");
|
||||
background-size: 100% auto;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.custom-bav-bar {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.back_icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.logo_icon {
|
||||
width: 168rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #ffffff;
|
||||
line-height: 36rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.page-title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 202rpx;
|
||||
margin-bottom: 54rpx;
|
||||
|
||||
.desc {
|
||||
padding-left: 40rpx;
|
||||
background: url("@/assets/images/page/icon_select@2x.png") no-repeat 0 center;
|
||||
background-size: 28rpx 28rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.page-main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 400rpx);
|
||||
padding: 30rpx 30rpx 0;
|
||||
background: #f3f5f8;
|
||||
border-radius: 24rpx 24rpx 0px 0px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 140rpx;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f3f5f8 100%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.page-search {
|
||||
position: relative;
|
||||
margin-bottom: 39rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.page-main {
|
||||
.timeline {
|
||||
display: flex;
|
||||
&.mask {
|
||||
filter: blur(5px);
|
||||
}
|
||||
.line {
|
||||
position: relative;
|
||||
top: 12rpx;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 2rpx;
|
||||
height: 100%;
|
||||
background: #d9d7d7;
|
||||
transform: translateX(-1rpx);
|
||||
z-index: 1;
|
||||
}
|
||||
&::before {
|
||||
position: relative;
|
||||
content: "";
|
||||
display: block;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: url("@/assets/images/page/icon_cicle@2x.png") no-repeat;
|
||||
background-size: 20rpx 20rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 0 30rpx 15rpx;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.news-list {
|
||||
margin-top: 30rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
|
||||
.news {
|
||||
padding: 25rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.news-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.time {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.source {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.t-1 {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #222222;
|
||||
line-height: 33rpx;
|
||||
margin-right: 4rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.t-2 {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #222222;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.news-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
.icon-hot {
|
||||
// flex: 1;
|
||||
width: 63rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
background: url("@/assets/images/page/only_icon@2x.png") no-repeat;
|
||||
background-size: 63rpx 32rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
position: relative;
|
||||
height: 32rpx;
|
||||
.text {
|
||||
position: relative;
|
||||
max-width: 520rpx;
|
||||
display: block;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
line-height: 32rpx;
|
||||
color: #222222;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.news-content {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 44rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
margin-bottom: 20rpx;
|
||||
.tag {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #5978b2;
|
||||
line-height: 44rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
.stocks {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
.stock {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #edf1f5;
|
||||
border-radius: 25rpx;
|
||||
padding: 0 18rpx;
|
||||
|
||||
.name {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
.code {
|
||||
margin-left: 20rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,451 @@
|
|||
<template>
|
||||
<view class="custom-container" @click.stop>
|
||||
<!-- 导航栏 start -->
|
||||
<view class="custom-bav-bar">
|
||||
<view class="left">
|
||||
<u-icon name="arrow-left" color="#666" size="36rpx" @click="handleBack" />
|
||||
</view>
|
||||
<view class="center"> 添加关注申万行业 </view>
|
||||
</view>
|
||||
<!-- 导航栏 end -->
|
||||
|
||||
<!-- 搜搜 start -->
|
||||
<view class="page-search">
|
||||
<u-input
|
||||
v-model="input"
|
||||
type="text"
|
||||
placeholder="输入行业查找"
|
||||
prefixIcon="search"
|
||||
fontSize="28rpx"
|
||||
prefixIconStyle="font-size: 40rpx;color: #BDC1C7;"
|
||||
:customStyle="{
|
||||
borderRadius: '36rpx',
|
||||
background: '#F3F5F8',
|
||||
}"
|
||||
clearable
|
||||
@confirm="handleSearchTag"
|
||||
/>
|
||||
</view>
|
||||
<!-- 搜搜 end -->
|
||||
|
||||
<view class="custom-main">
|
||||
<view class="my-industry">
|
||||
<view class="my-industry-top">
|
||||
<view class="label">我的行业</view>
|
||||
<view class="label-count">
|
||||
<text>已选</text>
|
||||
<text class="color">{{ myTagList.length }}</text>
|
||||
<text>/10</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="my-industry-list" v-if="myTagList.length > 0">
|
||||
<view class="industry-item" v-for="(item, index) in myTagList">
|
||||
<view class="industry-name">{{ item.name.split("-")[1] }}</view>
|
||||
<view class="industry-btn" @click="handleDeleteTag(index)"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="my-industry-empty" v-else> 暂无自选,请从下方添加 </view>
|
||||
</view>
|
||||
<view class="recommend-industry">
|
||||
<view class="recommend-industry-top">
|
||||
<view class="label">推荐行业</view>
|
||||
<view class="right" @click="handleChange">
|
||||
<view class="icon"></view>
|
||||
<view class="text">换一换</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="recommend-industry-list" v-if="industryList.length > 0">
|
||||
<view
|
||||
v-for="(item, index) in industryList"
|
||||
:key="index"
|
||||
:class="['industry-item', { active: isSelected(item.content) }]"
|
||||
@click="handleAddTag(item.content)"
|
||||
>
|
||||
<view class="industry-name">{{ item.content.split("-")[1] }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="no-data"> <u-empty /></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="custom-footer">
|
||||
<view class="btn-clear" @click="handleClear">清空</view>
|
||||
<view class="btn-done" @click="handleComplete">完成配置</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getTopIndustryPeriod } from "@/api/newsInfo";
|
||||
import dayjs from "dayjs";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
tagList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
allTagList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["onChange", "onBack"]);
|
||||
|
||||
const input = ref("");
|
||||
|
||||
// 导航栏路由返回
|
||||
const handleBack = () => {
|
||||
if (props.tagList.length === 0) {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
} else {
|
||||
emit("onBack");
|
||||
}
|
||||
};
|
||||
|
||||
const myTagList = ref([]);
|
||||
const industryList = ref([]);
|
||||
const page = ref(0)
|
||||
|
||||
const getTagList = () => {
|
||||
return [...props.allTagList].splice(page.value, 10);
|
||||
};
|
||||
|
||||
const handleChange = () => {
|
||||
page.value = page.value ? 0 : 10;
|
||||
industryList.value = getTagList();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.allTagList,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
industryList.value = getTagList();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
// 是否选中
|
||||
function isSelected(tag) {
|
||||
const index = myTagList.value.findIndex((item) => item.name === tag);
|
||||
return index === -1 ? false : true;
|
||||
}
|
||||
// 添加标签
|
||||
function handleAddTag(tag) {
|
||||
if (isSelected(tag)) return;
|
||||
if (myTagList.value.length >= 10) {
|
||||
uni.showToast({
|
||||
title: "最多添加10个标签",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
myTagList.value.push({
|
||||
name: tag,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除标签
|
||||
function handleDeleteTag(index: number) {
|
||||
myTagList.value.splice(index, 1);
|
||||
}
|
||||
|
||||
// 搜索标签
|
||||
function handleSearchTag() {
|
||||
if (!input.value) {
|
||||
return;
|
||||
}
|
||||
industryList.value = props.allTagList.filter((item) => {
|
||||
if (!item || !item.content) return false;
|
||||
|
||||
return item.content.includes(input.value);
|
||||
});
|
||||
}
|
||||
|
||||
// 完成配置
|
||||
function handleComplete() {
|
||||
if (myTagList.value.length < 1) {
|
||||
uni.showToast({
|
||||
title: "请先选择标签",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
emit("onChange", myTagList.value);
|
||||
}
|
||||
// 清除
|
||||
function handleClear() {
|
||||
myTagList.value = [];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.tagList,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
myTagList.value = [...newVal];
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-container {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
z-index: 9;
|
||||
padding-bottom: 80rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.custom-bav-bar {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.back_icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.logo_icon {
|
||||
width: 168rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #222222;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-search {
|
||||
position: relative;
|
||||
margin-top: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 0 30rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.custom-main {
|
||||
width: 100%;
|
||||
height: calc(100% - 250rpx);
|
||||
padding: 33rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
|
||||
.my-industry {
|
||||
margin-bottom: 80rpx;
|
||||
.my-industry-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
.label {
|
||||
margin-right: 13rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #111111;
|
||||
}
|
||||
|
||||
.label-count {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
.color {
|
||||
color: #3f80fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-industry-list {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.industry-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 18rpx 30rpx;
|
||||
background: #eff7ff;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.industry-name {
|
||||
margin-right: 20rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #3f80fa;
|
||||
}
|
||||
.industry-btn {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: url("@/assets/images/page/icon_close@2x.png") no-repeat;
|
||||
background-size: 20rpx 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-industry-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100rpx;
|
||||
background: #f7f8fa;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #e4e9f0;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #cccccc;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend-industry {
|
||||
.recommend-industry-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.label {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #111111;
|
||||
}
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: url("@/assets/images/page/icon_change@2x.png") no-repeat 0 3rpx;
|
||||
background-size: 32rpx 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.text {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recommend-industry-list {
|
||||
display: grid;
|
||||
gap: 20rpx;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
||||
.industry-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 18rpx 0;
|
||||
background-color: #f3f5f8;
|
||||
border-radius: 8px;
|
||||
|
||||
&.active {
|
||||
background-image: url("@/assets/images/page/chose_icon@2x.png");
|
||||
background-position: right bottom;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 38rpx 31rpx;
|
||||
}
|
||||
|
||||
.industry-name {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-data {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16rpx 24rpx;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px -4px 12px 0px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
|
||||
.btn-clear {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 239rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
background: #fff;
|
||||
border: 2rpx solid #979797;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #656565;
|
||||
line-height: 45rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-done {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 437rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
background: #3f80fa;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
line-height: 45rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 导航栏 start -->
|
||||
<view class="custom-bav-bar">
|
||||
<view class="left">
|
||||
<u-icon name="arrow-left" color="#666" size="36rpx" @click="handleBack" />
|
||||
</view>
|
||||
<view class="center"> 热门行业 </view>
|
||||
<view class="right" v-if="userStore.isLogin" @click="handleShowCustom">管理</view>
|
||||
</view>
|
||||
<!-- 导航栏 end -->
|
||||
|
||||
<!-- tabs start -->
|
||||
<view class="page-nav-tabs">
|
||||
<u-tabs
|
||||
:list="tagList"
|
||||
lineWidth="28rpx"
|
||||
lineColor="#222222"
|
||||
:current="current"
|
||||
:activeStyle="{
|
||||
color: '#222',
|
||||
fontWeight: '500',
|
||||
fontFamily: 'PingFangSC, PingFang SC',
|
||||
}"
|
||||
:inactiveStyle="{
|
||||
color: '#666',
|
||||
fontWeight: '400',
|
||||
fontFamily: 'PingFangSC, PingFang SC',
|
||||
}"
|
||||
itemStyle="padding-left: 15px; padding-right: 15px; height: 70rpx;"
|
||||
keyName="content"
|
||||
@change="handleChangeTag"
|
||||
>
|
||||
</u-tabs>
|
||||
</view>
|
||||
<!-- tabs end -->
|
||||
|
||||
<view class="page-main">
|
||||
<view class="banner">
|
||||
<view class="text-1">{{ tagList[current]?.content }}</view>
|
||||
<view class="text-2" v-if="tagList[current]?.index">热门行业近一个月排名{{ tagList[current]?.index }}</view>
|
||||
</view>
|
||||
|
||||
<view class="news-list">
|
||||
<u-loading-icon v-if="loading"></u-loading-icon>
|
||||
<template v-else-if="data?.length > 0">
|
||||
<view
|
||||
:class="['news-item', { mask: !userStore.isLogin }]"
|
||||
v-for="item in data"
|
||||
:key="item.id"
|
||||
@click="goDetail(item)"
|
||||
>
|
||||
<view class="title">
|
||||
<view class="name">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['content', { mask: isMask }]">
|
||||
{{ item.summary }}
|
||||
</view>
|
||||
<view :class="['source', { mask: isMask }]">
|
||||
<view>{{ item.tag }}</view>
|
||||
<view>{{ item.time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<u-empty v-else />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { getListByTagIndustry } from "@/api/detail";
|
||||
|
||||
const props = defineProps({
|
||||
tagList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["onShow", "onShowCustom"]);
|
||||
|
||||
const loading = ref(false);
|
||||
const activeTag = ref("");
|
||||
const current = computed(() => {
|
||||
return props.tagList.findIndex((item) => item.name === activeTag.value);
|
||||
});
|
||||
|
||||
const handleChangeTag = (item: any) => {
|
||||
activeTag.value = item.name;
|
||||
getList(item.name);
|
||||
};
|
||||
|
||||
// 导航栏路由返回
|
||||
const handleBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 未登录|试用,显示蒙层
|
||||
const isMask = computed(() => {
|
||||
return !userStore.isUserType;
|
||||
});
|
||||
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
}
|
||||
|
||||
// 数据列表
|
||||
const data = ref([]);
|
||||
// 新闻列表
|
||||
const getList = async (name: string) => {
|
||||
loading.value = true;
|
||||
const result = await getListByTagIndustry({ name });
|
||||
loading.value = false;
|
||||
if (result.code === 200) {
|
||||
data.value = result.data;
|
||||
} else {
|
||||
data.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.tagList,
|
||||
(newVal) => {
|
||||
if (newVal?.length > 0) {
|
||||
activeTag.value = newVal[0]?.name || "";
|
||||
getList(activeTag.value);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
const handleShowCustom = () => {
|
||||
emit("onShowCustom");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.custom-bav-bar {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.back_icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.logo_icon {
|
||||
width: 168rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #222222;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: absolute;
|
||||
top: 22rpx;
|
||||
right: 30rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-nav-tabs {
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.page-main {
|
||||
padding-top: 30rpx;
|
||||
background-color: #f3f5f8;
|
||||
|
||||
.banner {
|
||||
width: 690rpx;
|
||||
height: 113rpx;
|
||||
margin: 0 30rpx 30rpx;
|
||||
padding: 15rpx 30rpx;
|
||||
border-radius: 10rpx;
|
||||
background-image: url("@/assets/images/page/page_5@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 690rpx 113rpx;
|
||||
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.12);
|
||||
box-sizing: border-box;
|
||||
|
||||
.text-1 {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #3f80fa;
|
||||
line-height: 42rpx;
|
||||
}
|
||||
.text-2 {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.news-list {
|
||||
width: 100%;
|
||||
padding: 30rpx 30rpx 0;
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0px 0px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
.mask {
|
||||
filter: blur(5px);
|
||||
}
|
||||
|
||||
.news-item {
|
||||
width: 100%;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 2rpx solid #f3f3f5;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
width: 564rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
margin-bottom: 16rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
|
||||
.source {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 自定义配置 start -->
|
||||
<CustomView
|
||||
v-if="isShowCustom && userStore.isLogin"
|
||||
:tagList="tagList"
|
||||
:allTagList="allTagList"
|
||||
@onChange="handleChangeTag"
|
||||
@onBack="handleHideCustom"
|
||||
/>
|
||||
<!-- 自定义配置 end -->
|
||||
|
||||
<List
|
||||
v-show="!isShowCustom"
|
||||
:tagList="tagList"
|
||||
@onShow="handleShowLogin"
|
||||
@onShowCustom="handleShowCustom"
|
||||
/>
|
||||
|
||||
<!-- 登录弹窗 start -->
|
||||
<LoginDialog
|
||||
:show="LoginShow"
|
||||
@onSuccess="handleLoginSuccess"
|
||||
@onCancel="handleLoginCancel"
|
||||
@onError="handleLoginError"
|
||||
/>
|
||||
<!-- 登录弹窗 end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import LoginDialog from "@/pages/realtimeInfo/components/LoginPopup/index.vue";
|
||||
import CustomView from "./components/CustomView.vue";
|
||||
import List from "./components/List.vue";
|
||||
import { getMyIndustries, updateMyIndustries } from "@/api";
|
||||
import { getTopIndustryPeriod } from "@/api/newsInfo";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const allTagList = ref([]);
|
||||
const start_time = dayjs().subtract(1, "month").format("YYYY-MM-DD");
|
||||
const end_time = dayjs().format("YYYY-MM-DD");
|
||||
const limit_num = 20;
|
||||
// 热门行业top10
|
||||
async function getTopIndustry_dFn() {
|
||||
allTagList.value = await getTopIndustryPeriod({
|
||||
start_time: start_time,
|
||||
end_time: end_time,
|
||||
limit_num: limit_num,
|
||||
});
|
||||
}
|
||||
|
||||
const isShowCustom = ref(false);
|
||||
|
||||
const handleChangeTag = async (item: any) => {
|
||||
const params = item.map((tag: any) => {
|
||||
const _tag = tag.name.split("-");
|
||||
return {
|
||||
primaryName: _tag[0],
|
||||
secondaryName: _tag[1],
|
||||
};
|
||||
});
|
||||
const result = await updateMyIndustries(params);
|
||||
if (result.code === 200) {
|
||||
getTagList();
|
||||
handleHideCustom();
|
||||
}
|
||||
};
|
||||
|
||||
const handleShowCustom = () => {
|
||||
isShowCustom.value = true;
|
||||
};
|
||||
const handleHideCustom = () => {
|
||||
isShowCustom.value = false;
|
||||
};
|
||||
|
||||
const tagList = ref([]);
|
||||
|
||||
const getTagList = async () => {
|
||||
const result = await getMyIndustries({});
|
||||
if (result.code === 200) {
|
||||
tagList.value = result.data.map((item: any) => {
|
||||
const name = item.primaryName + "-" + item.secondaryName;
|
||||
const content = item.secondaryName;
|
||||
const index = allTagList.value.findIndex((tag: any) => tag.content === name);
|
||||
return {
|
||||
name,
|
||||
content,
|
||||
index: index + 1,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
tagList.value = [];
|
||||
}
|
||||
|
||||
if (tagList.value.length === 0) {
|
||||
handleShowCustom();
|
||||
}
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
const LoginShow = ref(false);
|
||||
// 显示弹框
|
||||
const handleShowLogin = () => {
|
||||
LoginShow.value = true;
|
||||
};
|
||||
|
||||
// 关闭弹框
|
||||
const handleLoginCancel = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录成功之后的回调
|
||||
const handleLoginSuccess = () => {
|
||||
LoginShow.value = false;
|
||||
getTagList();
|
||||
};
|
||||
// 登录失败之后的回调
|
||||
const handleLoginError = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
return;
|
||||
}
|
||||
await getTopIndustry_dFn();
|
||||
await getTagList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 导航栏 start -->
|
||||
<view class="custom-bav-bar">
|
||||
<view class="left">
|
||||
<u-icon name="arrow-left" color="#666" size="36rpx" @click="handleBack" />
|
||||
</view>
|
||||
<view class="center"> 宏观知微 </view>
|
||||
</view>
|
||||
<!-- 导航栏 end -->
|
||||
|
||||
<!-- 标题 start -->
|
||||
<view class="page-title">
|
||||
<view class="hide">挖掘核心投资资产 提供决策先手信息</view>
|
||||
</view>
|
||||
<!-- 标题 end -->
|
||||
|
||||
<view class="page-main">
|
||||
<view class="news-list" v-if="data?.length > 0">
|
||||
<template v-for="(item, index) in data" :key="index">
|
||||
<view
|
||||
:class="['news-item', { mask: !userStore.isLogin }]"
|
||||
v-for="news in item.list"
|
||||
:key="news.id"
|
||||
@click="goDetail(news)"
|
||||
>
|
||||
<view class="title">
|
||||
<view class="icon">宏观</view>
|
||||
<view class="name">
|
||||
{{ news.title }}
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['content', { mask: isMask }]">
|
||||
{{ news.summary }}
|
||||
</view>
|
||||
<view :class="['source', { mask: isMask }]">
|
||||
<view>中国证券报</view>
|
||||
<view>{{ `${item.day} ${news.timeStr}` }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<u-empty v-else />
|
||||
<u-loading-icon
|
||||
v-if="!isBottom && loading"
|
||||
mode="circle"
|
||||
text="加载中..."
|
||||
textSize="26rpx"
|
||||
textColor="#999999"
|
||||
color="rgba(23, 119, 255, 1)"
|
||||
size="28rpx"
|
||||
></u-loading-icon>
|
||||
</view>
|
||||
<!-- 登录弹窗 start -->
|
||||
<LoginDialog
|
||||
:show="LoginShow"
|
||||
@onSuccess="handleLoginSuccess"
|
||||
@onCancel="handleLoginCancel"
|
||||
@onError="handleLoginError"
|
||||
/>
|
||||
<!-- 登录弹窗 end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getMacroList } from "@/api";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import LoginDialog from "@/pages/realtimeInfo/components/LoginPopup/index.vue";
|
||||
import { onReachBottom } from "@dcloudio/uni-app";
|
||||
// 导航栏路由返回
|
||||
const handleBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
};
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 未登录|试用,显示蒙层
|
||||
const isMask = computed(() => {
|
||||
return !userStore.isUserType;
|
||||
});
|
||||
|
||||
const LoginShow = ref(false);
|
||||
// 显示弹框
|
||||
const handleShowLogin = () => {
|
||||
LoginShow.value = true;
|
||||
};
|
||||
|
||||
// 关闭弹框
|
||||
const handleLoginCancel = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录成功之后的回调
|
||||
const handleLoginSuccess = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
// 登录失败之后的回调
|
||||
const handleLoginError = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
}
|
||||
|
||||
const data = ref([]);
|
||||
const loading = ref(false);
|
||||
const keyword = ref("");
|
||||
const isBottom = ref(false);
|
||||
const pages = reactive({
|
||||
page: 1,
|
||||
size: 20,
|
||||
total: 0,
|
||||
});
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const result = await getMacroList({
|
||||
keyword: keyword.value,
|
||||
page: pages.page,
|
||||
size: pages.size,
|
||||
});
|
||||
loading.value = false;
|
||||
if (result.code === 200) {
|
||||
const { list, total } = result.data;
|
||||
data.value = [...data.value, ...list];
|
||||
pages.total = Math.ceil(total / pages.size);
|
||||
isBottom.value = pages.page >= pages.total;
|
||||
} else {
|
||||
data.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
onReachBottom(() => {
|
||||
if (isBottom.value) return;
|
||||
pages.page++;
|
||||
getList();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
}
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-container {
|
||||
width: 100%;
|
||||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
background-image: url("@/assets/images/page/page_3@2x.png");
|
||||
background-size: 100% auto;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.custom-bav-bar {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.back_icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.logo_icon {
|
||||
width: 168rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 32rpx;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #222222;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 202rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.page-main {
|
||||
width: 100%;
|
||||
padding: 30rpx 30rpx 0;
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0px 0px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
.mask {
|
||||
filter: blur(5px);
|
||||
}
|
||||
|
||||
.news-item {
|
||||
width: 100%;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 2rpx solid #f3f3f5;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
.icon {
|
||||
padding: 2rpx 8rpx 7rpx;
|
||||
font-family: "AlimamaShuHeiTi, AlimamaShuHeiTi";
|
||||
font-weight: bold;
|
||||
font-size: 24rpx;
|
||||
color: #fffdf9;
|
||||
line-height: 34rpx;
|
||||
background: #ff9d2f;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
width: 564rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
margin-bottom: 16rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
|
||||
.source {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<template>
|
||||
<view class="news-section">
|
||||
<swiper
|
||||
class="news-section-swiper"
|
||||
circular
|
||||
:indicator-dots="true"
|
||||
:autoplay="true"
|
||||
:interval="3000"
|
||||
:duration="500"
|
||||
indicator-color="rgba(199, 199, 199, 1)"
|
||||
indicator-active-color="#3F80FA"
|
||||
>
|
||||
<swiper-item v-for="(item, index) in data" :key="index">
|
||||
<view class="swiper-item" @click.stop="goDetail(item)">
|
||||
<view class="source">
|
||||
<view>
|
||||
<text class="label">来自</text>
|
||||
<text class="name">中国证券报</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>{{ item.timeStr }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="title">{{ item.title }}</view>
|
||||
<view class="content">{{ item.summary }}</view>
|
||||
<view class="tag">
|
||||
<text class="txt">{{ item.companyName }}</text>
|
||||
<!-- <text class="txt">#三星生物制药</text> -->
|
||||
</view>
|
||||
<view class="industry" v-if="item?.stocks && item?.stocks.length > 0">
|
||||
<text class="txt" v-for="stock in item?.stocks">{{
|
||||
maskStockNameProportional(stock?.name)
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getForeignList } from "@/api";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { maskStockNameProportional } from "@/utils/util";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
const emit = defineEmits(["onShow"]);
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (userStore.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
} else {
|
||||
emit("onShow");
|
||||
}
|
||||
}
|
||||
|
||||
const data = ref([]);
|
||||
const getList = async () => {
|
||||
const result = await getForeignList({});
|
||||
if (result.code === 200) {
|
||||
const { list, total } = result.data;
|
||||
for (const item of list) {
|
||||
for (const o of item.list) {
|
||||
data.value.push(o);
|
||||
if (data.value.length >= 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data.value.length >= 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.news-section {
|
||||
width: 710rpx;
|
||||
height: 522rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
padding: 87rpx 54rpx 0 24rpx;
|
||||
background-image: url("@/assets/images/page/banner-2@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
box-sizing: border-box;
|
||||
|
||||
.news-section-swiper {
|
||||
width: 100%;
|
||||
height: 435rpx;
|
||||
|
||||
:deep(.uni-swiper-dot) {
|
||||
width: 11rpx;
|
||||
height: 6rpx;
|
||||
background: #c7c7c7;
|
||||
border-radius: 8px;
|
||||
margin-right: 8rpx;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
:deep(.uni-swiper-dot-active) {
|
||||
width: 40rpx;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.source {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
line-height: 33rpx;
|
||||
|
||||
.label {
|
||||
margin-right: 2rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.name {
|
||||
color: #333333;
|
||||
}
|
||||
.time {
|
||||
color: #666664;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
margin-bottom: 10rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #222222;
|
||||
line-height: 42rpx;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.content {
|
||||
margin-bottom: 14rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666664;
|
||||
line-height: 33rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
}
|
||||
.tag {
|
||||
display: flex;
|
||||
margin-bottom: 22rpx;
|
||||
.txt {
|
||||
margin-right: 16rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #d6a68c;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
.industry {
|
||||
display: flex;
|
||||
.txt {
|
||||
padding: 8rpx 12rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
margin-right: 16rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #5c5c5b;
|
||||
line-height: 33rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
<template>
|
||||
<view class="hot-section">
|
||||
<view class="hot-top" @click="navigateTo">
|
||||
<view class="title">风口概念</view>
|
||||
<view class="time">近一个月热门</view>
|
||||
</view>
|
||||
<view class="tag-box">
|
||||
<!-- <view v-for="(item, index) in topConceptList" :key="index" class="tag">
|
||||
{{ item.content?.split("-")[1] }}
|
||||
</view> -->
|
||||
<view class="tag-box">
|
||||
<view
|
||||
v-for="(item, index) in topConceptList"
|
||||
:class="['tag', { 'tag-active': active === index }]"
|
||||
@click="handleClickTag(index, item)"
|
||||
>
|
||||
{{ item.content?.split("-")[1] }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tag-content">
|
||||
<view class="content" @click="goDetail(oneData)">{{ oneData?.title }} </view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getHotByTag } from "@/api";
|
||||
import { getTopConceptPeriod } from "@/api/newsInfo";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import dayjs from "dayjs";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
|
||||
const emit = defineEmits(["onShow"]);
|
||||
const active = ref(0);
|
||||
const topConceptList = ref([]);
|
||||
const oneData = ref({});
|
||||
const userStore = useUserStore();
|
||||
const start_time = dayjs().subtract(1, "month").format("YYYY-MM-DD");
|
||||
const end_time = dayjs().format("YYYY-MM-DD");
|
||||
const limit_num = 4;
|
||||
|
||||
const handleClickTag = (index: number, item: any) => {
|
||||
active.value = index;
|
||||
getList();
|
||||
};
|
||||
// 热门行业top10
|
||||
async function getTopConcept_dFn() {
|
||||
topConceptList.value = await getTopConceptPeriod({
|
||||
start_time: start_time,
|
||||
end_time: end_time,
|
||||
limit_num: limit_num,
|
||||
});
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
const name = topConceptList.value[active.value].content;
|
||||
// 概念标签
|
||||
let { code, data } = await getHotByTag({ name });
|
||||
if (code == 200) {
|
||||
oneData.value = data// && data.length > 0 ? data[0] : {};
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
if (!item.id) return;
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
}
|
||||
|
||||
// 跳转子页
|
||||
function navigateTo() {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
uni.showToast({
|
||||
title: "暂未开通本栏目",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/concept/index`,
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 热门行业top10
|
||||
await getTopConcept_dFn();
|
||||
await getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.hot-section {
|
||||
width: 710rpx;
|
||||
height: 257rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
padding: 30rpx 30rpx 0 30rpx;
|
||||
background-image: url("@/assets/images/page/5_pic@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hot-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.title {
|
||||
font-family: "AlimamaShuHeiTi, AlimamaShuHeiTi";
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
color: #111111;
|
||||
line-height: 45rpx;
|
||||
}
|
||||
.time {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.tag {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rpx 8rpx;
|
||||
border-radius: 4rpx;
|
||||
background-color: #fff;
|
||||
border: 2rpx solid #666;
|
||||
font-size: 22rpx;
|
||||
color: #666;
|
||||
line-height: 30rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.tag-active {
|
||||
border: 2rpx solid #bb875d;
|
||||
color: #bb875d;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -12rpx;
|
||||
left: 50%;
|
||||
border-left: 12rpx solid transparent;
|
||||
border-right: 12rpx solid transparent;
|
||||
border-top: 12rpx solid #bb875d;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: -10rpx;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-content {
|
||||
width: 100%;
|
||||
|
||||
.content {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #111111;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<view class="footer">
|
||||
<view class="logout" v-if="userStore.isLogin" @click="loginOut">退出登录</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { doLogout } from "@/api";
|
||||
import { Session } from "@/utils/storage";
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 退出登录
|
||||
function loginOut() {
|
||||
uni.showModal({
|
||||
title: "退出登录?",
|
||||
content: "",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
doLogout({
|
||||
financialAccount: userStore.getUserInfos().phone,
|
||||
});
|
||||
Session.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.footer {
|
||||
margin: 0 20rpx;
|
||||
padding: 20rpx 0;
|
||||
.logout {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 44rpx;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #666666;
|
||||
border: none;
|
||||
font-size: 32rpx;
|
||||
&::after {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<view class="header">
|
||||
<view class="banner">
|
||||
<text class="date"> 数据更新时间:{{ date }} </text>
|
||||
</view>
|
||||
<u-grid class="menu" :col="5" :border="false" align="center">
|
||||
<u-grid-item v-for="menu in menus" @click="goto(menu)">
|
||||
<image :src="menu.icon" class="menu-icon"></image>
|
||||
<text class="menu-text">{{ menu.label }}</text>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
import MENUICON1 from "@/assets/images/page/icon_1@2x.png";
|
||||
import MENUICON2 from "@/assets/images/page/icon_2@2x.png";
|
||||
import MENUICON3 from "@/assets/images/page/icon_3@2x.png";
|
||||
import MENUICON4 from "@/assets/images/page/icon_4@2x.png";
|
||||
import MENUICON5 from "@/assets/images/page/icon_5@2x.png";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const menus = reactive([
|
||||
{
|
||||
label: "海外先机",
|
||||
name: "hwxj",
|
||||
icon: MENUICON1,
|
||||
path: "/pages/foreign/index",
|
||||
},
|
||||
{
|
||||
label: "编辑精选",
|
||||
name: "bjjx",
|
||||
icon: MENUICON2,
|
||||
path: "/pages/recommend/index",
|
||||
},
|
||||
{
|
||||
label: "宏观知微",
|
||||
name: "hgzw",
|
||||
icon: MENUICON3,
|
||||
path: "/pages/macroscopic/index",
|
||||
},
|
||||
{
|
||||
label: "热门行业",
|
||||
name: "rthx",
|
||||
icon: MENUICON4,
|
||||
path: "/pages/industry/index",
|
||||
},
|
||||
{
|
||||
label: "风口概念",
|
||||
name: "fkgn",
|
||||
icon: MENUICON5,
|
||||
path: "/pages/concept/index",
|
||||
},
|
||||
]);
|
||||
const date = computed(() => dayjs().format("YYYY-MM-DD"));
|
||||
const userStore = useUserStore();
|
||||
const userInfos = computed(() => {
|
||||
return userStore.getUserInfos();
|
||||
});
|
||||
|
||||
const emit = defineEmits(["onShow"]);
|
||||
const goto = (menu: any) => {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
uni.showToast({
|
||||
title: "暂未开通本栏目",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const isAuth = userInfos.value?.auth?.findIndex((item) => item.name === menu.name);
|
||||
if (isAuth === -1 || userInfos.value?.auth[isAuth]?.enabled === 0) {
|
||||
uni.showToast({
|
||||
title: "暂未开通本栏目",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: menu.path,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.header {
|
||||
margin-bottom: 24rpx;
|
||||
background-color: #fbf9f6;
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
min-height: 334rpx;
|
||||
background-image: url("@/assets/images/page/banner_1@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
.date {
|
||||
position: absolute;
|
||||
top: 271rpx;
|
||||
left: 38rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #aa8e83;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 30rpx;
|
||||
background: linear-gradient(180deg, rgba(253, 250, 249, 0) 0%, #fbf9f6 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
height: 193rpx;
|
||||
padding: 30rpx 0;
|
||||
box-sizing: border-box;
|
||||
.menu-icon {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
.menu-text {
|
||||
margin-top: 12rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
<template>
|
||||
<view class="hot-section">
|
||||
<view class="hot-top" @click="navigateTo">
|
||||
<view class="title">热门行业</view>
|
||||
<view class="time">近一个月热门</view>
|
||||
</view>
|
||||
<view class="tag-box">
|
||||
<view
|
||||
v-for="(item, index) in industryList"
|
||||
:class="['tag', { 'tag-active': active === index }]"
|
||||
@click="handleClickTag(index, item)"
|
||||
>
|
||||
{{ item.content?.split("-")[1] }}
|
||||
</view
|
||||
>
|
||||
</view>
|
||||
<view class="tag-content" @click="goDetail(oneData)">
|
||||
<view class="title">
|
||||
<image class="icon-hot" src="@/assets/images/page/icon_hot@2x.png"></image>
|
||||
<view class="name">
|
||||
<text class="text">{{ oneData?.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content">
|
||||
{{ oneData?.summary }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getHotByTagIndustry } from "@/api";
|
||||
import { getTopIndustryPeriod } from "@/api/newsInfo";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import dayjs from "dayjs";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
const emit = defineEmits(["onShow"]);
|
||||
const active = ref(0);
|
||||
const industryList = ref([]);
|
||||
const oneData = ref({});
|
||||
const userStore = useUserStore();
|
||||
const start_time = dayjs().subtract(1, "month").format("YYYY-MM-DD");
|
||||
const end_time = dayjs().format("YYYY-MM-DD");
|
||||
const limit_num = 4;
|
||||
|
||||
const handleClickTag = (index: number, item: any) => {
|
||||
active.value = index;
|
||||
getList();
|
||||
};
|
||||
|
||||
// 热门行业top10
|
||||
async function getTopIndustry_dFn() {
|
||||
industryList.value = await getTopIndustryPeriod({
|
||||
start_time: start_time,
|
||||
end_time: end_time,
|
||||
limit_num: limit_num,
|
||||
});
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
const name = industryList.value[active.value].content;
|
||||
// 概念标签
|
||||
let { code, data } = await getHotByTagIndustry({ name });
|
||||
if (code == 200) {
|
||||
oneData.value = data// && data.length > 0 ? data[0] : {};
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转详情
|
||||
function goDetail(item: any) {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
if (!item.id) return;
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&access=h5`,
|
||||
});
|
||||
}
|
||||
|
||||
// 跳转子页
|
||||
function navigateTo() {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
|
||||
// 试用账号
|
||||
if (!userStore.isUserType) {
|
||||
uni.showToast({
|
||||
title: "暂未开通本栏目",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/industry/index`,
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 热门行业top10
|
||||
await getTopIndustry_dFn();
|
||||
await getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.hot-section {
|
||||
width: 710rpx;
|
||||
height: 482rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
padding: 40rpx 30rpx 0 30rpx;
|
||||
background-image: url("@/assets/images/page/4_pic@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hot-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 34rpx;
|
||||
|
||||
.title {
|
||||
font-family: "AlimamaShuHeiTi, AlimamaShuHeiTi";
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
color: #111111;
|
||||
line-height: 45rpx;
|
||||
}
|
||||
.time {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.tag {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid rgba(255, 255, 255, 0);
|
||||
border-radius: 8rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
line-height: 36rpx;
|
||||
padding: 0 10rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tag-active {
|
||||
background: #f3f5fc;
|
||||
border: 2rpx solid #4d71dc;
|
||||
color: #466feb;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -12rpx;
|
||||
left: 50%;
|
||||
border-left: 12rpx solid transparent;
|
||||
border-right: 12rpx solid transparent;
|
||||
border-top: 12rpx solid #4d71dc;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
bottom: -10rpx;
|
||||
border-top-color: #f3f5fc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-content {
|
||||
width: 100%;
|
||||
height: 185rpx;
|
||||
background: #fafbfc;
|
||||
border-radius: 16rpx;
|
||||
border: 2rpx solid #e7e9eb;
|
||||
background-image: url("@/assets/images/page/icon_symbol@2x.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 32rpx 23rpx;
|
||||
background-position: 10rpx 0;
|
||||
padding: 34rpx 30rpx 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
.icon-hot {
|
||||
// flex: 1;
|
||||
width: 79rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
position: relative;
|
||||
height: 40rpx;
|
||||
.text {
|
||||
position: relative;
|
||||
max-width: 500rpx;
|
||||
display: block;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
color: #111111;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 5rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 10rpx;
|
||||
background: #e0e7fc;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #343636;
|
||||
line-height: 33rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
<template>
|
||||
<u-popup
|
||||
class="loginPopup"
|
||||
:show="props.show"
|
||||
closeable
|
||||
:mode="props.mode"
|
||||
round="12"
|
||||
:closeOnClickOverlay="false"
|
||||
@close="handlePopupClose"
|
||||
>
|
||||
<view class="loginPopupContent">
|
||||
<view class="loginTitle">登录后掌握更多优质财经内容</view>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<view class="loginForm">
|
||||
<u--form :model="state.loginForm" ref="uForm">
|
||||
<u-form-item
|
||||
style="padding: 0"
|
||||
class="loginFormItem"
|
||||
prop="userInfo.name"
|
||||
borderBottom
|
||||
ref="item1"
|
||||
>
|
||||
<u--input
|
||||
class="loginFormInput"
|
||||
placeholder="请输入您的手机号"
|
||||
v-model="state.loginForm.phone"
|
||||
border="none"
|
||||
></u--input>
|
||||
</u-form-item>
|
||||
<u-form-item
|
||||
class="loginFormItem"
|
||||
prop="userInfo.name"
|
||||
borderBottom
|
||||
ref="item1"
|
||||
>
|
||||
<u--input
|
||||
class="loginFormInput"
|
||||
placeholder="请输入短信验证码"
|
||||
v-model="state.loginForm.code"
|
||||
border="none"
|
||||
></u--input>
|
||||
<view class="getCode" @click="captcha">{{ codeText }}</view>
|
||||
</u-form-item>
|
||||
</u--form>
|
||||
<u-button class="loginFormBtn" text="登录" @click="Login"></u-button>
|
||||
</view>
|
||||
<!-- 用户协议 -->
|
||||
<view class="tips"
|
||||
>登录即代表已经阅读并同意
|
||||
<view class="userAgreement">《用户协议》</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import { getCaptcha, login } from "@/api";
|
||||
import { validatePhoneNumber } from "@/utils/util";
|
||||
import { Session } from "@/utils/storage";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const emit = defineEmits(["onSuccess", "onError", "onCancel"]);
|
||||
const props = defineProps({
|
||||
// 列表内容
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
|
||||
mode: {
|
||||
type: String,
|
||||
default: () => "bottom",
|
||||
},
|
||||
});
|
||||
const userStore = useUserStore();
|
||||
const codeText = ref("获取验证码");
|
||||
const isDisabled = ref(false);
|
||||
const state = reactive({
|
||||
loginForm: {
|
||||
phone: "",
|
||||
code: "",
|
||||
},
|
||||
});
|
||||
|
||||
// 获取验证码
|
||||
const captcha = async () => {
|
||||
if (!validatePhoneNumber(state.loginForm.phone)) {
|
||||
return uni.showToast({
|
||||
title: "请输入正确的手机号",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
const res = await getCaptcha({
|
||||
phone: state.loginForm.phone,
|
||||
});
|
||||
|
||||
if (res.code == 200) {
|
||||
let countdown = 60;
|
||||
if (!isDisabled.value) {
|
||||
isDisabled.value = true;
|
||||
codeText.value = `${countdown}秒后重新获取`;
|
||||
const intervalId = setInterval(() => {
|
||||
countdown--;
|
||||
codeText.value = `${countdown}秒后重新获取`;
|
||||
if (countdown <= 0) {
|
||||
clearInterval(intervalId);
|
||||
isDisabled.value = false;
|
||||
codeText.value = "获取验证码";
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "请等待 60s 后重试",
|
||||
icon: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 登录成功之后的回调
|
||||
const callbackSuccess = () => {
|
||||
emit("onSuccess");
|
||||
};
|
||||
// 登录失败之后的回调
|
||||
const callBackError = () => {
|
||||
emit("onError");
|
||||
};
|
||||
|
||||
// 登录
|
||||
const Login = async () => {
|
||||
if (!validatePhoneNumber(state.loginForm.phone)) {
|
||||
return uni.showToast({
|
||||
title: "请输入正确的手机号",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (state.loginForm.code.length !== 6) {
|
||||
return uni.showToast({
|
||||
title: "请输入正确的验证码",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
const result = await userStore.onLogin({ ...state.loginForm });
|
||||
if (result.code === 200) {
|
||||
callbackSuccess();
|
||||
} else {
|
||||
callBackError();
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭弹框
|
||||
const handlePopupClose = () => {
|
||||
emit("onCancel");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.loginPopup {
|
||||
::v-deep {
|
||||
.u-slide-up-enter-active {
|
||||
width: 100%;
|
||||
height: 786rpx;
|
||||
}
|
||||
|
||||
.u-popup__content__close {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.loginPopupContent {
|
||||
box-sizing: border-box;
|
||||
padding: 30rpx;
|
||||
position: relative;
|
||||
|
||||
.loginTitle {
|
||||
// font-size: 32rpx;
|
||||
font-size: var(--h1-font-size);
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
|
||||
.loginForm {
|
||||
width: 600rpx;
|
||||
// border: 1px solid;
|
||||
margin: 60rpx auto;
|
||||
|
||||
.loginFormItem {
|
||||
width: 600rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #fff;
|
||||
border: 2rpx solid #b9b9b9;
|
||||
// padding: 0 !important;
|
||||
|
||||
&:nth-child(2) {
|
||||
margin: 32rpx 0;
|
||||
}
|
||||
|
||||
::v-deep {
|
||||
.u-form-item__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.loginFormInput {
|
||||
width: 100%;
|
||||
height: 100rpx !important;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px !important;
|
||||
}
|
||||
|
||||
.getCode {
|
||||
height: 100rpx;
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: var(--h1-font-size);
|
||||
color: rgba(51, 51, 51, 0.6);
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 2rpx;
|
||||
height: 52rpx;
|
||||
background-color: rgba(51, 51, 51, 0.1);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loginFormBtn {
|
||||
width: 600rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 20rpx;
|
||||
border: none;
|
||||
background-color: #e7303f;
|
||||
color: #fff;
|
||||
|
||||
::v-deep {
|
||||
.u-button__text {
|
||||
font-size: var(--h1-font-size) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
// font-size: 24rpx;
|
||||
font-size: var(--h4-font-size);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
color: #717171;
|
||||
|
||||
.userAgreement {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<view class="info-section">
|
||||
<InfoSummary :count="newsNum" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, ref } from "vue";
|
||||
import InfoSummary from "@/components/InfoSummary.vue"; // 路径根据实际调整
|
||||
import { getNews_cnt_d } from "@/api/newsInfo";
|
||||
|
||||
const newsNum = ref(0);
|
||||
// 今日精选
|
||||
async function getNews_cnt_dFn() {
|
||||
let temp = await getNews_cnt_d({});
|
||||
|
||||
newsNum.value = temp[0].value;
|
||||
}
|
||||
|
||||
const timer = setInterval(() => {
|
||||
getNews_cnt_dFn();
|
||||
}, 5000);
|
||||
|
||||
onMounted(() => {
|
||||
getNews_cnt_dFn();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
clearInterval(timer);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.info-section {
|
||||
margin: 0 20rpx 20rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
<template>
|
||||
<view class="top-section">
|
||||
<view class="top-section-news" @click="navigateTo">
|
||||
<view class="top-section-img">
|
||||
<image
|
||||
class="image"
|
||||
mode="aspectFit"
|
||||
src="@/assets/images/page/icon_smart@2x.png"
|
||||
></image>
|
||||
</view>
|
||||
<swiper
|
||||
class="swiper-box"
|
||||
circular
|
||||
:indicator-dots="false"
|
||||
:autoplay="true"
|
||||
:vertical="true"
|
||||
:disable-touch="true"
|
||||
:interval="3000"
|
||||
:duration="500"
|
||||
>
|
||||
<swiper-item
|
||||
class="swiper-item"
|
||||
v-for="(item, index) in newsListAll"
|
||||
:key="item.news_id"
|
||||
>
|
||||
<view class="news-item">
|
||||
<view class="num">{{ index + 1 }}</view>
|
||||
<view class="title">{{ item.title }}</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getTopNews } from "@/api/newsInfo";
|
||||
import dayjs from "dayjs";
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const emit = defineEmits(["onShow"]);
|
||||
const userStore = useUserStore();
|
||||
const userInfos = computed(() => {
|
||||
return userStore.getUserInfos();
|
||||
});
|
||||
// 获取数据
|
||||
const loading = ref(false);
|
||||
const newsListAll = ref([]); // 全部新闻
|
||||
const limit_num = ref(5);
|
||||
|
||||
// 日期格式
|
||||
const formatDateStart = "YYYY-MM-DD 00:00:00";
|
||||
const formatDateEnd = "YYYY-MM-DD 23:59:59";
|
||||
// 选择的日期
|
||||
const chooseDate = reactive({
|
||||
startDate: dayjs().format(formatDateStart),
|
||||
endDate: dayjs().format(formatDateEnd),
|
||||
});
|
||||
async function getNewsList() {
|
||||
const params = {
|
||||
start_date: chooseDate.startDate,
|
||||
end_date: chooseDate.endDate,
|
||||
limit_num: limit_num.value,
|
||||
};
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const result = await getTopNews(params);
|
||||
newsListAll.value = result;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转子页
|
||||
const navigateTo = () => {
|
||||
if (!userStore.isLogin) {
|
||||
emit("onShow");
|
||||
return;
|
||||
}
|
||||
|
||||
const isAuth = userInfos.value?.auth?.findIndex((item) => item.name === 'znzx');
|
||||
if (isAuth === -1 || userInfos.value?.auth[isAuth]?.enabled === 0) {
|
||||
uni.showToast({
|
||||
title: "暂未开通本栏目",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: "/pages/topNews/index",
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getNewsList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.top-section {
|
||||
height: 104rpx;
|
||||
margin: 0 20rpx 20rpx;
|
||||
background: linear-gradient(90deg, #fce8ea 0%, #ffffff 27.03%, #ffffff 100%);
|
||||
box-shadow: inset 0px 1rpx 0px 0px #ffffff;
|
||||
border-radius: 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.top-section-news {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 12rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.top-section-img {
|
||||
width: 83rpx;
|
||||
height: 75rpx;
|
||||
padding-right: 10rpx;
|
||||
border-right: 1px solid #e7e9eb;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.swiper-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.news-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 22rpx;
|
||||
|
||||
.num {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
margin-right: 13rpx;
|
||||
text-align: center;
|
||||
background: linear-gradient(168deg, #ffb505 0%, #fdcf1b 100%);
|
||||
border-radius: 5px;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
.title {
|
||||
width: 488rpx;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
font-weight: 500;
|
||||
font-size: 26rpx;
|
||||
color: #111111;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,435 +1,107 @@
|
|||
<template>
|
||||
<!-- 顶部 banner 区域 -->
|
||||
<view class="all">
|
||||
<!-- banner start -->
|
||||
<view class="banner">
|
||||
<img :src="bannerImg" class="banner_bk" />
|
||||
<view class="r_banner_title">
|
||||
<img :src="bannerTitle" class="banner_title" />
|
||||
<text
|
||||
>数据更新时间:{{
|
||||
dayjs(new Date().getTime()).format("YYYY-MM-DD")
|
||||
}}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<!-- banner end -->
|
||||
<!-- 容器 -->
|
||||
<view class="container">
|
||||
<!-- 头部 start -->
|
||||
<HeaderView @on-show="handleShowLogin" />
|
||||
<!-- 头部 end -->
|
||||
|
||||
<view class="">
|
||||
<view class="tag">
|
||||
<view class="r_tag_img">
|
||||
<img :src="tagicon_1_bg" class="tag_bk" />
|
||||
<view class="tag_content">
|
||||
<view class="tag_item_left">
|
||||
<text class="tag_title">行业分类贴标</text>
|
||||
<!-- 海外独家 start -->
|
||||
<BannerNewsView @on-show="handleShowLogin" />
|
||||
<!-- 海外独家 end -->
|
||||
|
||||
<view style="display: flex; margin-top: 15rpx">
|
||||
<!-- <text class="tag_num">{{ topNum.leftNum }}</text> -->
|
||||
<countTo
|
||||
:startVal="lastLeftNum"
|
||||
:endVal="topNum.leftNum"
|
||||
:duration="5000"
|
||||
class="tag_num"
|
||||
></countTo>
|
||||
<!-- 资讯榜 start -->
|
||||
<TopNewsView @on-show="handleShowLogin" />
|
||||
<!-- 资讯榜 end -->
|
||||
|
||||
<text class="tag_status">已处理</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 热门行业 start -->
|
||||
<IndustryNewsView @on-show="handleShowLogin" />
|
||||
<!-- 热门行业 end -->
|
||||
|
||||
<view class="tag_item_right">
|
||||
<img :src="tagicon_1" class="tag_icon" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 风口概念 start -->
|
||||
<ConceptNewsView @on-show="handleShowLogin" />
|
||||
<!-- 风口概念 end -->
|
||||
|
||||
<view class="r_tag_img">
|
||||
<img :src="tagicon_2_bg" class="tag_bk" />
|
||||
<view class="tag_content">
|
||||
<view class="tag_item_left">
|
||||
<text class="tag_title">概念标签贴标</text>
|
||||
<view style="display: flex; margin-top: 15rpx">
|
||||
<!-- <text class="tag_num">{{ topNum.rightNum }}</text> -->
|
||||
<countTo
|
||||
:startVal="lastRightNum"
|
||||
:endVal="topNum.rightNum"
|
||||
:duration="5000"
|
||||
class="tag_num"
|
||||
></countTo>
|
||||
<!-- 今日资讯 start -->
|
||||
<TodayNewsView />
|
||||
<!-- 今日资讯 end -->
|
||||
|
||||
<text class="tag_status">已处理</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 尾部 start -->
|
||||
<FooterView />
|
||||
<!-- 尾部 end -->
|
||||
|
||||
<view class="tag_item_right">
|
||||
<img :src="tagicon_2" class="tag_icon" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<indexMenuTitle title="资讯评分分布区间"></indexMenuTitle>
|
||||
<Line style="margin-top: 30rpx" :data="lineData"></Line>
|
||||
|
||||
<view
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-bottom: 30rpx;
|
||||
"
|
||||
>
|
||||
<InfoSummary style="width: 85%" :count="newsNum"></InfoSummary>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<indexMenuTitle title="资讯头条榜 Top20"></indexMenuTitle>
|
||||
<RankList :newsList="newsList"></RankList>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<view
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-right: 30rpx;
|
||||
height: 100rpx;
|
||||
"
|
||||
>
|
||||
<indexMenuTitle title="热门行业池 Top10"></indexMenuTitle>
|
||||
<view style="display: flex; gap: 3rpx">
|
||||
<text class="view-all" @click="onViewAll(0)">查看全部</text>
|
||||
|
||||
<u-icon size="12" name="arrow-right"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<HotIndustryList
|
||||
:industryList="industryList"
|
||||
:type="0"
|
||||
@viewAll="handleViewAll"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: 40rpx">
|
||||
<view
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-right: 30rpx;
|
||||
height: 100rpx;
|
||||
"
|
||||
>
|
||||
<indexMenuTitle title="风口概念池 Top10"></indexMenuTitle>
|
||||
<view style="display: flex; gap: 3rpx">
|
||||
<text class="view-all" @click="onViewAll(1)">查看全部</text>
|
||||
|
||||
<u-icon size="12" name="arrow-right"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<HotIndustryList
|
||||
:type="1"
|
||||
:industryList="topConceptList"
|
||||
@viewAll="handleViewAll"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="logout" @click="loginOut" v-if="Session.get('token')"
|
||||
>退出登录</view
|
||||
>
|
||||
|
||||
<LoginPopup
|
||||
<!-- 登录弹窗 start -->
|
||||
<LoginDialog
|
||||
:show="LoginShow"
|
||||
@handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback"
|
||||
@handlePopupErrorCallback="handlePopupErrorCallback"
|
||||
@onSuccess="handleLoginSuccess"
|
||||
@onCancel="handleLoginCancel"
|
||||
@onError="handleLoginError"
|
||||
/>
|
||||
<!-- 登录弹窗 end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, reactive } from "vue";
|
||||
import Line from "@/components/charts/Line.vue";
|
||||
import bannerImg from "@/assets/zixun/banner_pic.png";
|
||||
import bannerTitle from "@/assets/zixun/banner_title.png";
|
||||
import tagicon_1_bg from "@/assets/zixun/tagicon_1_bg.png";
|
||||
import tagicon_2_bg from "@/assets/zixun/tagicon_2_bg.png";
|
||||
import tagicon_1 from "@/assets/zixun/tagicon_1.png";
|
||||
import tagicon_2 from "@/assets/zixun/tagicon_2.png";
|
||||
import LoginPopup from "@/components/loginPopup/index.vue";
|
||||
import HeaderView from "./components/HeaderView/index.vue";
|
||||
import BannerNewsView from "./components/BannerNewsView/index.vue";
|
||||
import TopNewsView from "./components/TopNewsView/index.vue";
|
||||
import IndustryNewsView from "./components/IndustryNewsView/index.vue";
|
||||
import ConceptNewsView from "./components/ConceptNewsView/index.vue";
|
||||
import TodayNewsView from "./components/TodayNewsView/index.vue";
|
||||
import FooterView from "./components/FooterView/index.vue";
|
||||
import LoginDialog from "@/pages/realtimeInfo/components/LoginPopup/index.vue";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { Session } from "@/utils/storage";
|
||||
|
||||
import {
|
||||
getindustryCount,
|
||||
getConceptCount,
|
||||
getTopNews,
|
||||
getTopIndustry_d,
|
||||
getTopConcept_d,
|
||||
getNews_cnt_d,
|
||||
newsInfoScore,
|
||||
} from "@/api/newsInfo";
|
||||
import countTo from "@/components/count-to/vue-countTo.vue";
|
||||
import RankList from "@/components/RankList.vue"; // 路径根据实际调整
|
||||
import InfoSummary from "@/components/InfoSummary.vue"; // 路径根据实际调整
|
||||
import indexMenuTitle from "@/components/indexMenuTitle.vue"; // 路径根据实际调整
|
||||
import dayjs from "dayjs/esm/index";
|
||||
import HotIndustryList from "@/components/HotIndustryList.vue"; // 路径根据实际调整
|
||||
const userStore = useUserStore();
|
||||
|
||||
const newsList = ref([]);
|
||||
|
||||
const lastLeftNum = ref(0);
|
||||
const lastRightNum = ref(0);
|
||||
// 登录弹框
|
||||
const LoginShow = ref(false);
|
||||
|
||||
const industryList = ref([]);
|
||||
const topConceptList = ref([]);
|
||||
const newsNum = ref(0);
|
||||
const lineData = ref();
|
||||
const handleViewAll = () => {
|
||||
// 在这里处理点击“查看全部”的逻辑,比如跳转新页面等
|
||||
console.log("点击了查看全部");
|
||||
// 显示弹框
|
||||
const handleShowLogin = () => {
|
||||
LoginShow.value = true;
|
||||
};
|
||||
|
||||
const topNum = ref({});
|
||||
|
||||
// 获取顶部两个统计数据
|
||||
async function getTopNum() {
|
||||
let res1 = await getindustryCount({});
|
||||
topNum.value.leftNum = res1.aggregations.industry_non_empty.doc_count;
|
||||
let res2 = await getConceptCount({});
|
||||
topNum.value.rightNum = res2.aggregations.concept_non_empty.doc_count;
|
||||
|
||||
lastLeftNum.value = topNum.value.leftNum;
|
||||
lastRightNum.value = topNum.value.rightNum;
|
||||
}
|
||||
|
||||
// 概念标签贴标
|
||||
async function getNewsList() {
|
||||
newsList.value = await getTopNews({});
|
||||
}
|
||||
|
||||
// 热门行业top10
|
||||
async function getTopIndustry_dFn() {
|
||||
industryList.value = await getTopIndustry_d({});
|
||||
}
|
||||
|
||||
// 风口概念池top10
|
||||
async function getTopConcept_dFn() {
|
||||
topConceptList.value = await getTopConcept_d({});
|
||||
}
|
||||
|
||||
// 今日精选
|
||||
async function getNews_cnt_dFn() {
|
||||
let temp = await getNews_cnt_d({});
|
||||
|
||||
newsNum.value = temp[0].value;
|
||||
}
|
||||
|
||||
// 获取柱状图数据
|
||||
async function getLineData() {
|
||||
let res = await newsInfoScore({});
|
||||
lineData.value = res;
|
||||
}
|
||||
|
||||
function initData() {
|
||||
// 获取柱状图数据
|
||||
getLineData();
|
||||
// 获取顶部两个统计数据
|
||||
getTopNum();
|
||||
// 概念标签贴标
|
||||
getNewsList();
|
||||
// 热门行业top10
|
||||
getTopIndustry_dFn();
|
||||
// 风口概念池top10
|
||||
getTopConcept_dFn();
|
||||
// 今日精选
|
||||
getNews_cnt_dFn();
|
||||
}
|
||||
|
||||
const type = ref();
|
||||
function onViewAll(type) {
|
||||
type.value = type;
|
||||
if (Session.get("token")) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/realtimeInfo/rankDetail?type=" + type,
|
||||
});
|
||||
} else {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
const timer = setInterval(() => {
|
||||
initData();
|
||||
}, 5000);
|
||||
|
||||
const LoginShow = ref(false);
|
||||
const isLoginStatus = ref();
|
||||
// 关闭弹框
|
||||
const handlePopupClose = () => {
|
||||
const handleLoginCancel = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
|
||||
// 登录成功之后的回调
|
||||
const handlePopupSuccessCallback = () => {
|
||||
isLoginStatus.value = true;
|
||||
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/realtimeInfo/rankDetail?type=" + type.value,
|
||||
// });
|
||||
const handleLoginSuccess = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
|
||||
// 登录失败之后的回调
|
||||
const handlePopupErrorCallback = () => {
|
||||
const handleLoginError = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
|
||||
function loginOut() {
|
||||
Session.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
initData();
|
||||
if (!Session.get("token")) {
|
||||
LoginShow.value = true;
|
||||
console.log('output >>>>> Session.get("userInfos")',Session.get("userInfos"));
|
||||
|
||||
if(!Session.get("userInfos")) {
|
||||
Session.clear()
|
||||
}
|
||||
|
||||
if (!userStore.isLogin) {
|
||||
handleShowLogin();
|
||||
}
|
||||
|
||||
const { aplus_queue } = window;
|
||||
aplus_queue.push({
|
||||
action: "aplus.sendPV",
|
||||
arguments: [{ is_auto: false }], // 此处上报的数据暂时在后台没有展示
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.all {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f3f5f8;
|
||||
}
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.banner_bk {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.r_banner_title {
|
||||
position: absolute;
|
||||
top: 160rpx;
|
||||
left: 50rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.banner_title {
|
||||
width: 364rpx;
|
||||
height: 134rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: flex;
|
||||
margin-top: -150rpx;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
padding: 0 25rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.r_tag_img {
|
||||
width: calc(50vw - 20rpx);
|
||||
height: 175rpx;
|
||||
position: relative;
|
||||
box-shadow: 0 10rpx 10rpx rgba(80, 80, 80, 0.1);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.tag_bk {
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tag_content {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
left: 30rpx;
|
||||
width: 83%;
|
||||
justify-content: space-between;
|
||||
|
||||
.tag_item_left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tag_title {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #222222;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
|
||||
.tag_num {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 38rpx;
|
||||
color: #222222;
|
||||
line-height: 56rpx;
|
||||
}
|
||||
|
||||
.tag_status {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 33rpx;
|
||||
margin-top: 15rpx;
|
||||
margin-left: 7rpx;
|
||||
}
|
||||
|
||||
.tag_item_right {
|
||||
width: 70rpx;
|
||||
height: 84rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag_icon {
|
||||
width: 70rpx;
|
||||
height: 84rpx;
|
||||
}
|
||||
|
||||
.view-all {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.logout {
|
||||
// width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: red;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
margin-top: 50rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-left: 20rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
max-width: 750rpx;
|
||||
margin: 0 auto;
|
||||
background-color: #f3f5f8;
|
||||
font-family: "PingFangSC, PingFang SC";
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,594 @@
|
|||
<template>
|
||||
<!-- 顶部 banner 区域 -->
|
||||
<!-- banner start -->
|
||||
<view class="all">
|
||||
<text class="top_menu_text">海外资讯</text>
|
||||
<view class="banner">
|
||||
<img :src="bannerImg" class="banner_bk" />
|
||||
<view class="r_banner_title">
|
||||
<img :src="bannerTitle2" class="banner_title" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- banner end -->
|
||||
|
||||
<view class="list_content">
|
||||
<!-- 搜索 start -->
|
||||
<view class="r_sreach">
|
||||
<view class="sreach" style="height: 72rpx">
|
||||
<u-search v-model="form.keyword" placeholder="搜索资讯" @search="onSreach" @custom="onSreach" />
|
||||
<!-- <view class="sreach_icon">
|
||||
<image :src="icon_search"></image>
|
||||
</view>
|
||||
<view class="sreach_text">
|
||||
<text>搜索资讯</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<!-- 搜索 end -->
|
||||
|
||||
<view class="r_list">
|
||||
<view v-for="item in listData" :key="item.day">
|
||||
<!-- 时间轴顶部日期 start -->
|
||||
<view class="item_top">
|
||||
<view class="r_line">
|
||||
<view class="item_point"></view>
|
||||
<view class="item_line"></view>
|
||||
</view>
|
||||
<text class="item_day">{{ dayjs(item.day).format("YYYY年MM月DD日") }}</text>
|
||||
</view>
|
||||
<!-- 时间轴顶部日期 end -->
|
||||
<view class="list_card">
|
||||
<view class="card_left">
|
||||
<img :src="time_icon" />
|
||||
<view class="left_line"></view>
|
||||
</view>
|
||||
<view class="card_right">
|
||||
<view v-for="item in item.list" :key="item.time" @click="goDetail(item)">
|
||||
<view class="item_time">
|
||||
<text>{{ item.timeStr }}</text>
|
||||
<text class="item_source_title">来自 <text class="item_source">中国证券报</text></text>
|
||||
</view>
|
||||
<view class="item_title">
|
||||
<text>{{ item.title }}</text>
|
||||
</view>
|
||||
<view class="item_summary">
|
||||
<text>{{ item.summary }}</text>
|
||||
</view>
|
||||
<view class="item_etf">
|
||||
<view v-for="etf in item.etfs" :key="etf.code" class="item_etf_item" @click.stop="goEtfDetail(etf)">
|
||||
<view></view>
|
||||
<text>{{ etf.name }}</text>
|
||||
<div class="btn-play"></div>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="r_logout">
|
||||
<view class="logout" @click="loginOut" v-if="Session.get('token')">退出登录</view>
|
||||
</view>
|
||||
|
||||
<LoginPopup
|
||||
:show="LoginShow"
|
||||
@handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback"
|
||||
@handlePopupErrorCallback="handlePopupErrorCallback"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, reactive } from "vue";
|
||||
import Line from "@/components/charts/Line.vue";
|
||||
import bannerImg from "@/assets/zixun/banner_pic1.png";
|
||||
import bannerTitle from "@/assets/zixun/banner_title.png";
|
||||
import bannerTitle2 from "@/assets/zixun/banner_title3.png";
|
||||
import icon_search from "@/assets/zixun/icon_search.png";
|
||||
import time_icon from "@/assets/zixun/time_icon.png";
|
||||
import LoginPopup from "@/components/loginPopup/index.vue";
|
||||
import { Session } from "@/utils/storage";
|
||||
import dayjs from "dayjs/esm/index";
|
||||
import { onReachBottom } from "@dcloudio/uni-app";
|
||||
import { getEtfIndexList } from "@/api/index";
|
||||
|
||||
const listData = ref([
|
||||
// {
|
||||
// day: "2026-10-26",
|
||||
// list: [
|
||||
// {
|
||||
// time: "11:30:56",
|
||||
// title: "刚果延长禁令后,中国钴价和库存飙升刚果延长禁令后,中国钴价和库存飙升",
|
||||
// summary: "刚果民主共和国将钴出口禁令延长至9月,导致全球约四分之三的钴供应受到影响。这一消息引…",
|
||||
// etfs: [
|
||||
// {
|
||||
// name: "医药 ETF",
|
||||
// code: "string",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
]);
|
||||
|
||||
const form = ref({
|
||||
page: 1,
|
||||
keyword: null,
|
||||
});
|
||||
async function getData() {
|
||||
uni.showLoading({
|
||||
title: "加载中",
|
||||
});
|
||||
let { code, data } = await getEtfIndexList({
|
||||
...form.value,
|
||||
size: 20,
|
||||
});
|
||||
uni.hideLoading();
|
||||
|
||||
if (code == 200) {
|
||||
if (form.value.page == 1) {
|
||||
listData.value = [];
|
||||
listData.value = data.list;
|
||||
} else {
|
||||
// 处理可能的day字段重复,合并相同day的list数据
|
||||
const newList = [...data.list];
|
||||
const updatedList = [...listData.value];
|
||||
|
||||
newList.forEach(newItem => {
|
||||
// 检查是否存在相同day的条目
|
||||
const existingItemIndex = updatedList.findIndex(item => item.day === newItem.day);
|
||||
|
||||
if (existingItemIndex !== -1) {
|
||||
// 如果存在相同day,合并list数据
|
||||
updatedList[existingItemIndex].list = [...updatedList[existingItemIndex].list, ...newItem.list];
|
||||
} else {
|
||||
// 如果不存在相同day,直接添加
|
||||
updatedList.push(newItem);
|
||||
}
|
||||
});
|
||||
|
||||
listData.value = updatedList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LoginShow = ref(false);
|
||||
const isLoginStatus = ref();
|
||||
// 关闭弹框
|
||||
const handlePopupClose = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
|
||||
// 登录成功之后的回调
|
||||
const handlePopupSuccessCallback = () => {
|
||||
isLoginStatus.value = true;
|
||||
};
|
||||
|
||||
// 登录失败之后的回调
|
||||
const handlePopupErrorCallback = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
import { doLogout } from "@/api";
|
||||
import { onPullDownRefresh } from "@dcloudio/uni-app";
|
||||
function loginOut() {
|
||||
doLogout({
|
||||
financialAccount: Session.get("userPhone"),
|
||||
});
|
||||
Session.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
form.value.page++;
|
||||
getData();
|
||||
});
|
||||
|
||||
function goDetail(item, index) {
|
||||
if (Session.get("token")) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&intoType=etf`,
|
||||
});
|
||||
} else {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
function goEtfDetail(item) {
|
||||
console.log("🚀 ~ goEtfDetail ~ item:", item);
|
||||
uni.navigateTo({
|
||||
url: `/pages/realtimeInfo/indexEtfInfo?name=${item.name}&code=${item.code}`,
|
||||
});
|
||||
}
|
||||
|
||||
function onSreach() {
|
||||
if (Session.get("token")) {
|
||||
form.value.page = 1;
|
||||
getData();
|
||||
} else {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (!Session.get("token")) {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
getData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.all {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.top_menu_text {
|
||||
position: absolute;
|
||||
top: 60rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 9999;
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #ffffff;
|
||||
line-height: 36rpx;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.banner_bk {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.r_banner_title {
|
||||
position: absolute;
|
||||
top: 200rpx;
|
||||
left: 50rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.banner_title {
|
||||
width: 461rpx;
|
||||
height: 110rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-family: AlibabaPuHuiTiM;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.r_logout {
|
||||
position: fixed;
|
||||
bottom: 0rpx;
|
||||
right: 0rpx;
|
||||
z-index: 9999;
|
||||
background-color: white;
|
||||
width: 100vw;
|
||||
height: auto;
|
||||
box-shadow: 0 -10rpx 20rpx rgba(73, 73, 73, 0.1);
|
||||
}
|
||||
|
||||
.logout {
|
||||
// width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: red;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-left: 20rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.logo_text {
|
||||
width: 88rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.top_bk {
|
||||
width: 100vw;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.list_content {
|
||||
position: relative;
|
||||
z-index: 9999;
|
||||
|
||||
// margin-top: -70px;
|
||||
// padding: 10rpx 30rpx;
|
||||
background-color: #f3f5f8;
|
||||
// background: linear-gradient(180deg, #ffffff 0%, #f3f5f8 100%);
|
||||
// min-height: 80vh;
|
||||
|
||||
.r_sreach {
|
||||
position: relative;
|
||||
z-index: 99999;
|
||||
|
||||
margin-top: -120rpx;
|
||||
|
||||
border-radius: 24rpx 24rpx 0rpx 0rpx;
|
||||
// width: 100%;
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// margin-top: 30rpx;
|
||||
padding-top: 30rpx;
|
||||
padding: 0 30rpx;
|
||||
background-color: white;
|
||||
background-image: linear-gradient(to bottom, white 60rpx, #f3f5f8);
|
||||
// background: linear-gradient(to bottom, #ffffff 0%, #f3f5f8 100%);
|
||||
}
|
||||
|
||||
.sreach {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0rpx 30rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 100rpx;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #f3f5f8;
|
||||
border-radius: 36rpx;
|
||||
// box-shadow: 0 0 10rpx rgba(97, 97, 97, 0.1);
|
||||
}
|
||||
|
||||
.sreach_icon {
|
||||
margin-right: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.sreach_text {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
line-height: 40rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.item_day {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 24rpx;
|
||||
color: #222222;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
margin-top: -10rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.r_list {
|
||||
padding: 10rpx 30rpx;
|
||||
margin-top: -30rpx;
|
||||
}
|
||||
|
||||
.item_top {
|
||||
display: flex;
|
||||
margin-top: 40rpx;
|
||||
padding: 0 30rpx;
|
||||
|
||||
.r_line {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item_point {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #eb5d46;
|
||||
border-radius: 100rpx;
|
||||
}
|
||||
|
||||
.item_line {
|
||||
width: 1rpx;
|
||||
height: 35rpx;
|
||||
border-left: 2px dashed #d9d7d7;
|
||||
}
|
||||
}
|
||||
|
||||
.list_card {
|
||||
display: flex;
|
||||
// height: 334rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 30rpx 30rpx;
|
||||
|
||||
.card_left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 25rpx;
|
||||
|
||||
img {
|
||||
width: 8rpx;
|
||||
height: 33rpx;
|
||||
}
|
||||
|
||||
.left_line {
|
||||
width: 1rpx;
|
||||
height: 100%;
|
||||
border-left: 2px dashed #d9d7d7;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.card_right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 20rpx;
|
||||
width: 95%;
|
||||
margin-top: 10rpx;
|
||||
gap: 10rpx;
|
||||
|
||||
.item_time {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
color: #222222;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.item_title {
|
||||
width: 100%;
|
||||
margin-top: 30rpx;
|
||||
|
||||
text {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
display: inline-block;
|
||||
/* 或 block */
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.item_summary {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
margin-top: 10rpx;
|
||||
|
||||
/* 1. 必须将元素设置为块级或弹性盒 */
|
||||
display: -webkit-box;
|
||||
/* 2. 定义盒模型的排列方向为垂直 */
|
||||
-webkit-box-orient: vertical;
|
||||
/* 3. 限制显示的行数 */
|
||||
-webkit-line-clamp: 2;
|
||||
/* 4. 隐藏超出的内容 */
|
||||
overflow: hidden;
|
||||
/* 5. (可选) 当文本溢出时显示省略号 */
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.item_source_title {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #b3b3b3;
|
||||
line-height: 33rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.item_source {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #5978b2;
|
||||
line-height: 33rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.item_etf {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 10rpx;
|
||||
gap: 20rpx;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.item_etf_item {
|
||||
// width: 168rpx;
|
||||
width: calc(50% - 60rpx);
|
||||
height: 48rpx;
|
||||
background: #edf1f5;
|
||||
border-radius: 125rpx;
|
||||
padding: 5rpx 25rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
justify-content: space-between;
|
||||
|
||||
text {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
/* 容器样式(模拟红框) */
|
||||
.btn-play {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
/* 三角形伪元素 */
|
||||
.btn-play::before {
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 8px solid #999;
|
||||
/* 注意:这里是border-left,因为三角形朝右时,左边框是实心 */
|
||||
margin-left: 4px;
|
||||
/* 与文字的间距(从右边移到左边) */
|
||||
}
|
||||
|
||||
/* 文字部分 */
|
||||
.btn-play span {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
line-height: 44rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
<template>
|
||||
<div class="index-etf-info">
|
||||
<!-- 头部 -->
|
||||
<view class="vipHeader">
|
||||
<view class="flashBack" @click="doBack">
|
||||
<u-icon size="20" name="arrow-left" color="#000"></u-icon>
|
||||
</view>
|
||||
<view style="display: flex; flex-direction: column">
|
||||
<view class="title">{{ name }}</view>
|
||||
<view class="title_sub">{{ code }}</view>
|
||||
</view>
|
||||
<view style="width: 5%"></view>
|
||||
</view>
|
||||
|
||||
<view style="width: 100vw; height: 10rpx; background-color: #f5f5f5"></view>
|
||||
<!-- 指数ETF实时信息展示区域 -->
|
||||
<view class="r_list">
|
||||
<view v-for="(item, index) in etfInfoList" :key="index" class="news-item" @click="goDetail(item, 0)">
|
||||
<view class="news-content">
|
||||
<text class="news-title">{{ item.title }}</text>
|
||||
<text class="news-desc">{{ item.summary }}</text>
|
||||
|
||||
<view class="news-meta">
|
||||
<view>
|
||||
<text class="time">
|
||||
{{ timeFormat(new Date(item.publish_time).getTime()) }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="time">中国证券报</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { ref } from "vue";
|
||||
import { fetchEtfDetail } from "@/api/index";
|
||||
|
||||
// 使用 Vue3 的 <script setup> 语法糖
|
||||
// 在此声明响应式数据、方法等
|
||||
|
||||
const etfInfoList = ref([]);
|
||||
async function getEtfInfo() {
|
||||
uni.showLoading({
|
||||
title: "加载中",
|
||||
});
|
||||
let { code, data } = await fetchEtfDetail({
|
||||
etfName: name.value,
|
||||
});
|
||||
uni.hideLoading();
|
||||
|
||||
if (code === 200) {
|
||||
console.log(data);
|
||||
etfInfoList.value = data.list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 格式化时间
|
||||
* @param {String|Number} dateTime 需要格式化的时间戳
|
||||
* @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
|
||||
* @returns {string} 返回格式化后的字符串
|
||||
*/
|
||||
function timeFormat(dateTime = null, formatStr = "yyyy-mm-dd hh:MM:ss") {
|
||||
let date;
|
||||
// 若传入时间为假值,则取当前时间
|
||||
if (!dateTime) {
|
||||
date = new Date();
|
||||
}
|
||||
// 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
|
||||
else if (/^\d{10}$/.test(dateTime.toString().trim())) {
|
||||
date = new Date(dateTime * 1000);
|
||||
}
|
||||
// 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
|
||||
else if (typeof dateTime === "string" && /^\d+$/.test(dateTime.trim())) {
|
||||
date = new Date(Number(dateTime));
|
||||
}
|
||||
// 其他都认为符合 RFC 2822 规范
|
||||
else {
|
||||
// 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
|
||||
date = new Date(typeof dateTime === "string" ? dateTime.replace(/-/g, "/") : dateTime);
|
||||
}
|
||||
|
||||
const timeSource = {
|
||||
y: date.getFullYear().toString(), // 年
|
||||
m: (date.getMonth() + 1).toString().padStart(2, "0"), // 月
|
||||
d: date.getDate().toString().padStart(2, "0"), // 日
|
||||
h: date.getHours().toString().padStart(2, "0"), // 时
|
||||
M: date.getMinutes().toString().padStart(2, "0"), // 分
|
||||
s: date.getSeconds().toString().padStart(2, "0"), // 秒
|
||||
// 有其他格式化字符需求可以继续添加,必须转化成字符串
|
||||
};
|
||||
|
||||
for (const key in timeSource) {
|
||||
const [ret] = new RegExp(`${key}+`).exec(formatStr) || [];
|
||||
if (ret) {
|
||||
// 年可能只需展示两位
|
||||
const beginIndex = key === "y" && ret.length === 2 ? 2 : 0;
|
||||
formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex));
|
||||
}
|
||||
}
|
||||
|
||||
return formatStr;
|
||||
}
|
||||
|
||||
function goDetail(item, index) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/indexNewsInfo?id=${item.id}&intoType=etf`,
|
||||
});
|
||||
}
|
||||
|
||||
function doBack() {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
}
|
||||
|
||||
const name = ref("");
|
||||
const code = ref("");
|
||||
onLoad((option) => {
|
||||
console.log(option.name);
|
||||
name.value = option.name;
|
||||
code.value = option.code;
|
||||
|
||||
getEtfInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.news-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 1px solid #f2f2f2;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.news-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.r_list {
|
||||
padding: 30rpx;
|
||||
width: calc(100vw - 60rpx);
|
||||
}
|
||||
|
||||
.news-title {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 30rpx;
|
||||
color: #222222;
|
||||
line-height: 42rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
margin-bottom: 5px;
|
||||
line-height: 1.2;
|
||||
|
||||
width: calc(100vw - 60rpx);
|
||||
display: inline-block;
|
||||
/* 或 block */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.news-desc {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
display: -webkit-box;
|
||||
/* 设置为WebKit内核的弹性盒子模型 */
|
||||
-webkit-box-orient: vertical;
|
||||
/* 垂直排列 */
|
||||
-webkit-line-clamp: 2;
|
||||
/* 限制显示三行 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出范围的内容 */
|
||||
text-overflow: ellipsis;
|
||||
/* 使用省略号 */
|
||||
|
||||
width: calc(100vw - 60rpx);
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.news-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 26rpx;
|
||||
}
|
||||
|
||||
.source,
|
||||
.time,
|
||||
.score {
|
||||
// opacity: 0.8;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 30rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.time {
|
||||
// margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.score {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 22rpx;
|
||||
color: #ffa800;
|
||||
line-height: 30rpx;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.vipHeader {
|
||||
width: 100vw;
|
||||
height: 120rpx;
|
||||
background-color: white;
|
||||
box-sizing: border-box;
|
||||
padding: 32rpx 32rpx 6rpx 40rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
// position: sticky;
|
||||
// top: 0;
|
||||
// z-index: 9999;
|
||||
|
||||
.flashBack {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.title_sub {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
font-weight: 400;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,623 @@
|
|||
<template>
|
||||
<!-- 顶部 banner 区域 -->
|
||||
<view class="all">
|
||||
<!-- banner start -->
|
||||
<view class="banner">
|
||||
<img :src="bannerImg" class="banner_bk" />
|
||||
<view class="r_banner_title">
|
||||
<img :src="bannerTitle2" class="banner_title" />
|
||||
<text>数据更新时间:{{ dayjs(new Date().getTime()).format("YYYY-MM-DD") }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- banner end -->
|
||||
|
||||
<view>
|
||||
<!-- <view class="tag">
|
||||
<view class="r_tag_img">
|
||||
<img :src="tagicon_1_bg" class="tag_bk" />
|
||||
<view class="tag_content">
|
||||
<view class="tag_item_left">
|
||||
<text class="tag_title">行业分类贴标</text>
|
||||
|
||||
<view style="display: flex; margin-top: 15rpx">
|
||||
<countTo :startVal="lastLeftNum" :endVal="topNum.leftNum" :duration="5000" class="tag_num"></countTo>
|
||||
|
||||
<text class="tag_status">已处理</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tag_item_right">
|
||||
<img :src="tagicon_1" class="tag_icon" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="r_tag_img">
|
||||
<img :src="tagicon_2_bg" class="tag_bk" />
|
||||
<view class="tag_content">
|
||||
<view class="tag_item_left">
|
||||
<text class="tag_title">概念标签贴标</text>
|
||||
<view style="display: flex; margin-top: 15rpx">
|
||||
<countTo :startVal="lastRightNum" :endVal="topNum.rightNum" :duration="5000" class="tag_num"></countTo>
|
||||
|
||||
<text class="tag_status">已处理</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tag_item_right">
|
||||
<img :src="tagicon_2" class="tag_icon" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<view style="background-color: white; margin-top: -100rpx; position: relative; z-index: 9999">
|
||||
<indexMenuTitle title="近7天热度统计"></indexMenuTitle>
|
||||
<LineHol v-if="lineTabIndex === 0" barColor="#3C74F1" :data="lineTopData"></LineHol>
|
||||
<LineHol v-else-if="lineTabIndex === 1" barColor="#FFCC65" :data="lineTopData"></LineHol>
|
||||
<LineHolYellow v-else-if="lineTabIndex === 2" barColor="#8B2DD4" :data="lineTopData"></LineHolYellow>
|
||||
|
||||
<div style="display: flex; justify-content: center; margin-bottom: 20px; margin-top: 20px">
|
||||
<div class="tabs">
|
||||
<div :class="['tab', 'tab_left', { active: lineTabIndex === 0 }]" @click="handleTabClick(0)">申万行业</div>
|
||||
<div :class="['tab', { active: lineTabIndex === 1 }]" @click="handleTabClick(1)">概念标签</div>
|
||||
<div :class="['tab', 'tab_right', { active: lineTabIndex === 2 }]" @click="handleTabClick(2)">媒体来源</div>
|
||||
</div>
|
||||
</div>
|
||||
</view>
|
||||
|
||||
<!-- <view style="background-color: white; margin-top: 40rpx">
|
||||
<indexMenuTitle title="资讯评分分布区间"></indexMenuTitle>
|
||||
<Line style="margin-top: 30rpx" :data="lineData"></Line>
|
||||
|
||||
<view style="display: flex; flex-direction: column; text-align: center; justify-content: center; align-items: center; padding-bottom: 30rpx">
|
||||
<InfoSummary style="width: 85%" :count="newsNum"></InfoSummary>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view style="background-color: white; padding-top: 40rpx">
|
||||
<view style="width: 100vw; display: flex; justify-content: space-between; align-items: center">
|
||||
<indexMenuTitle title="编辑精选" style="margin-top: 10rpx"></indexMenuTitle>
|
||||
|
||||
<view class="r_sreach">
|
||||
<!-- <image class="top_bk" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/top_bg.png"></image> -->
|
||||
<!-- <image class="logo_text" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/logo_text_icon.png"> </image> -->
|
||||
<view class="sreach" @click="goSreach">
|
||||
<view class="sreach_icon">
|
||||
<image src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_search_line.png"></image>
|
||||
</view>
|
||||
<view class="sreach_text">
|
||||
<text>搜索资讯</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="width: 100%; display: flex; justify-content: flex-end">
|
||||
<view
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 15rpx;
|
||||
font-size: 30rpx;
|
||||
gap: 10rpx;
|
||||
margin-top: 10rpx;
|
||||
"
|
||||
@click="showCalendar"
|
||||
>
|
||||
{{ chooseDate.startDate.split(" ")[0] }}
|
||||
<u-icon name="calendar" size="26" style="margin-right: 10rpx"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<RankList hasTag :newsList="newsList" :needExp="false"></RankList>
|
||||
</view>
|
||||
|
||||
<view class="logout" @click="loginOut" v-if="Session.get('token')">退出登录</view>
|
||||
|
||||
<u-calendar
|
||||
:show="calendarShow"
|
||||
min-date="2025-01-01"
|
||||
closeOnClickOverlay
|
||||
:max-date="maxDate"
|
||||
:default-date="chooseDate.startDate"
|
||||
monthNum="24"
|
||||
:key="chooseDate.startDate"
|
||||
@confirm="calendarConfirm"
|
||||
@close="calendarShow = false"
|
||||
>
|
||||
</u-calendar>
|
||||
|
||||
<LoginPopup
|
||||
:show="LoginShow"
|
||||
@handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback"
|
||||
@handlePopupErrorCallback="handlePopupErrorCallback"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, reactive } from "vue";
|
||||
import Line from "@/components/charts/Line.vue";
|
||||
import bannerImg from "@/assets/zixun/banner_pic.png";
|
||||
import bannerTitle from "@/assets/zixun/banner_title.png";
|
||||
import bannerTitle2 from "@/assets/zixun/banner_title2.png";
|
||||
import tagicon_1_bg from "@/assets/zixun/tagicon_1_bg.png";
|
||||
import tagicon_2_bg from "@/assets/zixun/tagicon_2_bg.png";
|
||||
import tagicon_1 from "@/assets/zixun/tagicon_1.png";
|
||||
import tagicon_2 from "@/assets/zixun/tagicon_2.png";
|
||||
import LoginPopup from "@/components/loginPopup/index.vue";
|
||||
import { Session } from "@/utils/storage";
|
||||
import LineHol from "@/components/charts/LineHol.vue";
|
||||
import LineHolYellow from "@/components/charts/LineHolYellow.vue";
|
||||
|
||||
import {
|
||||
getindustryCount,
|
||||
getConceptCount,
|
||||
getTopNewsAll,
|
||||
getTopIndustry_d,
|
||||
getTopConcept_d,
|
||||
getNews_cnt_d,
|
||||
newsInfoScore,
|
||||
getTopConceptPeriod,
|
||||
getTopIndustryPeriod,
|
||||
getTopSourcePeriod,
|
||||
getTopNewsAllRelease,
|
||||
} from "@/api/newsInfo";
|
||||
import countTo from "@/components/count-to/vue-countTo.vue";
|
||||
import RankList from "@/components/RankList.vue"; // 路径根据实际调整
|
||||
import InfoSummary from "@/components/InfoSummary.vue"; // 路径根据实际调整
|
||||
import indexMenuTitle from "@/components/indexMenuTitle.vue"; // 路径根据实际调整
|
||||
import dayjs from "dayjs/esm/index";
|
||||
import HotIndustryList from "@/components/HotIndustryList.vue"; // 路径根据实际调整
|
||||
|
||||
const newsList = ref([]);
|
||||
|
||||
const lastLeftNum = ref(0);
|
||||
const lastRightNum = ref(0);
|
||||
|
||||
const industryList = ref([]);
|
||||
const topConceptList = ref([]);
|
||||
const newsNum = ref(0);
|
||||
const lineData = ref();
|
||||
const handleViewAll = () => {
|
||||
// 在这里处理点击“查看全部”的逻辑,比如跳转新页面等
|
||||
console.log("点击了查看全部");
|
||||
};
|
||||
|
||||
const topNum = ref({});
|
||||
|
||||
const d = new Date();
|
||||
const year = d.getFullYear();
|
||||
let month = d.getMonth() + 1;
|
||||
month = month < 10 ? `0${month}` : month;
|
||||
const date = d.getDate();
|
||||
const maxDate = ref(`${year}-${month}-${date} 23:59:59`);
|
||||
const minDate = ref(`${year}-${month}-${date}`);
|
||||
|
||||
const calendarShow = ref(false);
|
||||
|
||||
const chooseDate = reactive({
|
||||
startDate: `${year}-${month}-${date}`,
|
||||
endDate: null,
|
||||
});
|
||||
function showCalendar() {
|
||||
calendarShow.value = true;
|
||||
}
|
||||
|
||||
function calendarConfirm(dateList) {
|
||||
console.log("🚀 ~ calendarConfirm ~ dateList:", dateList);
|
||||
if (dateList && dateList.length > 0) {
|
||||
chooseDate.startDate = dateList[0] + " 00:00:00";
|
||||
chooseDate.endDate = dateList[dateList.length - 1] + " 23:59:59";
|
||||
}
|
||||
getNewsList();
|
||||
calendarShow.value = false;
|
||||
console.log("🚀 ~ calendarConfirm ~ chooseDate:", chooseDate);
|
||||
}
|
||||
|
||||
// 获取顶部两个统计数据
|
||||
async function getTopNum() {
|
||||
let res1 = await getindustryCount({});
|
||||
topNum.value.leftNum = res1.aggregations.industry_non_empty.doc_count;
|
||||
let res2 = await getConceptCount({});
|
||||
topNum.value.rightNum = res2.aggregations.concept_non_empty.doc_count;
|
||||
|
||||
lastLeftNum.value = topNum.value.leftNum;
|
||||
lastRightNum.value = topNum.value.rightNum;
|
||||
}
|
||||
|
||||
// 概念标签贴标
|
||||
async function getNewsList() {
|
||||
console.log(`🚀 ~ getNewsList ~ chooseDate.startDate.split(" ")[0]:`, chooseDate.startDate.split(" ")[0]);
|
||||
|
||||
newsList.value = await getTopNewsAllRelease({
|
||||
input_date: chooseDate.startDate.split(" ")[0],
|
||||
});
|
||||
}
|
||||
|
||||
// 热门行业top10
|
||||
async function getTopIndustry_dFn() {
|
||||
industryList.value = await getTopIndustry_d({});
|
||||
}
|
||||
|
||||
// 风口概念池top10
|
||||
async function getTopConcept_dFn() {
|
||||
topConceptList.value = await getTopConcept_d({});
|
||||
}
|
||||
|
||||
// 今日精选
|
||||
async function getNews_cnt_dFn() {
|
||||
let temp = await getNews_cnt_d({});
|
||||
|
||||
newsNum.value = temp[0].value;
|
||||
}
|
||||
|
||||
// 获取柱状图数据
|
||||
async function getLineData() {
|
||||
let res = await newsInfoScore({});
|
||||
lineData.value = res;
|
||||
}
|
||||
|
||||
function initData() {
|
||||
// 获取柱状图数据
|
||||
getLineData();
|
||||
// 获取顶部两个统计数据
|
||||
getTopNum();
|
||||
// 概念标签贴标
|
||||
getNewsList();
|
||||
// 热门行业top10
|
||||
getTopIndustry_dFn();
|
||||
// 风口概念池top10
|
||||
getTopConcept_dFn();
|
||||
// 今日精选
|
||||
getNews_cnt_dFn();
|
||||
}
|
||||
|
||||
const type = ref();
|
||||
function onViewAll(type) {
|
||||
type.value = type;
|
||||
if (Session.get("token")) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/realtimeInfo/rankDetail?type=" + type,
|
||||
});
|
||||
} else {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
// const timer = setInterval(() => {
|
||||
// initData();
|
||||
// }, 5000);
|
||||
|
||||
const LoginShow = ref(false);
|
||||
const isLoginStatus = ref();
|
||||
// 关闭弹框
|
||||
const handlePopupClose = () => {
|
||||
LoginShow.value = false;
|
||||
};
|
||||
|
||||
// 登录成功之后的回调
|
||||
const handlePopupSuccessCallback = () => {
|
||||
isLoginStatus.value = true;
|
||||
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/realtimeInfo/rankDetail?type=" + type.value,
|
||||
// });
|
||||
};
|
||||
|
||||
// 登录失败之后的回调
|
||||
const handlePopupErrorCallback = () => {
|
||||
console.log("登录失败");
|
||||
};
|
||||
import { doLogout } from "@/api";
|
||||
function loginOut() {
|
||||
doLogout({
|
||||
financialAccount: Session.get("userPhone"),
|
||||
});
|
||||
Session.clear();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
const lineTabIndex = ref(0);
|
||||
function handleTabClick(index) {
|
||||
lineTabIndex.value = index;
|
||||
getLineDataFn();
|
||||
}
|
||||
|
||||
const lineTopData = ref({});
|
||||
async function getLineDataFn() {
|
||||
if (lineTabIndex.value == 0) {
|
||||
// 行业
|
||||
getTopIndustryPeriod({
|
||||
start_time: dayjs().subtract(7, "day").format("YYYY-MM-DD"),
|
||||
end_time: dayjs().format("YYYY-MM-DD"),
|
||||
limit_num: 10,
|
||||
}).then((res) => {
|
||||
lineTopData.value = res;
|
||||
});
|
||||
} else if (lineTabIndex.value == 1) {
|
||||
// 概念
|
||||
getTopConceptPeriod({
|
||||
start_time: dayjs().subtract(7, "day").format("YYYY-MM-DD"),
|
||||
end_time: dayjs().format("YYYY-MM-DD"),
|
||||
limit_num: 10,
|
||||
}).then((res) => {
|
||||
lineTopData.value = res;
|
||||
});
|
||||
} else if (lineTabIndex.value == 2) {
|
||||
// 媒体
|
||||
getTopSourcePeriod({
|
||||
start_time: dayjs().subtract(7, "day").format("YYYY-MM-DD"),
|
||||
end_time: dayjs().format("YYYY-MM-DD"),
|
||||
limit_num: 10,
|
||||
}).then((res) => {
|
||||
lineTopData.value = res;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function goSreach() {
|
||||
if (Session.get("token")) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/sreachReq/index",
|
||||
});
|
||||
} else {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer);
|
||||
});
|
||||
const { aplus_queue } = window;
|
||||
onMounted(async () => {
|
||||
initData();
|
||||
if (!Session.get("token")) {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
getLineDataFn();
|
||||
|
||||
aplus_queue.push({
|
||||
action: "aplus.sendPV",
|
||||
arguments: [{ is_auto: false }], // 此处上报的数据暂时在后台没有展示
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.all {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f3f5f8;
|
||||
}
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.banner_bk {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.r_banner_title {
|
||||
position: absolute;
|
||||
top: 160rpx;
|
||||
left: 50rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.banner_title {
|
||||
width: 364rpx;
|
||||
height: 134rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: flex;
|
||||
margin-top: -150rpx;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
padding: 0 25rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.r_tag_img {
|
||||
width: calc(50vw - 20rpx);
|
||||
height: 175rpx;
|
||||
position: relative;
|
||||
box-shadow: 0 10rpx 10rpx rgba(80, 80, 80, 0.1);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.tag_bk {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tag_content {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
left: 30rpx;
|
||||
width: 83%;
|
||||
justify-content: space-between;
|
||||
|
||||
.tag_item_left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tag_title {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #222222;
|
||||
line-height: 33rpx;
|
||||
}
|
||||
|
||||
.tag_num {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 38rpx;
|
||||
color: #222222;
|
||||
line-height: 56rpx;
|
||||
}
|
||||
|
||||
.tag_status {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
line-height: 33rpx;
|
||||
margin-top: 15rpx;
|
||||
margin-left: 7rpx;
|
||||
}
|
||||
|
||||
.tag_item_right {
|
||||
width: 70rpx;
|
||||
height: 84rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag_icon {
|
||||
width: 70rpx;
|
||||
height: 84rpx;
|
||||
}
|
||||
|
||||
.view-all {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.logout {
|
||||
// width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: red;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
margin-top: 50rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-left: 20rpx;
|
||||
margin-right: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
border-radius: 10px;
|
||||
|
||||
.tab {
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid #e7e7e7;
|
||||
color: #000;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tab_left {
|
||||
border-start-start-radius: 10px;
|
||||
border-end-start-radius: 10px;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.tab_right {
|
||||
border-start-end-radius: 10px;
|
||||
border-end-end-radius: 10px;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 1px solid #3c74f1;
|
||||
background-color: #3c74f1;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.r_sreach {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 30rpx;
|
||||
// position: absolute;
|
||||
// top: 10px;
|
||||
// left: 0;
|
||||
// z-index: 9999;
|
||||
// background: url("https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/top_bg.png");
|
||||
}
|
||||
|
||||
.logo_text {
|
||||
width: 88rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.sreach {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0rpx 30rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 100rpx;
|
||||
// width: 90vw;
|
||||
height: 63rpx;
|
||||
margin-left: 20rpx;
|
||||
border: 1px solid #e7e7e7;
|
||||
margin-top: 5rpx;
|
||||
// box-shadow: 0 0 10rpx rgba(97, 97, 97, 0.1);
|
||||
}
|
||||
|
||||
.sreach_icon {
|
||||
margin-right: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 35rpx;
|
||||
height: 35rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.sreach_text {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
line-height: 33rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.top_bk {
|
||||
width: 100vw;
|
||||
height: 60px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
<view class="page_top">
|
||||
<view class="r_menu">
|
||||
<image src="@/assets/images/logo.png" class="logo"></image>
|
||||
|
||||
<view class="r_menu_item" @click="tabChange(1)">
|
||||
<text class="menu_item">资讯头条榜</text>
|
||||
<view class="line" v-if="tabIndex == 1"></view>
|
||||
|
|
@ -16,6 +17,11 @@
|
|||
<text class="menu_item">风口概念</text>
|
||||
<view class="line" v-if="tabIndex == 3"></view>
|
||||
</view>
|
||||
|
||||
<view class="r_menu_item" @click="tabChange(4)">
|
||||
<text class="menu_item">编辑精选</text>
|
||||
<view class="line" v-if="tabIndex == 4"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view @click="logout" v-if="Session.get('token')">
|
||||
|
|
@ -25,9 +31,10 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, reactive } from "vue";
|
||||
import { ref, onMounted, onUnmounted, reactive, nextTick } from "vue";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { Session } from "@/utils/storage";
|
||||
import { doLogout } from "@/api";
|
||||
|
||||
const tabIndex = ref(0);
|
||||
function tabChange(type) {
|
||||
|
|
@ -38,13 +45,41 @@ function tabChange(type) {
|
|||
});
|
||||
}
|
||||
|
||||
function logout() {
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
async function logout() {
|
||||
if (Session.get("userPhone")) {
|
||||
await doLogout({
|
||||
financialAccount: Session.get("userPhone"),
|
||||
});
|
||||
}
|
||||
|
||||
Session.clear();
|
||||
window.location.reload();
|
||||
|
||||
// 解构路由参数,排除token
|
||||
const { token, ...otherQuery } = route.query;
|
||||
// 若存在token,替换路由清除参数
|
||||
if (token) {
|
||||
router.replace({
|
||||
path: route.path, // 保持当前路径不变
|
||||
query: otherQuery, // 保留其他参数
|
||||
});
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
onLoad((e) => {
|
||||
if (e.type) tabIndex.value = e.type;
|
||||
|
||||
console.log("🚀 ~ route.query.token:", route.query.token);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ onMounted(async () => {
|
|||
if (route.query.id) {
|
||||
infoId.value = route.query.id;
|
||||
}
|
||||
// 如果过来的链接里有token说明是财保过来的
|
||||
console.log("🚀 ~ route.query:", route.query);
|
||||
|
||||
if (route.query.type) {
|
||||
switch (route.query.type) {
|
||||
|
|
@ -38,11 +40,13 @@ onMounted(async () => {
|
|||
case "3":
|
||||
layoutName.value = "top10";
|
||||
uni.navigateTo({
|
||||
url:
|
||||
"/pages/realtimeInfo/pc/top10?type=" +
|
||||
route.query.type +
|
||||
"&name=" +
|
||||
route.query.name,
|
||||
url: "/pages/realtimeInfo/pc/top10?type=" + route.query.type + "&name=" + route.query.name,
|
||||
});
|
||||
break;
|
||||
case "4":
|
||||
layoutName.value = "rank";
|
||||
uni.navigateTo({
|
||||
url: "/pages/realtimeInfo/pc/rank?type=" + route.query.type,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
<view class="pc_all">
|
||||
<PageTop></PageTop>
|
||||
|
||||
<view
|
||||
class="content"
|
||||
:style="{ filter: Session.get('token') ? '' : 'blur(5px)' }"
|
||||
>
|
||||
<view class="content" :style="{ filter: Session.get('token') ? '' : 'blur(5px)' }">
|
||||
<view class="top" @click="goBack">
|
||||
<image src="@/assets/zixun/icon_fanhui.png" class="icon_back" />
|
||||
<text>返回列表</text>
|
||||
|
|
@ -22,64 +19,42 @@
|
|||
<text class="time"> {{ infoData?.publishTime }}</text>
|
||||
</view>
|
||||
|
||||
<view class="abstract">
|
||||
<view class="abstract" v-if="infoData?.summary">
|
||||
{{ infoData?.summary }}
|
||||
</view>
|
||||
|
||||
<!-- 两个标签 start -->
|
||||
<view class="r_tag_two">
|
||||
<view
|
||||
style="display: flex"
|
||||
v-if="infoData?.conceptLabels && infoData?.conceptLabels.length > 0"
|
||||
>
|
||||
<view style="display: flex" v-if="infoData?.industryLabels && infoData?.industryLabels.length > 0">
|
||||
<text class="tag_title">行业分类:</text>
|
||||
<view class="r_tags">
|
||||
<view
|
||||
class="tag"
|
||||
style="background-color: #fff9ec; color: #ffb100"
|
||||
v-for="(item, index) in infoData?.industryLabels"
|
||||
:key="index"
|
||||
>{{ item }}</view
|
||||
>
|
||||
<view class="tag" style="background-color: #fff9ec; color: #ffb100"
|
||||
v-for="(item, index) in infoData?.industryLabels" :key="index">{{
|
||||
item
|
||||
}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
style="display: flex"
|
||||
v-if="infoData?.industryLabels && infoData?.industryLabels.length > 0"
|
||||
>
|
||||
<view style="display: flex" v-if="infoData?.conceptLabels && infoData?.conceptLabels.length > 0">
|
||||
<text class="tag_title">概念标签:</text>
|
||||
<view class="r_tags">
|
||||
<view
|
||||
class="tag"
|
||||
style="background-color: #f5f8fe; color: #007aff"
|
||||
v-for="(item, index) in infoData?.conceptLabels"
|
||||
:key="index"
|
||||
>{{ item }}</view
|
||||
>
|
||||
<view class="tag" style="background-color: #f5f8fe; color: #007aff"
|
||||
v-for="(item, index) in infoData?.conceptLabels" :key="index">{{
|
||||
item
|
||||
}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 两个标签 end -->
|
||||
|
||||
<view
|
||||
class="text"
|
||||
v-html="infoData.content"
|
||||
style="white-space: pre-wrap"
|
||||
>
|
||||
</view>
|
||||
<view class="text" v-html="infoData.content" style="white-space: pre-wrap"> </view>
|
||||
<!-- <view class="text">
|
||||
<text >{{ infoData.content }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<LoginPopup
|
||||
:show="LoginShow"
|
||||
mode="center"
|
||||
@handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback"
|
||||
@handlePopupErrorCallback="handlePopupErrorCallback"
|
||||
/>
|
||||
<LoginPopup :show="LoginShow" mode="center" @handlePopupClose="handlePopupClose"
|
||||
@handlePopupSuccessCallback="handlePopupSuccessCallback" @handlePopupErrorCallback="handlePopupErrorCallback" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -90,6 +65,7 @@ import { fetchArticleDetail } from "@/api/detail";
|
|||
import LoginPopup from "@/components/loginPopup/index.vue";
|
||||
import { Session } from "@/utils/storage";
|
||||
|
||||
|
||||
function goBack() {
|
||||
// uni.navigateBack();
|
||||
|
||||
|
|
@ -268,6 +244,8 @@ const handlePopupErrorCallback = () => {
|
|||
border-radius: 20rpx;
|
||||
|
||||
margin-top: 50rpx;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.r_tag_two {
|
||||
|
|
|
|||
|
|
@ -2,55 +2,76 @@
|
|||
<view class="pc_all">
|
||||
<PageTop></PageTop>
|
||||
|
||||
<view
|
||||
class="content"
|
||||
:style="{ filter: Session.get('token') ? '' : 'blur(5px)' }"
|
||||
>
|
||||
<view class="content" :style="{ filter: Session.get('token') ? '' : 'blur(5px)' }">
|
||||
<view class="top_title">
|
||||
<text class="pageTitle">资讯头条榜</text>
|
||||
<image src="@/assets/zixun/top20_icon.png" class="title_icon"></image>
|
||||
<text class="pageTitle" v-if="pageType != 4">资讯头条榜</text>
|
||||
<text class="pageTitle" v-if="pageType == 4">编辑精选</text>
|
||||
<image src="@/assets/zixun/top20_icon.png" class="title_icon" v-if="pageType != 4"></image>
|
||||
<!-- <u-input v-if="pageType == 4" placeholder="请输入搜索内容" v-model="form.keyword" prefixIcon="search"
|
||||
@keyup.enter="getNewsList" @blur="getNewsList" prefixIconStyle="font-size: 22px;color: #909399"
|
||||
style="margin-left: 40rpx; margin-top: 5rpx; border-radius: 20rpx">
|
||||
<template #suffix>
|
||||
<u-button @tap="getNewsList" text="搜索" size="mini" class="search_btn"></u-button>
|
||||
</template>
|
||||
</u-input> -->
|
||||
|
||||
<div class="r_input" v-if="pageType == 4">
|
||||
<input
|
||||
v-model="form.keyword"
|
||||
placeholder="请输入搜索内容"
|
||||
class="input"
|
||||
@keyup.enter="getNewsList"
|
||||
@clear="getNewsList"
|
||||
@blur="getNewsList"
|
||||
/>
|
||||
<div class="input_button" @click="getNewsList">搜索</div>
|
||||
</div>
|
||||
</view>
|
||||
|
||||
<view class="line"></view>
|
||||
|
||||
<view class="r_list">
|
||||
<view class="list_item" v-for="(item, index) in newsList" :key="index">
|
||||
<view class="r_list_item_num">
|
||||
<view class="list_item_num num1" v-if="index < 3 && index == 0">{{
|
||||
index + 1
|
||||
}}</view>
|
||||
<view
|
||||
class="list_item_num num2"
|
||||
v-else-if="index < 3 && index == 1"
|
||||
>{{ index + 1 }}</view
|
||||
>
|
||||
<view
|
||||
class="list_item_num num3"
|
||||
v-else-if="index < 3 && index == 2"
|
||||
>{{ index + 1 }}</view
|
||||
>
|
||||
<view class="r_list_item_num" v-if="pageType != 4">
|
||||
<view class="list_item_num num1" v-if="index < 3 && index == 0">{{ index + 1 }}</view>
|
||||
<view class="list_item_num num2" v-else-if="index < 3 && index == 1">{{ index + 1 }}</view>
|
||||
<view class="list_item_num num3" v-else-if="index < 3 && index == 2">{{ index + 1 }}</view>
|
||||
<view class="list_item_num nol_num" v-else>{{ index + 1 }}</view>
|
||||
</view>
|
||||
|
||||
<view class="list_item_content">
|
||||
<text class="item_title" @click="goDetail(item)">{{
|
||||
item.title
|
||||
}}</text>
|
||||
<text class="item_summary">{{ item.summary }}</text>
|
||||
<text class="item_title" @click="goDetail(item)" v-html="item.title"></text>
|
||||
<text class="item_summary" v-if="pageType != 4">{{ item.summary }}</text>
|
||||
<text class="item_summary" v-if="pageType == 4" v-html="item.summary"></text>
|
||||
|
||||
<view class="item_bottom">
|
||||
<view>
|
||||
<text class="time">{{ item.source }}</text>
|
||||
<text class="time" style="margin-left: 30rpx">{{
|
||||
<text class="time" style="margin-left: 30rpx" v-if="pageType != 4">{{
|
||||
dayjs(item.publish_time).format("YYYY-MM-DD HH:MM:ss")
|
||||
}}</text>
|
||||
<text class="time" style="margin-left: 30rpx" v-if="pageType == 4">{{ formatTime(item.time) }}</text>
|
||||
</view>
|
||||
|
||||
<text class="score">{{ item.news_score }}</text>
|
||||
<text class="score" v-if="pageType != 4">{{ item.news_score }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<div
|
||||
style="width: 100%; display: flex; justify-content: center"
|
||||
v-if="pageType == 4 && newsList && newsList.length > 0"
|
||||
>
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
:page-size="form.size"
|
||||
layout="prev, pager, next"
|
||||
:total="form.total"
|
||||
@current-change="currentChange"
|
||||
@size-change="sizeChange"
|
||||
/>
|
||||
</div>
|
||||
</view>
|
||||
<LoginPopup
|
||||
:show="LoginShow"
|
||||
|
|
@ -65,30 +86,135 @@
|
|||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, reactive } from "vue";
|
||||
import PageTop from "@/pages/realtimeInfo/pc/components/PageTop.vue";
|
||||
import { getTopNews } from "@/api/newsInfo";
|
||||
import { getTopNewsDay } from "@/api/newsInfo";
|
||||
import dayjs from "dayjs/esm/index";
|
||||
import LoginPopup from "@/components/loginPopup/index.vue";
|
||||
import { Session } from "@/utils/storage";
|
||||
import { editTopNews } from "@/api/index";
|
||||
import { sendToken } from "@/api/index";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
const pageSizes = ref([10, 20, 30, 40]);
|
||||
const form = reactive({
|
||||
keyword: "",
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 10,
|
||||
});
|
||||
const currentPage = ref(form.page);
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const pageType = ref(route.query.type);
|
||||
const newsList = ref([]);
|
||||
|
||||
// 概念标签贴标
|
||||
function formatTime(timestamp) {
|
||||
const date = new Date(Number(timestamp).toString().length === 10 ? timestamp * 1000 : timestamp);
|
||||
return (
|
||||
[
|
||||
date.getFullYear(),
|
||||
(date.getMonth() + 1).toString().padStart(2, "0"),
|
||||
date.getDate().toString().padStart(2, "0"),
|
||||
].join("-") +
|
||||
" " +
|
||||
[
|
||||
date.getHours().toString().padStart(2, "0"),
|
||||
date.getMinutes().toString().padStart(2, "0"),
|
||||
date.getSeconds().toString().padStart(2, "0"),
|
||||
].join(":")
|
||||
);
|
||||
}
|
||||
|
||||
async function getNewsList() {
|
||||
newsList.value = await getTopNews({});
|
||||
if (pageType.value == 4) {
|
||||
// 编辑精选
|
||||
let { code, data } = await editTopNews({
|
||||
...form,
|
||||
});
|
||||
if (code == 200) {
|
||||
newsList.value = data.list;
|
||||
form.total = data.total;
|
||||
data.list.forEach((item) => {
|
||||
item.summary = item.summary.replace(form.keyword, "<span style='color: #007aff'>" + form.keyword + "</span>");
|
||||
item.title = item.title.replace(form.keyword, "<span style='color: #007aff'>" + form.keyword + "</span>");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 概念标签贴标
|
||||
const res = await getTopNewsDay({});
|
||||
|
||||
newsList.value = res || []
|
||||
}
|
||||
}
|
||||
|
||||
function goDetail(item) {
|
||||
let id = null;
|
||||
if (pageType.value != 4) {
|
||||
id = item.news_id;
|
||||
} else {
|
||||
id = item.id;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: "/pages/realtimeInfo/pc/indexPC?id=" + item.news_id + "&type=1",
|
||||
url: "/pages/realtimeInfo/pc/indexPC?id=" + id + "&type=" + pageType.value,
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async (e) => {
|
||||
function currentChange(page) {
|
||||
form.page = page;
|
||||
getNewsList();
|
||||
}
|
||||
|
||||
if (!Session.get("token")) {
|
||||
LoginShow.value = true;
|
||||
onMounted(async (e) => {
|
||||
console.log("🚀 ~ route.query:", route.query);
|
||||
console.log(`🚀 ~ Session.get("token"):`, Session.get("token"));
|
||||
if (Session.get("token") == "undefined") {
|
||||
Session.remove("token");
|
||||
}
|
||||
if (route.query?.token && (!Session.get("token") || Session.get("token") == "undefined")) {
|
||||
uni.showLoading({
|
||||
title: "加载中",
|
||||
mask: true,
|
||||
});
|
||||
sendToken({
|
||||
token: route.query.token,
|
||||
}).then((res) => {
|
||||
uni.hideLoading();
|
||||
if (res.code == 200) {
|
||||
Session.set("token", res.data.token);
|
||||
Session.set("userPhone", res.data.phone);
|
||||
|
||||
// 解构路由参数,排除token
|
||||
const { token, ...otherQuery } = route.query;
|
||||
// 若存在token,替换路由清除参数
|
||||
if (token) {
|
||||
router.replace({
|
||||
path: route.path, // 保持当前路径不变
|
||||
query: otherQuery, // 保留其他参数
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!Session.get("token") || Session.get("token") == "undefined") {
|
||||
LoginShow.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 解构路由参数,排除token
|
||||
const { token, ...otherQuery } = route.query;
|
||||
// 若存在token,替换路由清除参数
|
||||
if (token) {
|
||||
router.replace({
|
||||
path: route.path, // 保持当前路径不变
|
||||
query: otherQuery, // 保留其他参数
|
||||
});
|
||||
}
|
||||
getNewsList();
|
||||
});
|
||||
|
||||
const LoginShow = ref(false);
|
||||
|
|
@ -170,7 +296,9 @@ const handlePopupErrorCallback = () => {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
color: #ffffff;
|
||||
|
|
@ -186,13 +314,16 @@ const handlePopupErrorCallback = () => {
|
|||
background: linear-gradient(169deg, #a9c3e3 0%, #92b2e0 100%);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.num3 {
|
||||
background: linear-gradient(169deg, #f2996e 0%, #f77741 100%);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.nol_num {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
color: #93a2b3;
|
||||
|
|
@ -211,8 +342,11 @@ const handlePopupErrorCallback = () => {
|
|||
.item_title:hover {
|
||||
color: #057cff;
|
||||
}
|
||||
|
||||
.item_title {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
color: #1a1a1a;
|
||||
|
|
@ -220,11 +354,30 @@ const handlePopupErrorCallback = () => {
|
|||
}
|
||||
|
||||
.item_summary {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
margin-top: 20rpx;
|
||||
|
||||
/* 必须:限制内容不溢出容器 */
|
||||
overflow: hidden;
|
||||
/* 必须:超出部分显示省略号 */
|
||||
text-overflow: ellipsis;
|
||||
/* 必须:将元素设置为webkit弹性盒模型(用于控制行数) */
|
||||
display: -webkit-box;
|
||||
/* 关键:限制显示的行数(这里设为2行) */
|
||||
-webkit-line-clamp: 2;
|
||||
/* 必须:设置弹性盒的排列方向为垂直(让文本换行) */
|
||||
-webkit-box-orient: vertical;
|
||||
|
||||
/* 可选:调整行高和容器高度,确保刚好容纳2行文本 */
|
||||
line-height: 1.5;
|
||||
/* 行高 */
|
||||
max-height: 3em;
|
||||
/* 2行总高度 = 行高 × 2(1.5×2=3) */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,8 +386,11 @@ const handlePopupErrorCallback = () => {
|
|||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.time {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #919191;
|
||||
|
|
@ -244,7 +400,9 @@ const handlePopupErrorCallback = () => {
|
|||
}
|
||||
|
||||
.score {
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
color: #ffa800;
|
||||
|
|
@ -253,4 +411,75 @@ const handlePopupErrorCallback = () => {
|
|||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.search_btn {
|
||||
border: none;
|
||||
display: flex;
|
||||
width: 56px;
|
||||
height: 44px;
|
||||
padding: 8px 15px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 8px;
|
||||
background: #0062d9;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.input {
|
||||
border: none;
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.input_button {
|
||||
display: flex;
|
||||
width: 140px;
|
||||
height: 100%;
|
||||
// padding: 8px 15px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 0 10px 10px 0;
|
||||
background: #007aff;
|
||||
|
||||
color: white;
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
color: #ffffff;
|
||||
line-height: 25px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.r_input {
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #e3e3e3;
|
||||
flex: 1;
|
||||
height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 30px;
|
||||
margin-top: 3px;
|
||||
|
||||
:deep(.el-input__inner::placeholder) {
|
||||
color: #ccced3;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
box-shadow: 0 0 0 #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,12 @@
|
|||
<template>
|
||||
<view class="all">
|
||||
<PageHeaderView
|
||||
:title="type == 0 ? '热门行业池Top10' : '风口概念池Top10'"
|
||||
></PageHeaderView>
|
||||
<PageHeaderView :title="type == 0 ? '热门行业池Top10' : '风口概念池Top10'"></PageHeaderView>
|
||||
|
||||
<!-- 类目标签 start -->
|
||||
<view class="page_content">
|
||||
<view class="tag_list">
|
||||
<view
|
||||
:class="['tag_item', clickTagIndex == index ? tagClickedClass : '']"
|
||||
class="tag_item"
|
||||
v-for="(item, index) in tagList"
|
||||
:key="index"
|
||||
@click="clickTag(index)"
|
||||
>
|
||||
<view :class="['tag_item', clickTagIndex == index ? tagClickedClass : '']" class="tag_item"
|
||||
v-for="(item, index) in tagList" :key="index" @click="clickTag(index)">
|
||||
{{ item.content }}
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -22,12 +15,7 @@
|
|||
|
||||
<!-- 列表 start -->
|
||||
<view class="list">
|
||||
<view
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
class="news-item"
|
||||
@click="goDetail(item)"
|
||||
>
|
||||
<view v-for="(item, index) in list" :key="index" class="news-item" @click="goDetail(item)">
|
||||
<view class="news-content">
|
||||
<text class="news-title">{{ item.title }}</text>
|
||||
<text class="news-desc">{{ item.summary }}</text>
|
||||
|
|
@ -165,6 +153,12 @@ onMounted(async () => {
|
|||
}
|
||||
|
||||
getListByTagFn();
|
||||
|
||||
const { aplus_queue } = window;
|
||||
aplus_queue.push({
|
||||
action: 'aplus.sendPV',
|
||||
arguments: [{ is_auto: false }] // 此处上报的数据暂时在后台没有展示
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -254,11 +248,16 @@ onMounted(async () => {
|
|||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
display: -webkit-box; /* 设置为WebKit内核的弹性盒子模型 */
|
||||
-webkit-box-orient: vertical; /* 垂直排列 */
|
||||
-webkit-line-clamp: 2; /* 限制显示三行 */
|
||||
overflow: hidden; /* 隐藏超出范围的内容 */
|
||||
text-overflow: ellipsis; /* 使用省略号 */
|
||||
display: -webkit-box;
|
||||
/* 设置为WebKit内核的弹性盒子模型 */
|
||||
-webkit-box-orient: vertical;
|
||||
/* 垂直排列 */
|
||||
-webkit-line-clamp: 2;
|
||||
/* 限制显示三行 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出范围的内容 */
|
||||
text-overflow: ellipsis;
|
||||
/* 使用省略号 */
|
||||
}
|
||||
|
||||
.news-meta {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
<template>
|
||||
<!-- 顶部 banner 区域 -->
|
||||
<view class="all">
|
||||
<view class="tabbar">
|
||||
<view class="tabbar_item" @click="tabChange(0)">
|
||||
<image
|
||||
v-if="tabIndex == 1"
|
||||
src=" @/assets/zixun/home_icon_normal.png"
|
||||
class="tabbar_img"
|
||||
/>
|
||||
<image
|
||||
v-if="tabIndex == 0"
|
||||
src=" @/assets/zixun/home_icon_press.png"
|
||||
class="tabbar_img"
|
||||
/>
|
||||
<text
|
||||
class="tabbar_title"
|
||||
:style="{ color: tabIndex == 0 ? '#3F80FA' : '#666666' }"
|
||||
>首页</text
|
||||
>
|
||||
</view>
|
||||
|
||||
<view class="tabbar_item" @click="tabChange(1)">
|
||||
<image
|
||||
v-if="tabIndex == 0"
|
||||
src=" @/assets/zixun/all_icon_normal.png"
|
||||
class="tabbar_img"
|
||||
/>
|
||||
<image
|
||||
v-if="tabIndex == 1"
|
||||
src=" @/assets/zixun/all_icon_press.png"
|
||||
class="tabbar_img"
|
||||
/>
|
||||
<text
|
||||
class="tabbar_title"
|
||||
:style="{ color: tabIndex == 1 ? '#3F80FA' : '#666666' }"
|
||||
>全部</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, reactive } from "vue";
|
||||
|
||||
const tabIndex = ref(0);
|
||||
function tabChange(index) {
|
||||
tabIndex.value = index;
|
||||
}
|
||||
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tabbar {
|
||||
display: flex;
|
||||
height: 150rpx;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -2rpx 10rpx rgba(128, 128, 128, 0.2);
|
||||
width: 100vw;
|
||||
|
||||
.tabbar_item {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.tabbar_img {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
.tabbar_title {
|
||||
display: flex;
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 20rpx;
|
||||
color: #666666;
|
||||
line-height: 28rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||