appsnbcbweicheng 1.2.29 → 1.2.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appsnbcbweicheng",
3
- "version": "1.2.29",
3
+ "version": "1.2.30",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -0,0 +1,180 @@
1
+ /**
2
+ * 事件渠道配置相关接口
3
+ * 开发环境通过 vue.config.js 代理 /api -> 后端
4
+ */
5
+
6
+ const MOCK_ASSET_TREE = [
7
+ {
8
+ value: 'equity',
9
+ label: '权益类',
10
+ children: [
11
+ { value: 'hs300', label: '沪深300' },
12
+ { value: 'zz500', label: '中证500' },
13
+ ],
14
+ },
15
+ {
16
+ value: 'bond',
17
+ label: '固收类',
18
+ children: [
19
+ { value: 'gov_bond', label: '国债指数' },
20
+ { value: 'corp_bond', label: '企业债指数' },
21
+ ],
22
+ },
23
+ {
24
+ value: 'commodity',
25
+ label: '商品类',
26
+ children: [
27
+ { value: 'gold', label: '黄金' },
28
+ { value: 'oil', label: '原油' },
29
+ ],
30
+ },
31
+ ]
32
+
33
+ const MOCK_CHANNELS = [
34
+ { value: 'app', label: 'APP' },
35
+ { value: 'wechat', label: '微信' },
36
+ { value: 'web', label: '官网' },
37
+ { value: 'offline', label: '线下' },
38
+ ]
39
+
40
+ const MOCK_LIST = [
41
+ {
42
+ id: 1,
43
+ assetCategory: '权益类',
44
+ assetCategoryCode: 'equity',
45
+ assetName: '沪深300',
46
+ assetNameCode: 'hs300',
47
+ channels: { app: true, wechat: true, web: false, offline: true },
48
+ },
49
+ {
50
+ id: 2,
51
+ assetCategory: '权益类',
52
+ assetCategoryCode: 'equity',
53
+ assetName: '中证500',
54
+ assetNameCode: 'zz500',
55
+ channels: { app: false, wechat: true, web: true, offline: false },
56
+ },
57
+ {
58
+ id: 3,
59
+ assetCategory: '固收类',
60
+ assetCategoryCode: 'bond',
61
+ assetName: '国债指数',
62
+ assetNameCode: 'gov_bond',
63
+ channels: { app: true, wechat: false, web: true, offline: false },
64
+ },
65
+ {
66
+ id: 4,
67
+ assetCategory: '固收类',
68
+ assetCategoryCode: 'bond',
69
+ assetName: '企业债指数',
70
+ assetNameCode: 'corp_bond',
71
+ channels: { app: true, wechat: true, web: true, offline: true },
72
+ },
73
+ {
74
+ id: 5,
75
+ assetCategory: '商品类',
76
+ assetCategoryCode: 'commodity',
77
+ assetName: '黄金',
78
+ assetNameCode: 'gold',
79
+ channels: { app: true, wechat: true, web: false, offline: false },
80
+ },
81
+ {
82
+ id: 6,
83
+ assetCategory: '商品类',
84
+ assetCategoryCode: 'commodity',
85
+ assetName: '原油',
86
+ assetNameCode: 'oil',
87
+ channels: { app: false, wechat: false, web: true, offline: true },
88
+ },
89
+ ]
90
+
91
+ async function request(url, options = {}) {
92
+ const res = await fetch(url, {
93
+ headers: { 'Content-Type': 'application/json', ...options.headers },
94
+ ...options,
95
+ })
96
+ if (!res.ok) {
97
+ throw new Error(`HTTP ${res.status}`)
98
+ }
99
+ return res.json()
100
+ }
101
+
102
+ function filterMockList(params) {
103
+ let list = [...MOCK_LIST]
104
+ if (params.assetCategoryCode) {
105
+ list = list.filter(item => item.assetCategoryCode === params.assetCategoryCode)
106
+ }
107
+ if (params.assetNameCode) {
108
+ list = list.filter(item => item.assetNameCode === params.assetNameCode)
109
+ }
110
+ if (params.channelCode) {
111
+ list = list.filter(item => item.channels && item.channels[params.channelCode])
112
+ }
113
+ return list
114
+ }
115
+
116
+ /** 资产类别 / 名称二级树 */
117
+ export async function fetchAssetTree() {
118
+ try {
119
+ const data = await request('/api/event-config/asset-tree')
120
+ return data.data || data
121
+ } catch {
122
+ return MOCK_ASSET_TREE
123
+ }
124
+ }
125
+
126
+ /** 渠道选项列表 */
127
+ export async function fetchChannels() {
128
+ try {
129
+ const data = await request('/api/event-config/channels')
130
+ return data.data || data
131
+ } catch {
132
+ return MOCK_CHANNELS
133
+ }
134
+ }
135
+
136
+ /** 分页查询列表 */
137
+ export async function fetchEventConfigList(params) {
138
+ const { page = 1, pageSize = 10, assetCategoryCode, assetNameCode, channelCode } = params
139
+ try {
140
+ const qs = new URLSearchParams({
141
+ page: String(page),
142
+ pageSize: String(pageSize),
143
+ ...(assetCategoryCode && { assetCategoryCode }),
144
+ ...(assetNameCode && { assetNameCode }),
145
+ ...(channelCode && { channelCode }),
146
+ })
147
+ const data = await request(`/api/event-config/list?${qs}`)
148
+ return {
149
+ list: data.data?.list || data.list || [],
150
+ total: data.data?.total ?? data.total ?? 0,
151
+ }
152
+ } catch {
153
+ const filtered = filterMockList({ assetCategoryCode, assetNameCode, channelCode })
154
+ const start = (page - 1) * pageSize
155
+ return {
156
+ list: filtered.slice(start, start + pageSize),
157
+ total: filtered.length,
158
+ }
159
+ }
160
+ }
161
+
162
+ /** 更新某条资产的渠道配置 */
163
+ export async function updateEventConfigChannels(payload) {
164
+ try {
165
+ const data = await request('/api/event-config/update', {
166
+ method: 'POST',
167
+ body: JSON.stringify(payload),
168
+ })
169
+ return data
170
+ } catch {
171
+ const row = MOCK_LIST.find(item => item.id === payload.id)
172
+ if (row) {
173
+ const channelCodes = payload.channelCodes || []
174
+ MOCK_CHANNELS.forEach(ch => {
175
+ row.channels[ch.value] = channelCodes.includes(ch.value)
176
+ })
177
+ }
178
+ return { success: true }
179
+ }
180
+ }
@@ -0,0 +1,269 @@
1
+ <template>
2
+ <div class="event-config">
3
+ <!-- 查询筛选 -->
4
+ <el-card class="filter-card" shadow="never">
5
+ <el-form :inline="true" :model="queryParams" size="small" label-width="80px">
6
+ <el-form-item label="资产类别">
7
+ <el-select v-model="queryParams.assetCategoryCode" placeholder="请选择资产类别" clearable
8
+ style="width: 180px" @change="onCategoryChange">
9
+ <el-option v-for="item in assetTree" :key="item.value" :label="item.label"
10
+ :value="item.value" />
11
+ </el-select>
12
+ </el-form-item>
13
+ <el-form-item label="资产名称">
14
+ <el-select v-model="queryParams.assetNameCode" placeholder="请先选择资产类别" clearable
15
+ :disabled="!queryParams.assetCategoryCode" style="width: 180px">
16
+ <el-option v-for="item in assetNameOptions" :key="item.value" :label="item.label"
17
+ :value="item.value" />
18
+ </el-select>
19
+ </el-form-item>
20
+ <el-form-item label="渠道">
21
+ <el-select v-model="queryParams.channelCode" placeholder="请选择渠道" clearable style="width: 160px">
22
+ <el-option v-for="item in channelOptions" :key="item.value" :label="item.label"
23
+ :value="item.value" />
24
+ </el-select>
25
+ </el-form-item>
26
+ <el-form-item>
27
+ <el-button type="primary" @click="handleSearch">查询</el-button>
28
+ <el-button @click="handleReset">重置</el-button>
29
+ </el-form-item>
30
+ </el-form>
31
+ </el-card>
32
+
33
+ <!-- 列表 -->
34
+ <el-card class="table-card" shadow="never">
35
+ <el-table :data="tableData" border v-loading="loading" style="width: 100%">
36
+ <el-table-column type="index" label="序号" width="60" fixed="left" :index="indexMethod" />
37
+ <el-table-column prop="assetCategory" label="资产类别" min-width="120" fixed="left" />
38
+ <el-table-column prop="assetName" label="资产名称" min-width="140" fixed="left" />
39
+
40
+ <el-table-column v-for="ch in channelOptions" :key="ch.value" :label="ch.label" min-width="90"
41
+ align="center">
42
+ <template slot-scope="{ row }">
43
+ <i v-if="isChannelEnabled(row, ch.value)"
44
+ class="el-icon-check channel-icon channel-icon--yes" />
45
+ <i v-else class="el-icon-close channel-icon channel-icon--no" />
46
+ </template>
47
+ </el-table-column>
48
+
49
+ <el-table-column label="操作" width="80" fixed="right" align="center">
50
+ <template slot-scope="{ row }">
51
+ <el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>
52
+ </template>
53
+ </el-table-column>
54
+ </el-table>
55
+
56
+ <div class="pagination-container">
57
+ <el-pagination background :current-page="pagination.page" :page-sizes="[10, 20, 50, 100]"
58
+ :page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper"
59
+ :total="pagination.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
60
+ </div>
61
+ </el-card>
62
+
63
+ <!-- 修改渠道 -->
64
+ <el-dialog title="修改渠道" :visible.sync="editDialogVisible" width="480px" :close-on-click-modal="false"
65
+ @close="resetEditForm">
66
+ <el-form ref="editForm" :model="editForm" label-width="90px" size="small">
67
+ <el-form-item label="资产类别">
68
+ <el-input v-model="editForm.assetCategory" disabled />
69
+ </el-form-item>
70
+ <el-form-item label="资产名称">
71
+ <el-input v-model="editForm.assetName" disabled />
72
+ </el-form-item>
73
+ <el-form-item label="渠道" prop="channelCodes">
74
+ <el-select v-model="editForm.channelCodes" multiple placeholder="请选择渠道" style="width: 100%">
75
+ <el-option v-for="item in channelOptions" :key="item.value" :label="item.label"
76
+ :value="item.value" />
77
+ </el-select>
78
+ </el-form-item>
79
+ </el-form>
80
+ <span slot="footer">
81
+ <el-button @click="editDialogVisible = false">取 消</el-button>
82
+ <el-button type="primary" :loading="submitLoading" @click="handleSubmit">确 定</el-button>
83
+ </span>
84
+ </el-dialog>
85
+ </div>
86
+ </template>
87
+
88
+ <script>
89
+ import {
90
+ fetchAssetTree,
91
+ fetchChannels,
92
+ fetchEventConfigList,
93
+ updateEventConfigChannels,
94
+ } from '@/api/eventConfig'
95
+
96
+ export default {
97
+ name: 'EventConfig',
98
+ data() {
99
+ return {
100
+ queryParams: {
101
+ assetCategoryCode: '',
102
+ assetNameCode: '',
103
+ channelCode: '',
104
+ },
105
+ assetTree: [],
106
+ channelOptions: [],
107
+ tableData: [],
108
+ loading: false,
109
+ pagination: {
110
+ page: 1,
111
+ pageSize: 10,
112
+ total: 0,
113
+ },
114
+ editDialogVisible: false,
115
+ submitLoading: false,
116
+ editForm: {
117
+ id: null,
118
+ assetCategory: '',
119
+ assetName: '',
120
+ channelCodes: [],
121
+ },
122
+ }
123
+ },
124
+ computed: {
125
+ assetNameOptions() {
126
+ if (!this.queryParams.assetCategoryCode) return []
127
+ const category = this.assetTree.find(
128
+ item => item.value === this.queryParams.assetCategoryCode,
129
+ )
130
+ return category && category.children ? category.children : []
131
+ },
132
+ },
133
+ mounted() {
134
+ this.initOptions()
135
+ this.loadTable()
136
+ },
137
+ methods: {
138
+ async initOptions() {
139
+ const [tree, channels] = await Promise.all([fetchAssetTree(), fetchChannels()])
140
+ this.assetTree = tree
141
+ this.channelOptions = channels
142
+ },
143
+
144
+ indexMethod(index) {
145
+ return (this.pagination.page - 1) * this.pagination.pageSize + index + 1
146
+ },
147
+
148
+ onCategoryChange() {
149
+ this.queryParams.assetNameCode = ''
150
+ },
151
+
152
+ isChannelEnabled(row, channelCode) {
153
+ return row.channels && row.channels[channelCode] === true
154
+ },
155
+
156
+ async loadTable() {
157
+ this.loading = true
158
+ try {
159
+ const { list, total } = await fetchEventConfigList({
160
+ page: this.pagination.page,
161
+ pageSize: this.pagination.pageSize,
162
+ assetCategoryCode: this.queryParams.assetCategoryCode || undefined,
163
+ assetNameCode: this.queryParams.assetNameCode || undefined,
164
+ channelCode: this.queryParams.channelCode || undefined,
165
+ })
166
+ this.tableData = list
167
+ this.pagination.total = total
168
+ } finally {
169
+ this.loading = false
170
+ }
171
+ },
172
+
173
+ handleSearch() {
174
+ this.pagination.page = 1
175
+ this.loadTable()
176
+ },
177
+
178
+ handleReset() {
179
+ this.queryParams = {
180
+ assetCategoryCode: '',
181
+ assetNameCode: '',
182
+ channelCode: '',
183
+ }
184
+ this.pagination.page = 1
185
+ this.loadTable()
186
+ },
187
+
188
+ handleSizeChange(size) {
189
+ this.pagination.pageSize = size
190
+ this.pagination.page = 1
191
+ this.loadTable()
192
+ },
193
+
194
+ handleCurrentChange(page) {
195
+ this.pagination.page = page
196
+ this.loadTable()
197
+ },
198
+
199
+ handleEdit(row) {
200
+ const channelCodes = this.channelOptions
201
+ .filter(ch => this.isChannelEnabled(row, ch.value))
202
+ .map(ch => ch.value)
203
+ this.editForm = {
204
+ id: row.id,
205
+ assetCategory: row.assetCategory,
206
+ assetName: row.assetName,
207
+ channelCodes: [...channelCodes],
208
+ }
209
+ this.editDialogVisible = true
210
+ },
211
+
212
+ resetEditForm() {
213
+ this.editForm = {
214
+ id: null,
215
+ assetCategory: '',
216
+ assetName: '',
217
+ channelCodes: [],
218
+ }
219
+ },
220
+
221
+ async handleSubmit() {
222
+ this.submitLoading = true
223
+ try {
224
+ await updateEventConfigChannels({
225
+ id: this.editForm.id,
226
+ channelCodes: this.editForm.channelCodes,
227
+ })
228
+ this.$message.success('保存成功')
229
+ this.editDialogVisible = false
230
+ this.loadTable()
231
+ } catch (e) {
232
+ this.$message.error('保存失败,请稍后重试')
233
+ } finally {
234
+ this.submitLoading = false
235
+ }
236
+ },
237
+ },
238
+ }
239
+ </script>
240
+
241
+ <style scoped>
242
+ .event-config {
243
+ max-width: 1200px;
244
+ margin: 0 auto;
245
+ }
246
+
247
+ .filter-card,
248
+ .table-card {
249
+ margin-bottom: 16px;
250
+ }
251
+
252
+ .pagination-container {
253
+ margin-top: 16px;
254
+ text-align: right;
255
+ }
256
+
257
+ .channel-icon {
258
+ font-size: 18px;
259
+ font-weight: bold;
260
+ }
261
+
262
+ .channel-icon--yes {
263
+ color: #67c23a;
264
+ }
265
+
266
+ .channel-icon--no {
267
+ color: #f56c6c;
268
+ }
269
+ </style>
package/readme.md CHANGED
@@ -1,3 +1,4 @@
1
+ 1.2.30 时间渠道配置
1
2
  1.2.29 优化双击
