From 37486e9d5beb6112c072625e74d3782f8bed7a01 Mon Sep 17 00:00:00 2001 From: zxl <763096477@qq.com> Date: 星期三, 27 八月 2025 00:34:45 +0800 Subject: [PATCH] 导出以及页面 --- manager/src/views/prize-grant-record/index.vue | 406 +++++++++++++++++++++++++ manager/src/api/prize-record.js | 13 manager/src/views/prize-record/index.vue | 518 ++++++++++++++++++++++++++++++++ manager/src/api/prize-grant-record.js | 13 4 files changed, 950 insertions(+), 0 deletions(-) diff --git a/manager/src/api/prize-grant-record.js b/manager/src/api/prize-grant-record.js new file mode 100644 index 0000000..025f219 --- /dev/null +++ b/manager/src/api/prize-grant-record.js @@ -0,0 +1,13 @@ +import service, {getRequest} from "../libs/axios"; + +export const queryExport = (params) =>{ + return getRequest("/lmk/prizeGrantRecord/queryExport", params,'blob') +} + +export const getPage = (params) =>{ + return service({ + url: "/lmk/prizeGrantRecord", + method: "GET", + params: params + }) +} diff --git a/manager/src/api/prize-record.js b/manager/src/api/prize-record.js new file mode 100644 index 0000000..f0b8207 --- /dev/null +++ b/manager/src/api/prize-record.js @@ -0,0 +1,13 @@ +import service, {getRequest} from "../libs/axios"; + +export const queryExport = (params) =>{ + return getRequest("/lmk/prizeRecord/queryExport", params,'blob') +} + +export const getPage = (params) =>{ + return service({ + url: "/lmk/prizeRecord", + method: "GET", + params: params + }) +} diff --git a/manager/src/views/prize-grant-record/index.vue b/manager/src/views/prize-grant-record/index.vue new file mode 100644 index 0000000..505710b --- /dev/null +++ b/manager/src/views/prize-grant-record/index.vue @@ -0,0 +1,406 @@ +<template> + <div> + <Card> + <!-- 鎼滅储琛ㄥ崟 --> + <Form + ref="searchForm" + @keydown.enter.native="handleSearch" + :model="searchForm" + inline + :label-width="80" + class="search-form" + > + <FormItem label="鐢ㄦ埛鏄电О" prop="nickName"> + <Input + type="text" + v-model="searchForm.nickName" + placeholder="璇疯緭鍏ョ敤鎴锋樀绉�" + clearable + @on-clear="handleSearch" + style="width: 180px" + /> + </FormItem> + <FormItem label="娲诲姩鍚嶇О" prop="activityName"> + <Input + type="text" + v-model="searchForm.activityName" + placeholder="璇疯緭鍏ユ椿鍔ㄥ悕绉�" + clearable + @on-clear="handleSearch" + style="width: 180px" + /> + </FormItem> + <FormItem label="涓鐘舵��" prop="beginTime"> + <Select + v-model="searchForm.grantStatus" + placeholder="璇烽�夋嫨涓鐘舵��" + style="width: 180px" + clearable + @on-clear="handleSearch" + @on-change="handleSearch" + > + <Option + v-for="item in typeSelect" + :value="item.value" + :key="item.id" + > + {{ item.label }} + </Option> + </Select> + </FormItem> + + <Button + @click="handleSearch" + type="primary" + icon="ios-search" + class="search-btn" + >鎼滅储</Button> + <Button + @click="resetSearch" + icon="md-refresh" + style="margin-left: 8px" + >閲嶇疆</Button> + <Button + @click="queryExport" + class="search-btn" + type="primary" + >瀵煎嚭</Button + > + </Form> + + + <!-- 娲诲姩琛ㄦ牸 --> + <Table + :loading="loading" + border + :columns="columns" + :data="data" + ref="table" + class="table" + > + <!-- 鎿嶄綔鎸夐挳鎻掓Ы --> + <template slot-scope="{ row }" slot="action"> + <div class="action-btns"> + <Button + type="info" + size="small" + @click="detail(row)" + >璇︽儏</Button> + </div> + </template> + </Table> + + <!-- 鍒嗛〉 --> + <Row type="flex" justify="end" class="page-footer"> + <Page + :current="searchForm.pageNumber" + :total="total" + :page-size="searchForm.pageSize" + @on-change="changePage" + @on-page-size-change="changePageSize" + :page-size-opts="[10, 20, 50]" + size="small" + show-total + show-elevator + show-sizer + ></Page> + </Row> + <!-- 璇︽儏--> + <Modal + v-model="infoModalShow" + title="娲诲姩璇︽儏" + @on-cancel="infoModelClose" + width="800" + :mask-closable="false" + > + <div class="detail-container"> + <Row :gutter="16"> + <Col span="12"> + <div class="detail-item"> + <label>娲诲姩鍚嶇О锛�</label> + <span>{{ detailData.activityName }}</span> + </div> + </Col> + <Col span="12"> + <div class="detail-item"> + <label>鐢ㄦ埛鏄电О锛�</label> + <span>{{ detailData.nickName}}</span> + </div> + </Col> + <Col span="12"> + <div class="detail-item"> + <label>濂栧搧鍚嶇О锛�</label> + <span>{{ detailData.prizeName }}</span> + </div> + </Col> + <Col span="12"> + <div class="detail-item"> + <label>濂栧搧鍐呭锛�</label> + <span>{{ detailData.prizeContent }}</span> + </div> + </Col> + <Col span="12"> + <div class="detail-item"> + <label>鎻忚堪锛�</label> + <span>{{ detailData.desc }}</span> + </div> + </Col> + <Col span="24"> + <div class="detail-item"> + <label>鍙戞斁鐘舵�侊細</label> + <Tag :color="detailData.grantStatus === 'SUCCESS' ? 'green' : 'red'"> + {{ detailData.grantStatus === 'SUCCESS' ? '鍙戞斁鎴愬姛' : '鍙戞斁澶辫触' }} + </Tag> + </div> + </Col> + + </Row> + </div> + + </Modal> + + </Card> + </div> +</template> + +<script> +import { + getPage, + queryExport +} from '@/api/prize-grant-record.js' + +export default { + name: "prizeGrantRecord", + + data() { + return { + infoModalShow:false, + detailData: {}, + modelShow:false, + modelTitle:'', + loading:false, + columns:[ + { + title: '鐢ㄦ埛鏄电О', + key: 'nickName', + minWidth: 100, + }, + { + title: '娲诲姩鍚嶇О', + key: 'activityName', + minWidth: 100, + }, + { + title: '濂栧搧鍚嶇О', + key: 'prizeName', + minWidth: 100, + }, + { + title: '鎻忚堪', + key: 'des', + minWidth: 100, + }, + { + title: '鍙戞斁鐘舵��', + key: 'grantStatus', + minWidth: 100, + render: (h, params) => { + return h('Tag', { + props: { + color: params.row.grantStatus === 'SUCCESS' ? 'green' : 'red' + }}, params.row.grantStatus === 'SUCCESS' ? '鍙戞斁鎴愬姛' : '鍙戞斁澶辫触') + } + }, + { + title: '鎿嶄綔', + slot: 'action', + width: 280, + align: 'center', + fixed: 'right' + }, + ], + data:[], + total:0, + searchForm:{ + pageSize:10, + pageNumber:1, + nickName:'', + activityName:'', + grantStatus:'' + }, + typeSelect:[ + {id: 1, value: 'SUCCESS', label: '鍙戞斁鎴愬姛'}, + {id: 2, value: 'FAILED', label: '鍙戞斁澶辫触'} + ], + activityCover:null, + + + } + }, + // 鍦ㄧ粍浠跺垱寤哄墠娉ㄥ唽 + beforeCreate() { + + }, + mounted() { + this.init(); + }, + methods: { + queryExport(){ + queryExport(this.searchForm).then(res =>{ + const blob = new Blob([res], { + type: "application/vnd.ms-excel;charset=utf-8", + }); + //瀵逛簬<a>鏍囩锛屽彧鏈� Firefox 鍜� Chrome锛堝唴鏍革級 鏀寔 download 灞炴�� + //IE10浠ヤ笂鏀寔blob浣嗘槸渚濈劧涓嶆敮鎸乨ownload + if ("download" in document.createElement("a")) { + //鏀寔a鏍囩download鐨勬祻瑙堝櫒 + const link = document.createElement("a"); //鍒涘缓a鏍囩 + link.download = "鐢ㄦ埛鎶藉璁板綍.xlsx"; //a鏍囩娣诲姞灞炴�� + link.style.display = "none"; + link.href = URL.createObjectURL(blob); + document.body.appendChild(link); + link.click(); //鎵ц涓嬭浇 + URL.revokeObjectURL(link.href); //閲婃斁url + document.body.removeChild(link); //閲婃斁鏍囩 + } else { + navigator.msSaveBlob(blob, fileName); + } + }) + + + }, + // 鏍煎紡鍖栧鍝佺被鍨� + replaceText(type) { + if (type === "coupon") { + return "浼樻儬鍒�"; + } + return type; // 濡傛灉涓嶆槸鐩爣璇嶏紝杩斿洖鍘熸枃鏈� + }, + resetSearch(){ + this.$refs.searchForm.resetFields() + this.searchForm.pageNumber = 1 + this.getPage() + }, + infoModelClose(){ + this.infoModalShow = false; + }, + + getPage(){ + this.loading = true; + getPage(this.searchForm).then(res =>{ + this.loading = false; + if (res.code === 200){ + this.data = res.data; + this.total = res.total; + }else { + this.$Message.error(res.msg) + } + }) + }, + detail(row){ + this.infoModalShow = true; + this.detailData = {...row}; + + + }, + + handleSearch(type,value){ + if (type === 'beginTime') { + this.searchForm.beginTime = value + } else if (type === 'endTime') { + this.searchForm.endTime = value + } + this.getPage() + }, + + // 鍒濆鍖栨暟鎹� + init() { + this.getPage() + }, + changePage(){ + this.searchForm.pageNumber = 1 + this.searchForm.pageSize = pageSize + this.getPage() + }, + changePageSize(){ + this.searchForm.pageNumber = page + this.getPage() + }, + + }, +} +</script> + +<style lang="scss" scoped> +.search-form { + padding: 16px; + background: #f8f8f9; + border-radius: 4px; + margin-bottom: 16px; + + .ivu-form-item { + margin-bottom: 16px; + margin-right: 16px; + } + + .search-btn { + margin-left: 8px; + } +} +.table { + .thumbnail { + max-width: 100%; + max-height: 100%; + object-fit: contain; + cursor: pointer; + transition: all 0.3s; + + &:hover { + transform: scale(1.05); + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); + } + } + .action-btns { + display: flex; + flex-wrap: wrap; + justify-content: center; + + .ivu-btn { + margin: 4px; + font-size: 12px; + padding: 2px 6px; + min-width: 60px; + } + } +} +.detail-container { + padding: 16px; +} + +.detail-item { + margin-bottom: 16px; + line-height: 1.5; +} + +.detail-item label { + display: inline-block; + width: 120px; + font-weight: bold; + color: #515a6e; + vertical-align: top; +} + +.detail-item span { + display: inline-block; + max-width: calc(100% - 120px); +} + +.detail-image { + display: inline-block; + margin-top: 8px; + border: 1px dashed #dcdee2; + padding: 4px; + border-radius: 4px; + background: #f8f8f9; +} +</style> diff --git a/manager/src/views/prize-record/index.vue b/manager/src/views/prize-record/index.vue new file mode 100644 index 0000000..c27ae75 --- /dev/null +++ b/manager/src/views/prize-record/index.vue @@ -0,0 +1,518 @@ +<template> + <div> + <Card> + <!-- 鎼滅储琛ㄥ崟 --> + <Form + ref="searchForm" + @keydown.enter.native="handleSearch" + :model="searchForm" + inline + :label-width="80" + class="search-form" + > + <FormItem label="鐢ㄦ埛鏄电О" prop="nickName"> + <Input + type="text" + v-model="searchForm.nickName" + placeholder="璇疯緭鍏ョ敤鎴锋樀绉�" + clearable + @on-clear="handleSearch" + style="width: 180px" + /> + </FormItem> + <FormItem label="娲诲姩鍚嶇О" prop="activityName"> + <Input + type="text" + v-model="searchForm.activityName" + placeholder="璇疯緭鍏ユ椿鍔ㄥ悕绉�" + clearable + @on-clear="handleSearch" + style="width: 180px" + /> + </FormItem> + <FormItem label="涓鐘舵��" prop="beginTime"> + <Select + v-model="searchForm.prizeStatus" + placeholder="璇烽�夋嫨涓鐘舵��" + style="width: 180px" + clearable + @on-clear="handleSearch" + @on-change="handleSearch" + > + <Option + v-for="item in typeSelect" + :value="item.value" + :key="item.id" + > + {{ item.label }} + </Option> + </Select> + </FormItem> + <FormItem label="濂栧搧鍙戞斁鐘舵��" prop="beginTime"> + <Select + v-model="searchForm.distributeStatus" + placeholder="璇烽�夋嫨濂栧搧鍙戞斁鐘舵��" + style="width: 180px" + clearable + @on-clear="handleSearch" + @on-change="handleSearch" + > + <Option + v-for="item in distributeSelect" + :value="item.value" + :key="item.id" + > + {{ item.label }} + </Option> + </Select> + </FormItem> + <Button + @click="handleSearch" + type="primary" + icon="ios-search" + class="search-btn" + >鎼滅储</Button> + <Button + @click="resetSearch" + icon="md-refresh" + style="margin-left: 8px" + >閲嶇疆</Button> + <Button + @click="queryExport" + class="search-btn" + type="primary" + >瀵煎嚭</Button + > + </Form> + + + <!-- 娲诲姩琛ㄦ牸 --> + <Table + :loading="loading" + border + :columns="columns" + :data="data" + ref="table" + class="table" + > + <!-- 鎿嶄綔鎸夐挳鎻掓Ы --> + <template slot-scope="{ row }" slot="action"> + <div class="action-btns"> + <Button + type="info" + size="small" + @click="detail(row)" + >璇︽儏</Button> + </div> + </template> + </Table> + + <!-- 鍒嗛〉 --> + <Row type="flex" justify="end" class="page-footer"> + <Page + :current="searchForm.pageNumber" + :total="total" + :page-size="searchForm.pageSize" + @on-change="changePage" + @on-page-size-change="changePageSize" + :page-size-opts="[10, 20, 50]" + size="small" + show-total + show-elevator + show-sizer + ></Page> + </Row> + <!-- 璇︽儏--> + <Modal + v-model="infoModalShow" + title="娲诲姩璇︽儏" + @on-cancel="infoModelClose" + width="800" + :mask-closable="false" + > + <div class="detail-container"> + <Row :gutter="16"> + <Col span="12"> + <div class="detail-item"> + <label>娲诲姩鍚嶇О锛�</label> + <span>{{ detailData.activityName }}</span> + </div> + </Col> + <Col span="12"> + <div class="detail-item"> + <label>鐢ㄦ埛鏄电О锛�</label> + <span>{{ detailData.nickName}}</span> + </div> + </Col> + <Col span="12"> + <div class="detail-item"> + <label>濂栧搧鍐呭锛�</label> + <span>{{ detailData.prizeContent }}</span> + </div> + </Col> + <Col span="24"> + <div class="detail-item"> + <label>涓鐘舵�侊細</label> + <Tag :color="detailData.prizeStatus === 'WIN' ? 'green' : 'red'"> + {{ detailData.prizeStatus === 'WIN' ? '涓' : '鏈腑濂�' }} + </Tag> + </div> + </Col> + <Col span="24"> + <div class="detail-item"> + <label>濂栧搧鍙戞斁锛�</label> + <Tag + :color="getStatusColor(detailData.distributeStatus)" + > + {{ getStatusText(detailData.distributeStatus) }} + </Tag> + </div> + </Col> + <Col span="24"> + <div class="detail-item"> + <label>娲诲姩灏侀潰锛�</label> + <div v-if="detailData.activityCoverUrl" class="detail-image"> + <img + :src="detailData.activityCoverUrl" alt="娲诲姩灏侀潰" + class="preview-image-limit" + > + </div> + <span v-else>-</span> + </div> + </Col> + <Col span="24"> + <div class="detail-item"> + <label>濂栧搧灏侀潰锛�</label> + <div v-if="detailData.prizeImgUrl" class="detail-image"> + <img + :src="detailData.prizeImgUrl" alt="濂栧搧灏侀潰" + class="preview-image-limit" + > + </div> + <span v-else>-</span> + </div> + </Col> + + </Row> + </div> + + </Modal> + + </Card> + </div> +</template> + +<script> +import { + getPage, + queryExport +} from '@/api/prize-record.js' + +export default { + name: "prizeRecord", + + data() { + return { + infoModalShow:false, + detailData: {}, + modelShow:false, + modelTitle:'', + loading:false, + columns:[ + { + title: '鐢ㄦ埛鏄电О', + key: 'nickName', + minWidth: 100, + }, + { + title: '娲诲姩鍚嶇О', + key: 'prizeActivityName', + minWidth: 100, + }, + { + title: '涓鐘舵��', + key: 'prizeStatus', + minWidth: 100, + render: (h, params) => { + return h('Tag', { + props: { + color: params.row.prizeStatus === 'WIN' ? 'green' : 'red' + }}, params.row.prizeStatus === 'WIN' ? '涓' : '鏈腑濂�') + } + }, + { + title: '濂栧搧鍙戞斁鐘舵��', + key: 'distributeStatus', + minWidth: 100, + render: (h, params) => { + // 鑾峰彇褰撳墠鐘舵�� + const status = params.row.distributeStatus; + + // 鏍规嵁鐘舵�佺‘瀹氶鑹插拰鏂囨湰 + let color, text; + switch(status) { + case 'SUCCESS': + color = 'green'; + text = '宸插彂鏀�'; + break; + case 'NOT_WAIT': + color = 'blue'; + text = '鏈腑濂�'; + break; + case 'FAILED': + color = 'red'; + text = '鍙戞斁澶辫触'; + break; + case 'WAIT': + color = 'orange'; + text = '寰呭彂鏀�'; + break; + default: + color = 'default'; + text = '鏈煡鐘舵��'; + } + + return h('Tag', { + props: { color } + }, text); + } + }, + { + title: '鎿嶄綔', + slot: 'action', + width: 280, + align: 'center', + fixed: 'right' + }, + ], + data:[], + total:0, + searchForm:{ + pageSize:10, + pageNumber:1, + nickName:'', + activityName:'', + prizeStatus:'', + distributeStatus:'' + }, + distributeSelect:[ + {id: 1, value: 'NOT_WAIT', label: '鏈腑濂�'}, + {id: 2, value: 'WAIT', label: '寰呭彂鏀�'}, + {id: 3, value: 'FAILED', label: '鍙戞斁澶辫触'}, + {id: 4, value: 'SUCCESS', label: '宸插彂鏀�'}, + ], + typeSelect:[ + {id: 1, value: 'WIN', label: '涓'}, + {id: 2, value: 'NOT_WIN', label: '鏈腑濂�'} + ], + activityCover:null, + + + } + }, + // 鍦ㄧ粍浠跺垱寤哄墠娉ㄥ唽 + beforeCreate() { + + }, + mounted() { + this.init(); + }, + methods: { + queryExport(){ + queryExport(this.searchForm).then(res =>{ + const blob = new Blob([res], { + type: "application/vnd.ms-excel;charset=utf-8", + }); + //瀵逛簬<a>鏍囩锛屽彧鏈� Firefox 鍜� Chrome锛堝唴鏍革級 鏀寔 download 灞炴�� + //IE10浠ヤ笂鏀寔blob浣嗘槸渚濈劧涓嶆敮鎸乨ownload + if ("download" in document.createElement("a")) { + //鏀寔a鏍囩download鐨勬祻瑙堝櫒 + const link = document.createElement("a"); //鍒涘缓a鏍囩 + link.download = "鐢ㄦ埛鎶藉璁板綍.xlsx"; //a鏍囩娣诲姞灞炴�� + link.style.display = "none"; + link.href = URL.createObjectURL(blob); + document.body.appendChild(link); + link.click(); //鎵ц涓嬭浇 + URL.revokeObjectURL(link.href); //閲婃斁url + document.body.removeChild(link); //閲婃斁鏍囩 + } else { + navigator.msSaveBlob(blob, fileName); + } + }) + + + }, + // 鑾峰彇鐘舵�佸搴旂殑棰滆壊 + getStatusColor(status) { + // 澶勭悊绌哄�兼儏鍐� + if (!status) return 'default' + + // 鏍规嵁鐘舵�佽繑鍥炲搴旈鑹� + switch(status) { + case 'NOT_WAIT': + return 'blue' + case 'WAIT': + return 'orange' + case 'FAILED': + return 'red' + case 'SUCCESS': + return 'green' + // 榛樿棰滆壊 + default: + return 'default' + } + }, + + // 鑾峰彇鐘舵�佸搴旂殑鏂囨湰 + getStatusText(status) { + if (!status) return '鏈煡鐘舵��' + + switch(status) { + case 'NOT_WAIT': + return '鏈腑濂�' + case 'WAIT': + return '寰呭彂鏀�' + case 'FAILED': + return '鍙戞斁澶辫触' + case 'SUCCESS': + return '宸插彂鏀�' + // 榛樿鏂囨湰 + default: + return '鏈煡鐘舵��' + } + }, + // 鏍煎紡鍖栧鍝佺被鍨� + replaceText(type) { + if (type === "coupon") { + return "浼樻儬鍒�"; + } + return type; // 濡傛灉涓嶆槸鐩爣璇嶏紝杩斿洖鍘熸枃鏈� + }, + resetSearch(){ + this.$refs.searchForm.resetFields() + this.searchForm.pageNumber = 1 + this.getPage() + }, + infoModelClose(){ + this.infoModalShow = false; + }, + + getPage(){ + this.loading = true; + getPage(this.searchForm).then(res =>{ + this.loading = false; + if (res.code === 200){ + this.data = res.data; + this.total = res.total; + }else { + this.$Message.error(res.msg) + } + }) + }, + detail(row){ + this.infoModalShow = true; + this.detailData = {...row}; + + + }, + + handleSearch(type,value){ + if (type === 'beginTime') { + this.searchForm.beginTime = value + } else if (type === 'endTime') { + this.searchForm.endTime = value + } + this.getPage() + }, + + // 鍒濆鍖栨暟鎹� + init() { + this.getPage() + }, + changePage(){ + this.searchForm.pageNumber = 1 + this.searchForm.pageSize = pageSize + this.getPage() + }, + changePageSize(){ + this.searchForm.pageNumber = page + this.getPage() + }, + + }, +} +</script> + +<style lang="scss" scoped> +.search-form { + padding: 16px; + background: #f8f8f9; + border-radius: 4px; + margin-bottom: 16px; + + .ivu-form-item { + margin-bottom: 16px; + margin-right: 16px; + } + + .search-btn { + margin-left: 8px; + } +} +.table { + .thumbnail { + max-width: 100%; + max-height: 100%; + object-fit: contain; + cursor: pointer; + transition: all 0.3s; + + &:hover { + transform: scale(1.05); + box-shadow: 0 0 8px rgba(0, 0, 0, 0.2); + } + } + .action-btns { + display: flex; + flex-wrap: wrap; + justify-content: center; + + .ivu-btn { + margin: 4px; + font-size: 12px; + padding: 2px 6px; + min-width: 60px; + } + } +} +.detail-container { + padding: 16px; +} + +.detail-item { + margin-bottom: 16px; + line-height: 1.5; +} + +.detail-item label { + display: inline-block; + width: 120px; + font-weight: bold; + color: #515a6e; + vertical-align: top; +} + +.detail-item span { + display: inline-block; + max-width: calc(100% - 120px); +} + +.detail-image { + display: inline-block; + margin-top: 8px; + border: 1px dashed #dcdee2; + padding: 4px; + border-radius: 4px; + background: #f8f8f9; +} +</style> -- Gitblit v1.8.0