123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- <template>
- <div>
- <div class="all" style="padding: 20px;">
- <FormBox>
- <div class="form-item">
- <div class="form-label">发放时间</div>
- <div class="form-search">
- <el-date-picker size="medium" style="width:290px" class="first-element-btn" :clearable="false"
- v-model="time_range" type="daterange" value-format="yyyy-MM-dd" range-separator="至"
- start-placeholder="开始日期" end-placeholder="结束日期"
- :picker-options="instantPickerOptions"></el-date-picker>
- </div>
- </div>
- <div class="form-item">
- <div class="form-label">姓名搜索</div>
- <div class="form-search">
- <el-select v-model="formData.employee_id" size="medium" filterable placeholder="请输入或选择人员" clearable>
- <el-option v-for="item in employee_map" :key="item.id" :label="item.name" :value="item.id"></el-option>
- </el-select>
- </div>
- </div>
- <div class="form-item">
- <div class="form-label">发放状态</div>
- <div class="form-search">
- <el-select v-model="formData.status" size="medium" placeholder="请选择" clearable>
- <el-option v-for="(item, index) in event_type" :key="index" :label="item.name" :value="item.id"></el-option>
- </el-select>
- </div>
- </div>
- <div class="form-item">
- <div class="form-label">兑换码</div>
- <div class="form-search">
- <el-input placeholder="请输入兑换码" size="medium" v-model="formData.sn" clearable></el-input>
- </div>
- </div>
- </FormBox>
- <div style="margin: 10px 0;">
- <el-button type="primary" size="medium" plain @click="grants"
- style="margin-right: 10px;">批量发放</el-button>
- <el-button type="primary" size="medium" plain @click="exportExcel">导出</el-button>
- </div>
- <el-table :data="list" style="width: 100%;cursor: pointer;" v-loading="loading" @row-click="openDetail"
- @selection-change="handleSelectionChange">
- <el-table-column type="selection" :selectable="selectable"></el-table-column>
- <el-table-column label="姓名" align="left">
- <template slot-scope="scope">
- <div style="display:flex;">
- <userImage :user_name="scope.row.employee.name" :id="scope.row.employee.id" width="50px"
- height="50px"></userImage>
- <span style="line-height: 50px; padding-left: 10px;">{{ scope.row.employee.name }}</span>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="goods_name" label="奖品名称" align="center"></el-table-column>
- <el-table-column prop="num" label="数量" align="center"></el-table-column>
- <el-table-column prop="total_price" label="总价" align="center"></el-table-column>
- <el-table-column prop="create_time" label="兑换时间" align="center">
- <template slot-scope="scope">
- {{ $moment.unix(scope.row.create_time).format('YYYY-MM-DD HH:mm:ss') }}
- </template>
- </el-table-column>
- <el-table-column prop="sn" label="兑换码" align="center" min-width="140"></el-table-column>
- <el-table-column prop="complete_time" label="发放时间" align="center">
- <template slot-scope="scope">
- <span
- v-if="scope.row.complete_time">{{ $moment.unix(scope.row.complete_time).format('YYYY-MM-DD HH:mm:ss') }}</span>
- <span v-else>--</span>
- </template>
- </el-table-column>
- <el-table-column prop="status" label="状态" align="center">
- <template slot-scope="scope">
- <span v-if="scope.row.status == 0" class="fontColorD">未发放</span>
- <span v-if="scope.row.status == 1" class="green">已发放</span>
- <span v-if="scope.row.status == 2" class="red">已取消</span>
- </template>
- </el-table-column>
- <el-table-column prop="point" label="操作" align="left">
- <template slot="header" slot-scope="scope">
- <el-tooltip effect="dark" placement="top-start">
- <div slot="content">
- <div style="margin-bottom: 10px;">7日内可执行撤销操作</div>
- </div>
- <span>
- <span>操作</span>
- <i class="el-icon-warning"></i>
- </span>
- </el-tooltip>
- </template>
- <template slot-scope="scope">
- <el-link type="primary" :underline="false" @click.stop="grant(scope.row.id)"
- v-if="scope.row.status == 0" style="padding-right: 10px;">发放</el-link>
- <el-link type="primary" :underline="false" @click.stop="revoke(scope.row.id)"
- v-if="scope.row.status == 1" style="padding-right: 10px;">撤销</el-link>
- <el-link type="primary" :underline="false" @click.stop="cancel(scope.row.id)"
- v-if="scope.row.status == 0" style="padding-right: 10px;">取消</el-link>
- <el-link type="primary" :underline="false">查看明细</el-link>
- </template>
- </el-table-column>
- <template slot="empty">
- <noData></noData>
- </template>
- </el-table>
- <center style="padding: 20px 0;">
- <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
- :current-page="formData.page" :page-sizes="[10, 20, 50, 100]"
- layout="total, sizes, prev, pager, next" :page-size="pageLimit" :total="total"></el-pagination>
- </center>
- </div>
- <el-dialog title="发放结果" :visible.sync="isResult" width="600" :close-on-click-modal="false"
- :close-on-press-escape="false" :show-close="false">
- <div v-if="!isShowError">
- <div style="text-align: center;margin-bottom: 10px;" class="red" v-if="isShowError2">{{ errorMsg }}
- </div>
- <el-progress :text-inside="true" :stroke-width="24" :percentage="percentage"></el-progress>
- <div style="margin-top: 20px;border: 1px solid #f1f1f1;max-height: 500px;overflow-y: auto;"
- class="scroll-bar">
- <div class="flex-box-ce results" style="font-weight: 600;">
- <div style="border-right: 1px solid #f1f1f1;width: 50px;">序号</div>
- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">姓名</div>
- <div class="flex-2">提交结果</div>
- </div>
- <div class="flex-box-ce results" v-for="(item, index) in results" :key="index">
- <div style="border-right: 1px solid #f1f1f1;width: 50px;">{{ results.length - index }}</div>
- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.source_msg.name }}</div>
- <div class="flex-2 green" v-if="item.status == 1">{{ item.msg }}</div>
- <div class="flex-2 red" v-else>{{ item.msg }}</div>
- </div>
- </div>
- <span slot="footer">
- <div class="flex-box-end" style="margin-top: 20px;"
- v-show="isShowError2 && results.length != resultList.length">
- <el-button type="primary" @click="isResult = false" size="small">确 定</el-button>
- </div>
- <div class="flex-box-end" style="margin-top: 20px;" v-show="results.length == resultList.length">
- <el-button type="primary" @click="isResult = false" size="small">确 定</el-button>
- </div>
- </span>
- </div>
- <div v-else>
- <div style="text-align: center;" class="red">{{ errorMsg }}</div>
- <span slot="footer">
- <div class="flex-box-end" style="margin-top: 20px;"><el-button type="primary"
- @click="isResult = false" size="small">确 定</el-button></div>
- </span>
- </div>
- </el-dialog>
- <!-- 缓存的奖扣 -->
- <el-dialog title="网络中断发放对象列表" :visible.sync="isShowBreak" width="800" :close-on-click-modal="false"
- :close-on-press-escape="false" :show-close="false">
- <div>
- <div style="margin-top: 20px;border: 1px solid #f1f1f1;max-height: 500px;overflow-y: auto;"
- class="scroll-bar">
- <div class="flex-box-ce results" style="font-weight: 600;">
- <div style="border-right: 1px solid #f1f1f1;width: 50px;">序号</div>
- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">姓名</div>
- </div>
- <div class="flex-box-ce results" v-for="(item, index) in breakList" :key="index">
- <div style="border-right: 1px solid #f1f1f1;width: 50px;">{{ index + 1 }}</div>
- <div class="flex-1" style="border-right: 1px solid #f1f1f1;">{{ item.name }}</div>
- </div>
- </div>
- <span slot="footer">
- <div class="flex-box-end" style="margin-top: 20px;">
- <el-button type="primary" @click="colseBreak()" size="small">取 消</el-button>
- <el-button type="primary" @click="submitBreak()" size="small">再次提交</el-button>
- </div>
- </span>
- </div>
- </el-dialog>
- <!-- 取消 -->
- <el-dialog title="取消兑换" :visible.sync="isCancel" width="500px">
- <div style="margin: 10px 0;">
- <el-form ref="addTypeName" :model="addTypeName" label-width="85px" @submit.native.prevent>
- <el-form-item label="取消原因"
- :rules="[{ required: true, message: '取消原因不能为空' }, { min: 2, max: 200, message: '长度在 2 到 200 个字符', trigger: 'blur' }]"
- prop="remark">
- <el-input v-model="addTypeName.remark" type="textarea" placeholder="请输入取消原因" :rows="5"
- maxlength="200" show-word-limit></el-input>
- </el-form-item>
- </el-form>
- <span class="dialog-footer" style="display:flex;justify-content: flex-end;">
- <el-button @click="isCancel = false">取 消</el-button>
- <el-button type="primary" @click="subGroupForm('addTypeName')">确 定</el-button>
- </span>
- </div>
- </el-dialog>
- <!-- 详情 -->
- <el-dialog title="兑换详情" :visible.sync="isDetail" width="600px">
- <div style="margin: 10px 0;" v-loading="attendload">
- <div class="flex-box-ce">
- <div class="flex-box-ce flex-1">
- <userImage :user_name="detailData.employee.name" :id="detailData.employee.id" width="50px"
- height="50px" fontSize="1"></userImage>
- <div style="margin-left:10px;margin-right:4px;">
- <div style="font-size: 16px;font-weight: 700;">{{ detailData.employee.name }}</div>
- <div v-if="detailData.employee.employee_detail">
- <span v-for="(item, index) in detailData.employee.employee_detail.dept_list"
- :key="index">
- {{ item.dept_name }}
- <span
- v-if="detailData.employee.employee_detail.dept_list.length - index > 1">,</span>
- </span>
- </div>
- </div>
- </div>
- <div v-if="detailData.status == 0" class="fontColorD" style="font-size: 16px;">未发放</div>
- <div v-if="detailData.status == 1" class="green" style="font-size: 16px;">已发放</div>
- <div v-if="detailData.status == 2" class="red" style="font-size: 16px;">已取消</div>
- </div>
- <div class="imgBox flex-box" style="height: 100px">
- <el-image style="width: 100px; height: 100px" :src="detailData.goods_image"
- :preview-src-list="[detailData.goods_image]"></el-image>
- <div class="flex-box-v" style="padding: 10px;">
- <div class="flex-1" style="width: 230px;">{{ detailData.goods_name }}</div>
- <div>单价 :<span class="blue">{{ detailData.price }}</span> 功勋点</div>
- </div>
- </div>
- <div style="margin-bottom: 30px;" class="message">
- <div class="flex-box-ce">
- <span class="tabel">数量</span>
- <span class="flex-1">{{ detailData.num }}</span>
- </div>
- <div class="flex-box-ce">
- <span class="tabel">总价</span>
- <span class="flex-1">{{ detailData.total_price }}</span>
- </div>
- <div class="flex-box-ce">
- <span class="tabel">兑换时间</span>
- <span
- class="flex-1">{{ $moment.unix(detailData.create_time).format('YYYY-MM-DD HH:mm:ss') }}</span>
- </div>
- <div class="flex-box" style="margin-bottom: 10px;">
- <span class="tabel">备注</span>
- <div class="flex-1"
- style="min-height: 80px;border-radius: 5px;background-color: #f1f1f1;padding: 10px;">
- {{ detailData.remark }}</div>
- </div>
- <div class="flex-box-ce" v-if="detailData.status == 1">
- <span class="tabel">发放时间</span>
- <span
- class="flex-1">{{ $moment.unix(detailData.complete_time).format('YYYY-MM-DD HH:mm:ss') }}</span>
- </div>
- <div class="flex-box-ce" v-if="detailData.status == 2">
- <span class="tabel">取消时间</span>
- <span
- class="flex-1">{{ $moment.unix(detailData.complete_time).format('YYYY-MM-DD HH:mm:ss') }}</span>
- </div>
- <div class="flex-box" v-if="detailData.status == 2">
- <span class="tabel">取消原因</span>
- <div class="flex-1"
- style="min-height: 80px;border-radius: 5px;background-color: #f1f1f1;padding: 10px;">
- {{ detailData.cancel_remark }}</div>
- </div>
- </div>
- <span class="dialog-footer" style="display:flex;justify-content: flex-end;">
- <el-button type="primary" @click="isDetail = false">确 定</el-button>
- </span>
- </div>
- </el-dialog>
- </div>
- </template>
- <script>
- export default {
- data() {
- return {
- instantPickerOptions: {
- shortcuts: [{
- text: '本周',
- onClick(picker) {
- const now = new Date();
- const start = new Date();
- start.setTime(now.getTime() - (now.getDay() - 1) * 24 * 60 * 60 * 1000);
- now.setTime(start.getTime() + 6 * 24 * 60 * 60 * 1000 - 1000);
- picker.$emit('pick', [start, now]);
- }
- },
- {
- text: '上周',
- onClick(picker) {
- const end = new Date();
- const start = new Date();
- start.setTime(start.getTime() - (start.getDay() + 6) * 3600 * 1000 * 24);
- end.setTime(start.getTime() + 6 * 24 * 60 * 60 * 1000 - 1000);
- picker.$emit('pick', [start, end]);
- }
- },
- {
- text: '本月',
- onClick(picker) {
- const now = new Date();
- const startDate = new Date(now.getFullYear(), now.getMonth(), 1);
- const endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0);
- picker.$emit('pick', [startDate, endDate]);
- }
- },
- {
- text: '上月',
- onClick(picker) {
- const now = new Date();
- const startDate = new Date(now.getFullYear() - (now.getMonth() > 0 ? 0 : 1), (now
- .getMonth() + 11) % 12, 1);
- const endDate = new Date(now.getFullYear(), now.getMonth(), 0);
- picker.$emit('pick', [startDate, endDate]);
- }
- }
- ]
- },
- employee_map: [],
- event_type: [{
- id: 0,
- name: '未发放'
- }, {
- id: 1,
- name: '已发放'
- }, {
- id: 2,
- name: '已取消'
- }],
- attendload: false,
- loading: false,
- list: null,
- time_range: [
- this.$moment()
- .startOf('month')
- .format('YYYY-MM-DD'),
- this.$moment()
- .endOf('month')
- .format('YYYY-MM-DD')
- ],
- formData: {
- this_only: '',
- status: '',
- page: 1,
- page_size: 10,
- export: 0,
- sn: '',
- employee_id: '',
- start_time: '',
- end_time: ''
- },
- total: 0,
- pageLimit: 10,
- selectIds: [],
- // 长连接结果
- results: [], //提交的返回结果集合
- isResult: false,
- percentage: 0,
- resultList: [], //要发送数据的集合
- resultIndex: 0,
- isShowError: false,
- isShowError2: false,
- errorMsg: '服务器繁忙,请稍后再试',
- breakList: [],
- isShowBreak: false,
- isCancel: false,
- isDetail: false,
- addTypeName: {
- id: '',
- remark: ''
- },
- detailData: {
- employee: {}
- }
- };
- },
- watch: {
- 'formData.employee_id'() {
- this.formData.page = 1;
- this.getList();
- },
- 'formData.sn'() {
- this.formData.page = 1;
- this.getList();
- },
- 'formData.status'() {
- this.formData.page = 1;
- this.getList();
- },
- time_range() {
- this.formData.page = 1;
- this.getList();
- },
- isResult(val) {
- if (!val) {
- this.isShowError = false;
- this.isShowBreak = false;
- this.errorMsg = '服务器繁忙,请稍后再试';
- this.$socketApiTow.closewebsocket();
- this.getList();
- }
- }
- },
- created() {
- this.employee_map = this.$getCache('userList');
- },
- mounted() {
- this.getList(); //考勤组
- let data = this.$getCache('conversion');
- if (data) {
- this.breakList = data.obj;
- this.isShowBreak = true;
- }
- },
- methods: {
- operation(url, str, data) {
- this.$confirm(`您确认${str}该奖品?`, '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- this.$axios('post', url, data).then(res => {
- this.$message.success(`已${str}`);
- this.isCancel = false;
- this.getList();
- });
- });
- },
- // 提交表单
- subGroupForm(formName) {
- this.$refs[formName].validate(valid => {
- if (valid) {
- this.operation('api/shop/exchange/cancel', '取消', this.addTypeName);
- }
- });
- },
- //取消
- cancel(id) {
- this.isCancel = true;
- if (this.$refs['addTypeName']) {
- this.$refs['addTypeName'].resetFields();
- }
- this.addTypeName.remark = '';
- this.addTypeName.id = id;
- },
- //撤销
- revoke(id) {
- this.operation('api/shop/exchange/revoke', '撤销', {
- id: id
- });
- },
- //发放
- grant(id) {
- this.operation('api/shop/exchange/deal', '发放', {
- id: id
- });
- },
- selectable(e) {
- return e.status == 0;
- },
- // 关闭缓存弹窗
- colseBreak() {
- this.isShowBreak = false;
- this.breakList = [];
- this.$removeCache('conversion');
- },
- // 提交缓存奖扣
- submitBreak() {
- this.$removeCache('conversion');
- this.resultList = JSON.parse(JSON.stringify(this.breakList));
- this.resultIndex = 0;
- this.percentage = 0;
- this.results = [];
- this.isResult = true;
- this.opneWebSocket();
- },
- returnName(id) {
- return this.employee_map[id].name;
- },
- grants() {
- if (this.selectIds.length == 0) {
- this.$message.error('请选择兑换记录');
- return false;
- }
- this.webSocket();
- },
- webSocket() {
- let arr = [];
- this.selectIds.forEach(item => {
- let data = {
- type: 'consume_deal',
- id: item.id,
- name: item.name
- };
- arr.push(data);
- });
- this.resultList = arr;
- this.resultIndex = 0;
- this.percentage = 0;
- this.results = [];
- this.isResult = true;
- this.opneWebSocket();
- },
- opneWebSocket() {
- let wsData = this.resultList;
- if (wsData[this.resultIndex] && !this.isShowError) {
- this.$socketApiTow.sendData(wsData[this.resultIndex], this.onmessageWS);
- }
- },
- onmessageWS(e) {
- if (e.type == 'consume_deal') {
- let result = e.result;
- result.status = e.code
- result.msg = e.msg
- this.results.unshift(result);
- this.resultIndex++;
- this.opneWebSocket();
- // 进度条
- let lng = this.resultList.length;
- this.percentage = Math.floor(this.resultIndex / (lng / 100))
- if (lng == this.results.length) {
- this.percentage = 100;
- }
- }
- // 中途断开
- if (e.type == 'break') {
- let wsData = this.resultList;
- this.errorMsg = e.msg;
- let data = {
- obj: wsData.slice(this.resultIndex, wsData.length)
- };
- this.$setCache('conversion', data);
- this.isShowError2 = true;
- }
- // 连接不上
- if (e.type == 'error') {
- this.errorMsg = e.msg;
- this.isShowError = true;
- }
- },
- handleSelectionChange(e) {
- this.selectIds = e.map(item => {
- let data = {
- id: item.id,
- name: item.employee.name
- };
- return data;
- });
- },
- openDetail(e) {
- this.isDetail = true;
- this.attendload = true;
- this.$axios('get', '/api/shop/exchange/detail', {
- id: e.id
- })
- .then(res => {
- this.detailData = res.data.data;
- })
- .finally(() => {
- this.attendload = false;
- });
- },
- exportExcel() {
- let url =
- `${process.env.VUE_APP_BASE_API}/api/download/shop/achievement/exchange/list?page=1&download_employee_id=${this.$getUserData().id}&page_size=8000&self_only=2&start_time=${this.time_range[0]}&end_time=${this.time_range[1]}`;
- window.open(url, '_blank');
- },
- //分页
- handleSizeChange(val) {
- this.pageLimit = val;
- this.formData.page_size = this.pageLimit;
- this.getList();
- },
- handleCurrentChange(val) {
- this.formData.page = val;
- this.getList();
- },
- //请求数据
- getList() {
- this.loading = true;
- let data = {
- self_only: '2',
- page: this.formData.page,
- page_size: this.formData.page_size,
- // status: this.formData.status,
- export: this.formData.export,
- sn: this.formData.sn
- // employee_id: this.formData.employee_id,
- };
- if (this.formData.employee_id) {
- data.employee_id = this.formData.employee_id;
- }
- if (this.formData.status === 0 || this.formData.status === 1 || this.formData.status === 2) {
- data.status = this.formData.status;
- }
- data.start_time = this.time_range[0];
- data.end_time = this.time_range[1];
- this.$axios('get', '/api/shop/exchange/list', data)
- .then(res => {
- this.list = res.data.data.list;
- this.total = res.data.data.count;
- })
- .finally(() => {
- this.loading = false;
- });
- }
- }
- };
- </script>
- <style scoped lang="scss">
- .message .flex-box-ce {
- margin-bottom: 10px;
- }
- .tabel {
- width: 80px;
- color: #606266;
- }
- .imgBox {
- width: 350px;
- border-radius: 5px;
- border: 1px solid #f1f1f1;
- margin: 10px 0;
- box-shadow: 0 0 5px #f1f1f1;
- }
- .results {
- border-bottom: 1px solid #f1f1f1;
- text-align: center;
- }
- .results div {
- padding: 10px;
- }
- .el-date-editor.el-input {
- width: auto;
- }
- .date-picker-width {
- width: 145px !important;
- }
- .search ::v-deep .el-input-group__append:active {
- background: #26a2ff;
- }
- .search ::v-deep .el-input-group__append:active .el-icon-search {
- color: #fff;
- }
- ::v-deep .el-dialog__body {
- padding: 0px 20px 30px;
- }
- </style>
|