2
3
  1.2.28 双击复制
3
4
  1.2.27 日历编辑
@@ -1,43 +0,0 @@
1
- ; ===== 记录鼠标按下位置 =====
2
- ~LButton::
3
- MouseGetPos, startX, startY
4
- return
5
-
6
- ; ===== 鼠标松开 =====
7
- ~LButton Up::
8
- MouseGetPos, endX, endY
9
-
10
- ; 排除终端
11
- WinGetClass, class, A
12
- if (class = "ConsoleWindowClass") ; cmd
13
- return
14
-
15
- if (class = "CASCADIA_HOSTING_WINDOW_CLASS") ; Windows Terminal
16
- return
17
-
18
- if (class = "VirtualConsoleClass")
19
- return
20
-
21
- ; ===== 双击 =====
22
- isDoubleClick := (A_PriorHotkey = "~LButton Up" && A_TimeSincePriorHotkey < 300)
23
-
24
- ; ===== 拖动 =====
25
- isDrag := (Abs(endX - startX) > 5 || Abs(endY - startY) > 5)
26
-
27
- if (!isDoubleClick && !isDrag)
28
- return
29
-
30
- Sleep 100
31
-
32
- oldClipboard := ClipboardAll
33
- Clipboard := ""
34
-
35
- Send ^c
36
- ClipWait, 0.2
37
-
38
- if (ErrorLevel || Clipboard = "")
39
- {
40
- Clipboard := oldClipboard
41
- }
42
-
43
- return