This commit is contained in:
weipengfei 2024-05-13 18:10:13 +08:00
parent 5449b2301c
commit 2bebabf1bc
26 changed files with 1306 additions and 733 deletions

View File

@ -1,4 +1,5 @@
VITE_NOW_TYPE = 'dist' VITE_NOW_TYPE = 'dist'
# VITE_BASE_URL = 'http://192.168.1.10:8546' VITE_PUSH_URL = 'ws://192.168.1.22:8787'
VITE_BASE_URL = 'https://erp.lihaink.cn' VITE_BASE_URL = 'http://192.168.1.22:8546'
# VITE_BASE_URL = 'https://erp.lihaink.cn'

View File

@ -1,3 +1,4 @@
VITE_NOW_TYPE = 'build' VITE_NOW_TYPE = 'build'
VITE_PUSH_URL = 'ws://192.168.1.22:3133'
VITE_BASE_URL = 'https://shop.lihaink.cn' VITE_BASE_URL = 'https://shop.lihaink.cn'

6
package-lock.json generated
View File

@ -15,6 +15,7 @@
"mitt": "^3.0.1", "mitt": "^3.0.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"print-js": "^1.6.0",
"sass": "^1.72.0", "sass": "^1.72.0",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-router": "^4.3.0" "vue-router": "^4.3.0"
@ -1469,6 +1470,11 @@
"postcss": "^8.0.0" "postcss": "^8.0.0"
} }
}, },
"node_modules/print-js": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz",
"integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg=="
},
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",

View File

@ -17,6 +17,7 @@
"mitt": "^3.0.1", "mitt": "^3.0.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"print-js": "^1.6.0",
"sass": "^1.72.0", "sass": "^1.72.0",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-router": "^4.3.0" "vue-router": "^4.3.0"

View File

@ -1,13 +1,14 @@
<script setup> <script setup>
import { onMounted } from 'vue' import { onMounted } from "vue";
onMounted(() => { onMounted(() => {
document.body.style.setProperty('--el-color-primary', '#1890ff'); document.body.style.setProperty("--el-color-primary", "#1890ff");
document.body.style.setProperty('--el-upload-picture-card-size', '60px'); document.body.style.setProperty("--el-upload-picture-card-size", "60px");
document.body.style.setProperty('--el-upload-list-picture-card-size', '60px'); document.body.style.setProperty("--el-upload-list-picture-card-size", "60px");
}) });
const screenWidth = window.innerWidth; const screenWidth = window.innerWidth;
console.log('当前屏幕宽度:', screenWidth); console.log("当前屏幕宽度:", screenWidth);
</script> </script>
<template> <template>
@ -15,12 +16,13 @@ const screenWidth = window.innerWidth;
</template> </template>
<style lang="scss"> <style lang="scss">
.el-button:focus{ .el-button:focus {
outline: none; outline: none;
} }
// input // input
input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none; -webkit-appearance: none;
margin: 0; margin: 0;
} }

View File

@ -73,6 +73,6 @@ export function saleStoreListApi(data) {
/** /**
* @description 店铺商品分类 * @description 店铺商品分类
*/ */
export function merchantCategoryListApi(id, data) { export function merchantCategoryListApi(data) {
return request.get(`store/merchant/category/lst/${id}`, { params: data }) return request.get(`goods/goodsclass/lists`, { params: data })
} }

View File

@ -26,21 +26,21 @@ export function cartChangeApi(id, data) {
* @description 结算 * @description 结算
*/ */
export function orderCheckApi(data) { export function orderCheckApi(data) {
return request.post(`v2/order/check`, data) return request.post(`/order/RetailOrder/checkOrder`, data)
} }
/** /**
* @description 删除商品 * @description 删除商品
*/ */
export function cartDeleteApi(data) { export function cartDeleteApi(data) {
return request.post(`user/cart/delete`, data) return request.post(`/order/cart/delete`, data)
} }
/** /**
* @description 支付 * @description 支付
*/ */
export function orderCreateApi(data) { export function orderCreateApi(data) {
return request.post(`v2/order/create`, data) return request.post(`/order/RetailOrder/createOrder`, data)
} }
/** /**
@ -60,8 +60,8 @@ export function orderStatusApi(data) {
/** /**
* @description 订单列表 * @description 订单列表
*/ */
export function orderListApi(id, data) { export function orderListApi(data) {
return request.get(`admin/${id}/order_list`, { params: data }) return request.get(`/order/retailOrder/merchant_order_list`, { params: data })
} }
/** /**
@ -108,8 +108,22 @@ export function orderPriceApi(mer_id, data) {
/** /**
* @description 批发订单列表 * @description 收银订单列表
*/ */
export function saleOrderListApi(mer_id, data) { export function saleOrderListApi(data) {
return request.get(`order/list`, { params: data }) return request.get(`/order/retailOrder/order_list`, { params: data })
}
/**
* @description 采购订单提交
*/
export function createOrderApi(data) {
return request.get(`/order/OpurchaseOrder/createOrder`, { params: data })
}
/**
* @description 订单商品列表
*/
export function cashierinfoListApi(data) {
return request.get(`/order/cashierinfo/lists`, { params: data })
} }

751
src/common/push.js Normal file
View File

@ -0,0 +1,751 @@
export const Push = function Push(options) {
this.doNotConnect = 0;
options = options || {};
options.heartbeat = options.heartbeat || 25000;
options.pingTimeout = options.pingTimeout || 10000;
this.config = options;
this.uid = 0;
this.channels = {};
this.connection = null;
this.pingTimeoutTimer = 0;
Push.instances.push(this);
this.createConnection();
}
Push.prototype.checkoutPing = function() {
var _this = this;
_this.checkoutPingTimer && clearTimeout(_this.checkoutPingTimer);
_this.checkoutPingTimer = setTimeout(function () {
_this.checkoutPingTimer = 0;
if (_this.connection.state === 'connected') {
_this.connection.send('{"event":"pusher:ping","data":{}}');
if (_this.pingTimeoutTimer) {
clearTimeout(_this.pingTimeoutTimer);
_this.pingTimeoutTimer = 0;
}
_this.pingTimeoutTimer = setTimeout(function () {
_this.connection.closeAndClean();
if (!_this.connection.doNotConnect) {
_this.connection.waitReconnect();
}
}, _this.config.pingTimeout);
}
}, this.config.heartbeat);
};
Push.prototype.channel = function (name) {
return this.channels.find(name);
};
Push.prototype.allChannels = function () {
return this.channels.all();
};
Push.prototype.createConnection = function () {
if (this.connection) {
throw Error('Connection already exist');
}
var _this = this;
var url = this.config.url;
function updateSubscribed () {
for (var i in _this.channels) {
_this.channels[i].subscribed = false;
}
}
this.connection = new Connection({
url: url,
app_key: this.config.app_key,
onOpen: function () {
_this.connection.state ='connecting';
_this.checkoutPing();
},
onMessage: function(params) {
if(_this.pingTimeoutTimer) {
clearTimeout(_this.pingTimeoutTimer);
_this.pingTimeoutTimer = 0;
}
params = JSON.parse(params.data);
var event = params.event;
var channel_name = params.channel;
if (event === 'pusher:pong') {
_this.checkoutPing();
return;
}
if (event === 'pusher:error') {
throw Error(params.data.message);
}
var data = JSON.parse(params.data), channel;
if (event === 'pusher_internal:subscription_succeeded') {
channel = _this.channels[channel_name];
channel.subscribed = true;
channel.processQueue();
channel.emit('pusher:subscription_succeeded');
return;
}
if (event === 'pusher:connection_established') {
_this.connection.socket_id = data.socket_id;
_this.connection.updateNetworkState('connected');
_this.subscribeAll();
}
if (event.indexOf('pusher_internal') !== -1) {
console.log("Event '"+event+"' not implement");
return;
}
channel = _this.channels[channel_name];
if (channel) {
channel.emit(event, data);
}
},
onClose: function () {
updateSubscribed();
},
onError: function () {
updateSubscribed();
}
});
};
Push.prototype.disconnect = function () {
this.connection.doNotConnect = 1;
this.connection.close();
};
Push.prototype.subscribeAll = function () {
if (this.connection.state !== 'connected') {
return;
}
for (var channel_name in this.channels) {
//this.connection.send(JSON.stringify({event:"pusher:subscribe", data:{channel:channel_name}}));
this.channels[channel_name].processSubscribe();
}
};
Push.prototype.unsubscribe = function (channel_name) {
if (this.channels[channel_name]) {
delete this.channels[channel_name];
if (this.connection.state === 'connected') {
this.connection.send(JSON.stringify({event:"pusher:unsubscribe", data:{channel:channel_name}}));
}
}
};
Push.prototype.unsubscribeAll = function () {
var channels = Object.keys(this.channels);
if (channels.length) {
if (this.connection.state === 'connected') {
for (var channel_name in this.channels) {
this.unsubscribe(channel_name);
}
}
}
this.channels = {};
};
Push.prototype.subscribe = function (channel_name) {
if (this.channels[channel_name]) {
return this.channels[channel_name];
}
if (channel_name.indexOf('private-') === 0) {
return createPrivateChannel(channel_name, this);
}
if (channel_name.indexOf('presence-') === 0) {
return createPresenceChannel(channel_name, this);
}
return createChannel(channel_name, this);
};
Push.instances = [];
function createChannel(channel_name, push)
{
var channel = new Channel(push.connection, channel_name);
push.channels[channel_name] = channel;
channel.subscribeCb = function () {
push.connection.send(JSON.stringify({event:"pusher:subscribe", data:{channel:channel_name}}));
}
channel.processSubscribe();
return channel;
}
function createPrivateChannel(channel_name, push)
{
var channel = new Channel(push.connection, channel_name);
push.channels[channel_name] = channel;
channel.subscribeCb = function () {
__ajax({
url: push.config.auth,
type: 'POST',
data: {channel_name: channel_name, socket_id: push.connection.socket_id},
success: function (data) {
data = JSON.parse(data);
data.channel = channel_name;
push.connection.send(JSON.stringify({event:"pusher:subscribe", data:data}));
},
error: function (e) {
throw Error(e);
}
});
};
channel.processSubscribe();
return channel;
}
function createPresenceChannel(channel_name, push)
{
return createPrivateChannel(channel_name, push);
}
/*window.addEventListener('online', function(){
var con;
for (var i in Push.instances) {
con = Push.instances[i].connection;
con.reconnectInterval = 1;
if (con.state === 'connecting') {
con.connect();
}
}
});*/
function Connection(options) {
this.dispatcher = new Dispatcher();
__extends(this, this.dispatcher);
var properies = ['on', 'off', 'emit'];
for (var i in properies) {
this[properies[i]] = this.dispatcher[properies[i]];
}
this.options = options;
this.state = 'initialized'; //initialized connecting connected disconnected
this.doNotConnect = 0;
this.reconnectInterval = 1;
this.connection = null;
this.reconnectTimer = 0;
this.connect();
}
Connection.prototype.updateNetworkState = function(state){
var old_state = this.state;
this.state = state;
if (old_state !== state) {
this.emit('state_change', { previous: old_state, current: state });
}
};
Connection.prototype.connect = function () {
this.doNotConnect = 0;
if (this.state === 'connected') {
console.log('networkState is "' + this.state + '" and do not need connect');
return;
}
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = 0;
}
this.closeAndClean();
var options = this.options;
var websocket = new WebSocket(options.url+'/app/'+options.app_key);
this.updateNetworkState('connecting');
var _this = this;
websocket.onopen = function (res) {
_this.reconnectInterval = 1;
if (_this.doNotConnect) {
_this.updateNetworkState('disconnected');
websocket.close();
return;
}
if (options.onOpen) {
options.onOpen(res);
}
};
if (options.onMessage) {
websocket.onmessage = options.onMessage;
}
websocket.onclose = function (res) {
websocket.onmessage = websocket.onopen = websocket.onclose = websocket.onerror = null;
_this.updateNetworkState('disconnected');
if (!_this.doNotConnect) {
_this.waitReconnect();
}
if (options.onClose) {
options.onClose(res);
}
};
websocket.onerror = function (res) {
_this.close();
if (!_this.doNotConnect) {
_this.waitReconnect();
}
if (options.onError) {
options.onError(res);
}
};
this.connection = websocket;
}
Connection.prototype.closeAndClean = function () {
if(this.connection) {
var websocket = this.connection;
websocket.onmessage = websocket.onopen = websocket.onclose = websocket.onerror = null;
try {
websocket.close();
} catch (e) {}
this.updateNetworkState('disconnected');
}
};
Connection.prototype.waitReconnect = function () {
if (this.state === 'connected' || this.state === 'connecting') {
return;
}
if (!this.doNotConnect) {
this.updateNetworkState('connecting');
var _this = this;
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
}
this.reconnectTimer = setTimeout(function(){
_this.connect();
}, this.reconnectInterval);
if (this.reconnectInterval < 1000) {
this.reconnectInterval = 1000;
} else {
// 每次重连间隔增大一倍
this.reconnectInterval = this.reconnectInterval * 2;
}
// 有网络的状态下重连间隔最大2秒
if (this.reconnectInterval > 2000 && navigator.onLine) {
_this.reconnectInterval = 2000;
}
}
}
Connection.prototype.send = function(data) {
if (this.state !== 'connected') {
console.trace('networkState is "' + this.state + '", can not send ' + data);
return;
}
this.connection.send(data);
}
Connection.prototype.close = function(){
this.updateNetworkState('disconnected');
this.connection.close();
}
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) {d[p] = b[p];}
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
function Channel(connection, channel_name) {
this.subscribed = false;
this.dispatcher = new Dispatcher();
this.connection = connection;
this.channelName = channel_name;
this.subscribeCb = null;
this.queue = [];
__extends(this, this.dispatcher);
var properies = ['on', 'off', 'emit'];
for (var i in properies) {
this[properies[i]] = this.dispatcher[properies[i]];
}
}
Channel.prototype.processSubscribe = function () {
if (this.connection.state !== 'connected') {
return;
}
this.subscribeCb();
};
Channel.prototype.processQueue = function () {
if (this.connection.state !== 'connected' || !this.subscribed) {
return;
}
for (var i in this.queue) {
this.queue[i]();
}
this.queue = [];
};
Channel.prototype.trigger = function (event, data) {
if (event.indexOf('client-') !== 0) {
throw new Error("Event '" + event + "' should start with 'client-'");
}
var _this = this;
this.queue.push(function () {
_this.connection.send(JSON.stringify({ event: event, data: data, channel: _this.channelName }));
});
this.processQueue();
};
////////////////
var Collections = (function () {
var exports = {};
function extend(target) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
for (var i = 0; i < sources.length; i++) {
var extensions = sources[i];
for (var property in extensions) {
if (extensions[property] && extensions[property].constructor &&
extensions[property].constructor === Object) {
target[property] = extend(target[property] || {}, extensions[property]);
}
else {
target[property] = extensions[property];
}
}
}
return target;
}
exports.extend = extend;
function stringify() {
var m = ["Push"];
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] === "string") {
m.push(arguments[i]);
}
else {
m.push(safeJSONStringify(arguments[i]));
}
}
return m.join(" : ");
}
exports.stringify = stringify;
function arrayIndexOf(array, item) {
var nativeIndexOf = Array.prototype.indexOf;
if (array === null) {
return -1;
}
if (nativeIndexOf && array.indexOf === nativeIndexOf) {
return array.indexOf(item);
}
for (var i = 0, l = array.length; i < l; i++) {
if (array[i] === item) {
return i;
}
}
return -1;
}
exports.arrayIndexOf = arrayIndexOf;
function objectApply(object, f) {
for (var key in object) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
f(object[key], key, object);
}
}
}
exports.objectApply = objectApply;
function keys(object) {
var keys = [];
objectApply(object, function (_, key) {
keys.push(key);
});
return keys;
}
exports.keys = keys;
function values(object) {
var values = [];
objectApply(object, function (value) {
values.push(value);
});
return values;
}
exports.values = values;
function apply(array, f, context) {
for (var i = 0; i < array.length; i++) {
f.call(context || (window), array[i], i, array);
}
}
exports.apply = apply;
function map(array, f) {
var result = [];
for (var i = 0; i < array.length; i++) {
result.push(f(array[i], i, array, result));
}
return result;
}
exports.map = map;
function mapObject(object, f) {
var result = {};
objectApply(object, function (value, key) {
result[key] = f(value);
});
return result;
}
exports.mapObject = mapObject;
function filter(array, test) {
test = test || function (value) {
return !!value;
};
var result = [];
for (var i = 0; i < array.length; i++) {
if (test(array[i], i, array, result)) {
result.push(array[i]);
}
}
return result;
}
exports.filter = filter;
function filterObject(object, test) {
var result = {};
objectApply(object, function (value, key) {
if ((test && test(value, key, object, result)) || Boolean(value)) {
result[key] = value;
}
});
return result;
}
exports.filterObject = filterObject;
function flatten(object) {
var result = [];
objectApply(object, function (value, key) {
result.push([key, value]);
});
return result;
}
exports.flatten = flatten;
function any(array, test) {
for (var i = 0; i < array.length; i++) {
if (test(array[i], i, array)) {
return true;
}
}
return false;
}
exports.any = any;
function all(array, test) {
for (var i = 0; i < array.length; i++) {
if (!test(array[i], i, array)) {
return false;
}
}
return true;
}
exports.all = all;
function encodeParamsObject(data) {
return mapObject(data, function (value) {
if (typeof value === "object") {
value = safeJSONStringify(value);
}
return encodeURIComponent(base64_1["default"](value.toString()));
});
}
exports.encodeParamsObject = encodeParamsObject;
function buildQueryString(data) {
var params = filterObject(data, function (value) {
return value !== undefined;
});
return map(flatten(encodeParamsObject(params)), util_1["default"].method("join", "=")).join("&");
}
exports.buildQueryString = buildQueryString;
function decycleObject(object) {
var objects = [], paths = [];
return (function derez(value, path) {
var i, name, nu;
switch (typeof value) {
case 'object':
if (!value) {
return null;
}
for (i = 0; i < objects.length; i += 1) {
if (objects[i] === value) {
return {$ref: paths[i]};
}
}
objects.push(value);
paths.push(path);
if (Object.prototype.toString.apply(value) === '[object Array]') {
nu = [];
for (i = 0; i < value.length; i += 1) {
nu[i] = derez(value[i], path + '[' + i + ']');
}
}
else {
nu = {};
for (name in value) {
if (Object.prototype.hasOwnProperty.call(value, name)) {
nu[name] = derez(value[name], path + '[' + JSON.stringify(name) + ']');
}
}
}
return nu;
case 'number':
case 'string':
case 'boolean':
return value;
}
}(object, '$'));
}
exports.decycleObject = decycleObject;
function safeJSONStringify(source) {
try {
return JSON.stringify(source);
}
catch (e) {
return JSON.stringify(decycleObject(source));
}
}
exports.safeJSONStringify = safeJSONStringify;
return exports;
})();
var Dispatcher = (function () {
function Dispatcher(failThrough) {
this.callbacks = new CallbackRegistry();
this.global_callbacks = [];
this.failThrough = failThrough;
}
Dispatcher.prototype.on = function (eventName, callback, context) {
this.callbacks.add(eventName, callback, context);
return this;
};
Dispatcher.prototype.on_global = function (callback) {
this.global_callbacks.push(callback);
return this;
};
Dispatcher.prototype.off = function (eventName, callback, context) {
this.callbacks.remove(eventName, callback, context);
return this;
};
Dispatcher.prototype.emit = function (eventName, data) {
var i;
for (i = 0; i < this.global_callbacks.length; i++) {
this.global_callbacks[i](eventName, data);
}
var callbacks = this.callbacks.get(eventName);
if (callbacks && callbacks.length > 0) {
for (i = 0; i < callbacks.length; i++) {
callbacks[i].fn.call(callbacks[i].context || (window), data);
}
}
else if (this.failThrough) {
this.failThrough(eventName, data);
}
return this;
};
return Dispatcher;
}());
var CallbackRegistry = (function () {
function CallbackRegistry() {
this._callbacks = {};
}
CallbackRegistry.prototype.get = function (name) {
return this._callbacks[prefix(name)];
};
CallbackRegistry.prototype.add = function (name, callback, context) {
var prefixedEventName = prefix(name);
this._callbacks[prefixedEventName] = this._callbacks[prefixedEventName] || [];
this._callbacks[prefixedEventName].push({
fn: callback,
context: context
});
};
CallbackRegistry.prototype.remove = function (name, callback, context) {
if (!name && !callback && !context) {
this._callbacks = {};
return;
}
var names = name ? [prefix(name)] : Collections.keys(this._callbacks);
if (callback || context) {
this.removeCallback(names, callback, context);
}
else {
this.removeAllCallbacks(names);
}
};
CallbackRegistry.prototype.removeCallback = function (names, callback, context) {
Collections.apply(names, function (name) {
this._callbacks[name] = Collections.filter(this._callbacks[name] || [], function (oning) {
return (callback && callback !== oning.fn) ||
(context && context !== oning.context);
});
if (this._callbacks[name].length === 0) {
delete this._callbacks[name];
}
}, this);
};
CallbackRegistry.prototype.removeAllCallbacks = function (names) {
Collections.apply(names, function (name) {
delete this._callbacks[name];
}, this);
};
return CallbackRegistry;
}());
function prefix(name) {
return "_" + name;
}
function __ajax(options){
options=options||{};
options.type=(options.type||'GET').toUpperCase();
options.dataType=options.dataType||'json';
params=formatParams(options.data);
var xhr;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}else{
xhr=ActiveXObject('Microsoft.XMLHTTP');
}
xhr.onreadystatechange=function(){
if(xhr.readyState === 4){
var status=xhr.status;
if(status>=200 && status<300){
options.success&&options.success(xhr.responseText,xhr.responseXML);
}else{
options.error&&options.error(status);
}
}
}
if(options.type==='GET'){
xhr.open('GET',options.url+'?'+params,true);
xhr.send(null);
}else if(options.type==='POST'){
xhr.open('POST',options.url,true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params);
}
}
function formatParams(data){
var arr=[];
for(var name in data){
arr.push(encodeURIComponent(name)+'='+encodeURIComponent(data[name]));
}
return arr.join('&');
}
// export const push = {
// a:6
// }

View File

@ -51,7 +51,7 @@ const setForm = (e) => {
}; };
const setRePay = (e) => { const setRePay = (e) => {
form.value.order_price = e.price; form.value.total = e.price;
order_id.value = e.order_id; order_id.value = e.order_id;
}; };
@ -88,7 +88,7 @@ const handleEnter = () => {
if (order_id.value) orderPay(order_id.value); if (order_id.value) orderPay(order_id.value);
else { else {
let pay_type; let pay_type;
if (regexWechat.test(input.value)) pay_type = "micropay"; if (regexWechat.test(input.value)) pay_type = "9";
else if (regexPay.test(input.value)) pay_type = "alipayBar"; else if (regexPay.test(input.value)) pay_type = "alipayBar";
else { else {
loading.value = false; loading.value = false;
@ -102,16 +102,15 @@ const handleEnter = () => {
cart_id: cart_id.value, cart_id: cart_id.value,
pay_type: pay_type, pay_type: pay_type,
auth_code: input.value, auth_code: input.value,
staff_id: userStore.userInfo.service.service_id,
}) })
.then((res) => { .then((res) => {
if (res.status == 200 && (res.message == "支付成功" || res.message == "success")) { if (res.data.trade_state == 'SUCCESS') {
drawer.value = false; drawer.value = false;
ElMessage({ ElMessage({
message: res.message=='success'?'支付成功':res.message, message: res.data.trade_state_desc || '支付成功',
type: "success", type: "success",
}); });
audioplay(res.data.message||res.data.result.message); if(res.data.message) audioplay(res.data.message);
beforeClose(); beforeClose();
} else { } else {
if (!res.data.group_order_sn) { if (!res.data.group_order_sn) {
@ -160,13 +159,13 @@ const orderPay = (id) => {
}; };
orderPayApi(id, query) orderPayApi(id, query)
.then((res) => { .then((res) => {
if (res.status == 200 && (res.message == "支付成功" || res.message == "success")) { if (res.data.trade_state == 'SUCCESS') {
drawer.value = false; drawer.value = false;
ElMessage({ ElMessage({
message: res.message=='success'?'支付成功':res.message, message: res.message=='success'?'支付成功':res.message,
type: "success", type: "success",
}); });
audioplay(res.data.message||res.data.result.message); if(res.data.message) audioplay(res.data.message);
beforeClose(); beforeClose();
} else { } else {
order_id.value = res.data.group_order_id; order_id.value = res.data.group_order_id;
@ -193,16 +192,16 @@ const getOrderStatus = (id) => {
order_sn: id, order_sn: id,
}) })
.then((res) => { .then((res) => {
if (res.data.paid == 1 || res.message == "支付成功") { if (res.data.trade_state == 'SUCCESS') {
ElMessage({ ElMessage({
message: res.message, message: res.message,
type: "success", type: "success",
}); });
audioplay(res.data.message); if(res.data.message) audioplay(res.data.message);
beforeClose(); beforeClose();
} else { } else {
ElMessage({ ElMessage({
message: res.message, message: res.data.trade_state=='USERPAYING' ? '用户正在支付中' : res.message,
type: "error", type: "error",
}); });
input.value = ""; input.value = "";
@ -256,7 +255,7 @@ const collection = ref(""); //输入的金额
const changePrice = computed(() => { const changePrice = computed(() => {
// //
if (+collection.value > 0) { if (+collection.value > 0) {
return (collection.value - form.value.order_price).toFixed(2); return (collection.value - form.value.total).toFixed(2);
} }
return -1; return -1;
}); });
@ -298,26 +297,24 @@ const cashBnt = () => {
changePrice.value === "" || changePrice.value === "" ||
changePrice.value === null || changePrice.value === null ||
changePrice.value === undefined || changePrice.value === undefined ||
+collection.value < +form.value.order_price +collection.value < +form.value.total
) return ElMessage.error("收款金额应该大于等于应收金额"); ) return ElMessage.error("收款金额应该大于等于应收金额");
if (order_id.value) orderPay(order_id.value); if (order_id.value) orderPay(order_id.value);
else else
orderCreateApi({ orderCreateApi({
address_id: "", address_id: "",
key: form.value.key,
cart_id: cart_id.value, cart_id: cart_id.value,
pay_type: "cash_payment", pay_type: "cash_payment",
staff_id: userStore.userInfo.service.service_id,
}) })
.then((res) => { .then((res) => {
if (res.status == 200 && res.message == "支付成功") { if (res.data.trade_state == 'SUCCESS') {
drawer.value = false; drawer.value = false;
ElMessage({ ElMessage({
message: res.message, message: res.message,
type: "success", type: "success",
}); });
changeActive(1); changeActive(1);
audioplay(res.data.message); if(res.data.message) audioplay(res.data.message);
beforeClose(); beforeClose();
} else { } else {
if (!res.data.group_order_sn) { if (!res.data.group_order_sn) {
@ -462,7 +459,7 @@ onUnmounted(() => {
</div> </div>
<div style="color: #999; padding: 2rem 0 0.3rem 0">应收金额():</div> <div style="color: #999; padding: 2rem 0 0.3rem 0">应收金额():</div>
<div style="color: #f5222d; padding-bottom: 2rem"> <div style="color: #f5222d; padding-bottom: 2rem">
¥<span style="font-size: 1.6rem">{{ form.order_price }}</span> ¥<span style="font-size: 1.6rem">{{ form.total }}</span>
</div> </div>
<div <div
v-loading="loading" v-loading="loading"
@ -513,7 +510,7 @@ onUnmounted(() => {
><el-icon><Delete /></el-icon ><el-icon><Delete /></el-icon
></el-button> ></el-button>
<el-button @click="delNum(-1)">C</el-button> <el-button @click="delNum(-1)">C</el-button>
<el-button class="enter" :class="{'enter-disable': +collection < +form.order_price}" :disabled="+collection < +form.order_price" @click="cashBnt"> <el-button class="enter" :class="{'enter-disable': +collection < +form.total}" :disabled="+collection < +form.total" @click="cashBnt">
确认 确认
</el-button> </el-button>
</div> </div>

View File

@ -3,9 +3,28 @@ import myHeader from "./myHeader.vue";
import myAside from "./myAside.vue"; import myAside from "./myAside.vue";
import { ref, nextTick, onMounted, onUnmounted } from "vue"; import { ref, nextTick, onMounted, onUnmounted } from "vue";
import mitt from "@/utils/mitt.js"; import mitt from "@/utils/mitt.js";
import { useUserStore } from "@/store/user.js";
import { Push } from "@/common/push.js";
const userStore = useUserStore();
const connection = new Push({
url: import.meta.env.VITE_PUSH_URL, // websocket
app_key: '2ce3ce22329517213caa7dad261f5695',
});
// user-1
const user_channel = connection.subscribe(`user-${userStore.userInfo.id}`);
// const user_channel = connection.subscribe(`user-${1}`);
// user-2message
user_channel.on('message', function (data) {
console.log("收到消息--",data, JSON.parse(data.content));
});
// 线
user_channel.on('close', function () {
});
const KeyboardEvent = (e)=>{ const KeyboardEvent = (e)=>{
console.log('按下', e.keyCode); console.log('按下', e.keyCode);

View File

@ -10,14 +10,10 @@ const navTo = (name) => {
router.push({ name }); router.push({ name });
}; };
const list = ref([ const list = ref([
{ name: "home", title: "收银", ico: "Sell", count: 0 }, { name: "saleHome", title: "收银", ico: "Sell", count: 0 },
{ name: "order", title: "收银订单", ico: "DataLine", count: 0 }, { name: "saleOrder", title: "收银订单", ico: "DataLine", count: 0 },
{ name: "orderSystem", title: "平台订单", ico: "DataAnalysis", count: 0 }, { name: "order", title: "待提采购", ico: "DataAnalysis", count: 0 },
{ name: "saleHome", title: "批发", ico: "Van", count: 0 }, { name: "orderSystem", title: "采购订单", ico: "Tickets", count: 0 },
{ name: "saleOrder", title: "批发订单", ico: "Tickets", count: 0 },
{ name: "convert", title: "核销", ico: "FullScreen", count: 0 },
{ name: "shop", title: "商品", ico: "ShoppingBag", count: 0 },
{ name: "orderCount", title: "订单统计", ico: "PieChart", count: 0 },
]); ]);
const aup = () => { const aup = () => {
let index = list.value.findIndex((item) => item.name == route.name); let index = list.value.findIndex((item) => item.name == route.name);

View File

@ -3,7 +3,7 @@ import { useUserStore } from "@/store/user.js";
import { ref } from "vue"; import { ref } from "vue";
import { info, logout } from "@/api/user.js"; import { info, logout } from "@/api/user.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useRouter } from 'vue-router' import { useRouter } from "vue-router";
const userStore = useUserStore(); const userStore = useUserStore();
@ -12,25 +12,18 @@ merInfo.value = userStore.userInfo;
const router = useRouter(); const router = useRouter();
const onLogout = () => { const onLogout = () => {
logout().then(() => {
userStore.setUserInfo({}); userStore.setUserInfo({});
userStore.setToken(""); userStore.setToken("");
router.push("/login"); router.push("/login");
}).catch(() => { };
ElMessage({
message: "退出失败",
type: "error",
})
});
}
</script> </script>
<template> <template>
<div class="my-card"> <div class="my-card">
<div class="card-header"> <div class="card-header">
<div style="width: 4.5rem;"> <div style="width: 4.5rem">
<el-image style="height: 2.5rem;width: 2.5rem;margin: 0 auto;" <el-image
style="height: 2.5rem; width: 2.5rem; margin: 0 auto"
src="https://lihai001.oss-cn-chengdu.aliyuncs.com/def/12c93202404101530591311.png" src="https://lihai001.oss-cn-chengdu.aliyuncs.com/def/12c93202404101530591311.png"
></el-image> ></el-image>
</div> </div>
@ -39,7 +32,7 @@ const onLogout = () => {
<div class="card-body"> <div class="card-body">
<el-dropdown trigger="hover"> <el-dropdown trigger="hover">
<div class="el-dropdown-link"> <div class="el-dropdown-link">
<el-avatar :src="merInfo.avatar" icon="user-filled"/> <el-avatar :src="merInfo.avatar" icon="user-filled" />
<div class="info"> <div class="info">
<div> <div>
{{ merInfo.nickname }} {{ merInfo.nickname }}
@ -75,12 +68,12 @@ const onLogout = () => {
} }
} }
} }
.el-dropdown-link{ .el-dropdown-link {
width: auto; width: auto;
display: flex; display: flex;
color: #fff; color: #fff;
align-items: center; align-items: center;
.info{ .info {
margin: 0 0.5rem; margin: 0 0.5rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -88,7 +81,7 @@ const onLogout = () => {
height: 100%; height: 100%;
} }
} }
.el-dropdown{ .el-dropdown {
border: none; border: none;
} }
</style> </style>

View File

@ -62,7 +62,7 @@ const routes = [
path: '/convert', path: '/convert',
name: 'convert', name: 'convert',
component: () => import('@/views/convert/index.vue'), component: () => import('@/views/convert/index.vue'),
} },
] ]
}, },
{ {
@ -70,6 +70,11 @@ const routes = [
name: 'login', name: 'login',
component: () => import('@/views/login/index.vue'), component: () => import('@/views/login/index.vue'),
}, },
{
path: '/test',
name: 'test',
component: () => import('@/views/test/test.vue'),
},
// 注意:通配符路由要放在最后 // 注意:通配符路由要放在最后
{ {
path: '/:catchAll(.*)', path: '/:catchAll(.*)',

View File

@ -6,7 +6,7 @@ import config from "@/config";
const request = axios.create({ const request = axios.create({
baseURL: config.url, baseURL: config.url,
timeout: 10000 timeout: 60000
}) })
@ -32,7 +32,7 @@ request.interceptors.request.use(
request.interceptors.response.use( request.interceptors.response.use(
response => { response => {
// 对响应数据做些什么,例如解析数据、统一处理错误等 // 对响应数据做些什么,例如解析数据、统一处理错误等
if (response.data.status === 401 || response.data.status === 40000) { if (response.data.status === 401 || response.data.status === 40000 || (response.data.code === -1 && response.data.msg === '登录超时,请重新登录')) {
ElMessage({ ElMessage({
message: response.data.message, message: response.data.message,
type: 'error', type: 'error',
@ -51,6 +51,12 @@ request.interceptors.response.use(
}) })
throw new Error(response.data.message); throw new Error(response.data.message);
} }
if (response.data.show) {
ElMessage({
message: response.data.msg,
type: 'error',
})
}
return response.data; return response.data;
}, },
error => { error => {

View File

@ -12,8 +12,8 @@ const accRef = ref(null);
const pwdRef = ref(null); const pwdRef = ref(null);
const formLogin = ref({ const formLogin = ref({
account: "xiao123", account: "",
password: "123456", password: "",
terminal: 3, terminal: 3,
scene: 1, scene: 1,
}); });
@ -31,11 +31,12 @@ const onLogin = () => {
}); });
login(formLogin.value) login(formLogin.value)
.then((res) => { .then((res) => {
console.log(res);
if (res.data?.token) { if (res.data?.token) {
if(!res.data.merchant||!res.data.merchant.service_phone) return ElMessage.error("请先完善商户信息");
userStore.setToken(res.data.token); userStore.setToken(res.data.token);
userStore.setUserInfo(res.data); userStore.setUserInfo(res.data);
router.push("/"); router.push("/");
// router.push("/test");
} }
}) })
.catch((err) => {}); .catch((err) => {});

View File

@ -1,10 +1,11 @@
<script setup> <script setup>
import { ref } from "vue"; import { onMounted, onUnmounted, ref } from "vue";
import { import {
orderListApi, orderListApi,
orderStatusApi, orderStatusApi,
orderLadingApi, orderLadingApi,
cartListApi, cartListApi,
cashierinfoListApi,
} from "@/api/store.js"; } from "@/api/store.js";
import { useUserStore } from "@/store/user.js"; import { useUserStore } from "@/store/user.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
@ -15,9 +16,8 @@ import pay from "@/components/pay.vue";
const userStore = useUserStore(); const userStore = useUserStore();
const router = useRouter(); const router = useRouter();
const formData = ref({}); const formData = ref({
mitt.on("set-order-detail", (res) => { id: "",
formData.value = res;
}); });
const list = ref([]); const list = ref([]);
@ -39,7 +39,7 @@ const orderLading = () => {
dialogVisible.value = false; dialogVisible.value = false;
orderLadingApi({ orderLadingApi({
order_sn: orderLadingSn.value, order_sn: orderLadingSn.value,
staff_id: userStore.userInfo.service.service_id staff_id: userStore.userInfo.service.service_id,
}).then((res) => { }).then((res) => {
ElMessage({ ElMessage({
message: res.message, message: res.message,
@ -69,7 +69,7 @@ const getOrderStatus = (id) => {
message: res.message, message: res.message,
type: "success", type: "success",
}); });
mitt.emit("update-order-detail", {}); mitt.emit("update-c-order-detail", {});
formData.value.paid = 1; formData.value.paid = 1;
} else { } else {
ElMessage({ ElMessage({
@ -80,85 +80,80 @@ const getOrderStatus = (id) => {
}) })
.catch((err) => {}); .catch((err) => {});
}; };
const where = ref({
page_no: 1,
page_size: 15,
loadend: false,
loading: false,
});
const goods_list = ref([]);
const getOrderList = () => {
console.log("触底");
if (formData.value.id && !where.value.loadend) {
console.log("加载");
where.value.loading = true;
cashierinfoListApi({
pid: formData.value.id,
page_no: where.value.page_no,
page_size: where.value.page_size,
}).then((res) => {
goods_list.value = [...goods_list.value, ...res.data.lists];
if (res.data.lists.length < where.value.page_size)
where.value.loadend = true;
where.value.loading = false;
where.value.page_no++;
});
}
};
onMounted(() => {
mitt.on("set-c-order-detail", (res) => {
formData.value = res;
where.value.page_no = 1;
where.value.loadend = false;
where.value.loading = false;
goods_list.value = [];
getOrderList();
});
});
onUnmounted(() => {
mitt.off("set-c-order-detail");
});
</script> </script>
<template> <template>
<div class="my-order"> <div class="my-order">
<div class="header-nav">
<div
v-for="(item, index) in activeStoreList"
:key="index"
class="nav-item"
:class="{
'nav-item-active': activeStore == index,
'nav-item-radius1': activeStore == index + 1,
'nav-item-radius2': activeStore == index - 1,
}"
@click="activeStore = index"
>
{{ item }}
</div>
<div
class="nav-item"
:class="{
'nav-item-radius2': activeStore == activeStoreList.length - 1,
}"
style="flex: 1"
></div>
</div>
<div class="detail" v-loading="loading"> <div class="detail" v-loading="loading">
<div class="table" v-if="formData.orderProduct && activeStore == 0"> <div
<div style="font-size: 0.9rem"> class="table"
共计 v-loading="loading"
<span style="color: #ff4a00">{{ formData.total_num }}</span> 件商品 v-infinite-scroll="getOrderList"
</div> infinite-scroll-distance="300"
<el-table infinite-scroll-delay="300"
style="height: calc(100vh - 100px - 14rem)" style="overflow: auto"
:data="formData.orderProduct" :infinite-scroll-immediate="false"
> >
<el-table-column prop="cart_info.product.store_name" label="商品信息">
<template #default="{ row }">
<div style="display: flex; align-items: center">
<el-image
style="height: 3rem; width: 3rem"
:src="
row.cart_info.productAttr.image ||
row.cart_info.product.image
"
></el-image>
<span style="margin-left: 0.5rem">{{
row.cart_info.product.store_name
}}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop="cart_info.productAttr.price"
label="单价"
width="150"
/>
<el-table-column prop="product_num" label="数量" width="150" />
<el-table-column prop="total_price" label="总价" width="150" />
</el-table>
</div>
<div class="table" v-if="formData.orderProduct && activeStore == 1">
<div class="table-title">订单信息</div> <div class="table-title">订单信息</div>
<div class="table-info"> <div class="table-info">
<div class="info-item"> <div class="info-item">
<div class="info-item-title">创建时间:</div> <div class="info-item-title">订单编号:</div>
<div class="info-item-info">{{ formData.create_time }}</div> <div class="info-item-info">{{ formData.number }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">商品:</div> <div class="info-item-title">商品款数:</div>
<div class="info-item-info">{{ formData.total_num }}</div> <div class="info-item-info">{{ formData.goods_count }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">商品总价:</div> <div class="info-item-title">商品总价:</div>
<div class="info-item-info">¥{{ formData.total_price }}</div> <div class="info-item-info">¥{{ formData.total }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">支付时间:</div> <div class="info-item-title">创建时间:</div>
<div class="info-item-info">{{ formData.pay_time }}</div> <div class="info-item-info">{{ formData.create_time }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">优惠抵扣:</div> <div class="info-item-title">优惠抵扣:</div>
@ -166,95 +161,72 @@ const getOrderStatus = (id) => {
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">实际支付:</div> <div class="info-item-title">实际支付:</div>
<div class="info-item-info">¥{{ formData.pay_price }}</div> <div class="info-item-info">¥{{ formData.actual }}</div>
</div>
<div class="info-item">
<div class="info-item-title">支付时间:</div>
<div class="info-item-info">{{ formData.update_time }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">支付方式:</div> <div class="info-item-title">支付方式:</div>
<div class="info-item-info"> <div class="info-item-info">
<span v-if="formData.pay_type == 11">微信收款</span> <span v-if="formData.pay_type == 9">微信收款</span>
<span v-if="formData.pay_type == 12">现金支付</span> <span v-if="formData.pay_type == 1">余额支付</span>
<span v-if="formData.pay_type == 13">支付宝收款</span> <span v-if="formData.pay_type == 3">微信支付</span>
<span v-if="formData.pay_type == 0">余额支付</span>
<span v-if="formData.pay_type == 1">微信支付</span>
<span v-if="formData.pay_type == 9">商户余额支付</span>
<span v-if="formData.pay_type == 10">对公转账</span>
</div> </div>
</div> </div>
</div> </div>
<div class="table-title" v-if="formData.service_info">收银员信息</div> <div class="table-title">收货人信息</div>
<div <div
class="table-info" class="table-info"
v-if="formData.service_info" v-if="formData.user_phone"
style="flex-direction: column" style="flex-direction: column"
> >
<div class="info-item"> <div class="info-item">
<div class="info-item-title">头像:</div> <div class="info-item-title">收货人:</div>
<div class="info-item-info"> <div class="info-item-info">
{{ formData.real_name }}
</div>
</div>
<div class="info-item">
<div class="info-item-title">联系方式:</div>
<div class="info-item-info">
{{ formData.user_phone }}
</div>
</div>
<div class="info-item">
<div class="info-item-title">收货地址:</div>
<div class="info-item-info">
{{ formData.user_address }}
</div>
</div>
</div>
<div v-else class="add-address">
<el-button type="primary" @click="addAddress()" size="Large" >点击添加收货地址</el-button>
</div>
<div style="font-size: 0.9rem">
共计
<span style="color: #ff4a00">{{ formData.goods_count }}</span> 款商品
</div>
<el-table :data="goods_list">
<el-table-column label="商品信息">
<template #default="{ row }">
<div style="display: flex; align-items: center">
<el-image <el-image
style="height: 4rem; width: 4rem; border-radius: 50%" style="height: 3rem; width: 3rem"
:src="formData.service_info.avatar" :src="row.imgs"
></el-image> ></el-image>
</div> <span style="margin-left: 0.5rem">{{ row.goods_name }}</span>
</div>
<div class="info-item">
<div class="info-item-title">昵称:</div>
<div class="info-item-info">
{{ formData.service_info.nickname }}
</div>
</div>
<div class="info-item">
<div class="info-item-title">账号:</div>
<div class="info-item-info">
{{ formData.service_info.account }}
</div>
</div>
</div>
</div>
<div class="footer" v-if="formData.service_info">
<div class="info">
<div class="ser">收银员: {{ formData.service_info.nickname }}</div>
<div class="price">
实付: <span>¥{{ formData.pay_price }}</span>
</div>
</div>
<div class="handle" v-if="!formData.paid">
<el-button class="btn" type="primary" @click="rePay(formData)"
>重新支付</el-button
>
<el-button
class="btn"
type="primary"
@click="getOrderStatus(formData.order_sn)"
>检测状态</el-button
>
<el-button
class="btn"
type="success"
@click="orderLadingComfirm(formData.order_sn)"
>提单</el-button
>
</div>
<div class="handle" v-else>已支付</div>
</div>
</div>
<pay ref="payRef" />
<el-dialog v-model="dialogVisible" title="提示" width="500">
<span
>提单前请清空购物车, 避免提单的商品与购物车商品混合,
请确保购物车内无数据后再进行提单</span
>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-if="cartCount > 0" @click="goHome">
前去清空购物车
</el-button>
<el-button v-else type="primary" @click="orderLading">
确认提单
</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-table-column>
<el-table-column prop="price" label="单价" width="150" />
<el-table-column prop="nums" label="数量" width="150" />
<el-table-column prop="total" label="总价" width="150">
</el-table-column>
</el-table>
</div>
</div>
</div> </div>
</template> </template>
@ -267,36 +239,6 @@ const getOrderStatus = (id) => {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
.header-nav {
display: flex;
background: linear-gradient(
to bottom,
#f5f5f5 50%,
#fff 50%
); /* 创建渐变背景 */
.nav-item {
height: 4rem;
width: 8rem;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
background-color: #f5f5f5;
border-radius: 1rem 1rem 0 0;
}
.nav-item-active {
background-color: #fff;
position: relative;
transition: 300ms;
}
.nav-item-radius1 {
border-radius: 0 0 1rem 0;
}
.nav-item-radius2 {
border-radius: 0 0 0 1rem;
}
}
.detail { .detail {
height: calc(100vh - 100px - 4rem); height: calc(100vh - 100px - 4rem);
box-sizing: border-box; box-sizing: border-box;
@ -305,17 +247,23 @@ const getOrderStatus = (id) => {
.table { .table {
padding: 1rem; padding: 1rem;
padding-bottom: 6rem; padding-bottom: 6rem;
overflow-y: auto;
height: 100%;
.table-title { .table-title {
font-weight: bold; font-weight: bold;
padding-top: 1rem; }
.add-address{
margin-top: 1rem;
margin-bottom: 1.5rem;
} }
.table-info { .table-info {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
color: #777; color: #777;
font-size: 0.9rem; font-size: 0.9rem;
padding-bottom: 2rem; padding-bottom: 1rem;
margin-bottom: 1rem;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
&:last-child { &:last-child {
@ -333,43 +281,6 @@ const getOrderStatus = (id) => {
} }
} }
} }
.footer {
height: 6rem;
box-sizing: border-box;
padding: 0 1.5rem;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
box-shadow: 0 -1px 0.625rem #eee;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
.info {
display: flex;
align-items: flex-end;
.ser {
font-weight: bold;
margin-right: 1rem;
}
.price {
margin-right: 1rem;
span {
color: #ff4a00;
font-size: 1.2rem;
font-weight: bold;
}
}
}
.handle {
.btn {
border-radius: 4rem;
padding: 1.2rem;
}
}
}
} }
} }
</style> </style>

View File

@ -1,30 +1,34 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import { import {
orderListApi, orderListApi,
orderStatusApi, orderStatusApi,
orderLadingApi, orderLadingApi,
cartListApi, cartListApi,
saleOrderListApi,
createOrderApi
} from "@/api/store.js"; } from "@/api/store.js";
import { useUserStore } from "@/store/user.js"; import { useUserStore } from "@/store/user.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useRouter, useRoute } from "vue-router"; import { useRouter } from "vue-router";
import mitt from "@/utils/mitt.js"; import mitt from "@/utils/mitt.js";
import moment from "moment"; import moment from "moment";
const route = useRoute();
const userStore = useUserStore(); const userStore = useUserStore();
const props = defineProps({ const props = defineProps({
isSystem: { isSystem: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
source: {
type: Number,
default: 0,
},
}); });
const list = ref([]); const lists = ref([]);
const tabPosition = ref(1); // 1-, 2- const tabPosition = ref(1); // 1-, 2-
const payType = ref(0); //
const changeTabPosition = (e) => { const changeTabPosition = (e) => {
where.value.page_no = 1; where.value.page_no = 1;
loadEnd.value = false; loadEnd.value = false;
@ -35,29 +39,17 @@ const changeTabPosition = (e) => {
const payRef = ref(null); const payRef = ref(null);
const date = ref(""); const changeDate = (e) => {
const changeDate = () => {
where.value.date = date.value.join("-");
getOrderList(true); getOrderList(true);
}; };
const where = ref({ const where = ref({
page_no: 1, page_no: 1,
page_size: 20, page_size: 20,
search_info: "", number: "",
date: "", date: moment(new Date()).format("YYYY-MM-DD"),
staff_id: 0, source: props.source,
}); });
if (route.query.date) {
date.value = [
moment(route.query.date).format("YYYY/MM/DD"),
moment(route.query.date).format("YYYY/MM/DD"),
];
where.value.date = date.value.join("-");
}
if(route.query.payType){
payType.value = route.query.payType;
}
const loading = ref(false); const loading = ref(false);
const total = ref(0); const total = ref(0);
@ -68,24 +60,17 @@ const orderList = ref([]);
const getOrderList = (reload = false) => { const getOrderList = (reload = false) => {
if (reload) where.value.page_no = 1; if (reload) where.value.page_no = 1;
else if (loadEnd.value || loading.value) return; else if (loadEnd.value || loading.value) return;
if (!props.isSystem) {
where.value.staff_id = userStore.userInfo.service.service_id;
if (payType.value == 1) where.value.pay_type = "12";
else if (payType.value == 2) where.value.pay_type = "11,13";
else where.value.pay_type = "";
}
loading.value = true; loading.value = true;
if (tabPosition.value == 1) where.value.paid = null; if (tabPosition.value == 1) where.value.paid = null;
if (tabPosition.value == 2) where.value.paid = 0; if (tabPosition.value == 2) where.value.paid = 0;
orderListApi(userStore.userInfo.service.mer_id, where.value) orderListApi(where.value)
.then((res) => { .then((res) => {
if (reload) orderList.value = res.data.list; if (reload) orderList.value = res.data.lists;
else orderList.value = [...orderList.value, ...res.data.list]; else orderList.value = [...orderList.value, ...res.data.lists];
if (res.data.list.length < where.value.page_size) loadEnd.value = true; if (res.data.lists.length < where.value.page_size) loadEnd.value = true;
else where.value.page_no++; else where.value.page_no++;
activeStore.value = 0; activeStore.value = 0;
if (orderList.value.length > 0) mitt.emit("set-c-order-detail", orderList.value[0]);
mitt.emit("set-order-detail", orderList.value[0]);
total.value = res.data.count; total.value = res.data.count;
loading.value = false; loading.value = false;
}) })
@ -95,60 +80,56 @@ const getOrderList = (reload = false) => {
}); });
}; };
const submitOrder = ()=>{
createOrderApi().then(res=>{
console.log(res);
})
}
const setForm = (item, index) => { const setForm = (item, index) => {
activeStore.value = index; activeStore.value = index;
mitt.emit("set-order-detail", item); mitt.emit("set-c-order-detail", item);
}; };
onMounted(() => { onMounted(() => {
mitt.on("update-order-detail", (item) => { mitt.on("update-c-order-detail", (item) => {
console.log("===");
orderList.value[activeStore.value].paid = 1; orderList.value[activeStore.value].paid = 1;
}); });
}); });
onUnmounted(()=>{
mitt.off("update-c-order-detail");
})
</script> </script>
<template> <template>
<div class="my-order" :class="{'my-order-no-system': !isSystem}"> <div class="my-order">
<div class="header-nav"> <div class="header-nav">
<div class="nav-item"> <div class="nav-item">
{{ isSystem ? "平台订单" : "收银订单" }} {{ "收银订单" }}
</div> </div>
<div class="nav-item-btn"> <div class="nav-item-btn">
<el-radio-group <!-- <el-radio-group
v-model="tabPosition" v-model="tabPosition"
@change="changeTabPosition" @change="changeTabPosition"
size="small" size="small"
> >
<el-radio-button :value="1">全部</el-radio-button> <el-radio-button :value="1">已支付</el-radio-button>
<el-radio-button :value="2">未支付</el-radio-button> <el-radio-button :value="2">未支付</el-radio-button>
</el-radio-group> </el-radio-group> -->
<el-date-picker <el-date-picker
v-model="date" v-model="where.date"
type="daterange" type="date"
start-placeholder="开始时间" placeholder="请选择时间"
end-placeholder="结束时间"
size="small" size="small"
value-format="YYYY/MM/DD" :clearable="false"
value-format="YYYY-MM-DD"
@change="changeDate" @change="changeDate"
style="width: 14rem; margin-left: 1rem"
/> />
</div> </div>
<div class="nav-item-btn" v-if="!isSystem">
<el-radio-group
v-model="payType"
@change="changeTabPosition"
size="small"
>
<el-radio-button :value="0">全部</el-radio-button>
<el-radio-button :value="1">现金收款</el-radio-button>
<el-radio-button :value="2">线上收款</el-radio-button>
</el-radio-group>
</div>
</div> </div>
<div class="header-input"> <div class="header-input">
<el-input <el-input
v-model="where.search_info" v-model="where.number"
placeholder="请输入订单编号" placeholder="请输入订单编号"
@keydown.enter="getOrderList(true)" @keydown.enter="getOrderList(true)"
@clear="getOrderList(true)" @clear="getOrderList(true)"
@ -169,7 +150,7 @@ onMounted(() => {
</el-input> </el-input>
</div> </div>
<div <div
class="order-list" class="order-lists"
v-loading="loading" v-loading="loading"
v-infinite-scroll="getOrderList" v-infinite-scroll="getOrderList"
infinite-scroll-distance="300" infinite-scroll-distance="300"
@ -184,61 +165,53 @@ onMounted(() => {
@click="setForm(item, index)" @click="setForm(item, index)"
> >
<div class="top"> <div class="top">
<div <div class="sn">单号: {{ item.number }}</div>
class="sn"
:class="
item.pay_type === 11 ||
item.pay_type === 12 ||
item.pay_type === 13
? 'cahier'
: 'cahier2'
"
>
单号: {{ item.order_sn }}
</div>
<div class="create-time">{{ item.create_time }}</div> <div class="create-time">{{ item.create_time }}</div>
</div> </div>
<div class="shop"> <div class="shop">
<div class="left" v-if="item.orderProduct"> <div class="left" v-if="item.goods_list">
<el-image <el-image
v-for="(shop, imgkey) in item.orderProduct.slice(0, 5)" v-for="(shop, imgkey) in item.goods_list.slice(0, 5)"
:key="imgkey" :key="imgkey"
:src=" :src="shop.imgs"
shop.cart_info.productAttr.image || shop.cart_info.product.image
"
class="shop-img" class="shop-img"
></el-image> ></el-image>
<div v-if="item.orderProduct.length == 1" class="shop-name"> <div v-if="item.goods_list.length == 1" class="shop-name">
{{ item.orderProduct[0].cart_info.product.store_name }} {{ item.goods_list[0].class_name }}
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<div class="money">¥{{ item.pay_price }}</div> <div class="money">¥{{ item.total }}</div>
<div class="count">{{ item.total_num }}商品</div> <div class="count">{{ item.goods_count }}商品</div>
</div> </div>
</div> </div>
<div class="bottom"> <div class="bottom">
<div class="pay"> <div class="pay">
<div v-if="item.paid"> <div v-if="item.paid">
已支付 已支付
<span v-if="item.pay_type == 13">(支付宝收款)</span> <span v-if="item.pay_type == 9">(微信收款)</span>
<span v-if="item.pay_type == 12">(现金支付)</span> <span v-if="item.pay_type == 1">(余额支付)</span>
<span v-if="item.pay_type == 11">(微信收款)</span> <span v-if="item.pay_type == 3">(微信支付)</span>
<span v-if="item.pay_type == 0">(余额支付)</span>
<span v-if="item.pay_type == 1">(微信支付)</span>
<span v-if="item.pay_type == 9">(商户余额支付)</span>
<span v-if="item.pay_type == 10">(对公转账)</span>
</div> </div>
<div v-else style="color: #ff4a00">未支付</div> <div v-else style="color: #ff4a00">未支付</div>
</div> </div>
<div class="cashier" v-if="item.service_info"> <!-- <div class="cashier" v-if="item.service_info">
收银员: {{ item.service_info.nickname }} 收银员: {{ item.service_info.nickname }}
</div> </div>
<div class="cashier" v-else>平台订单</div> <div class="cashier" v-else>平台订单</div> -->
<div class="cashier" v-if="!item.address_id">
<el-button size="small" type="primary" @click.stop="addAddress(item)">添加收货地址</el-button>
</div>
</div> </div>
</div> </div>
<div v-if="loadEnd" class="load-end">没有更多了</div> <div v-if="loadEnd" class="load-end">没有更多了</div>
<div v-if="loading" class="load-end">加载中...</div> <div v-if="loading" class="load-end">加载中...</div>
<div style="width: 100%; height: 7rem"></div>
</div>
<div class="bottom-btn-fiexd" v-if="!loading">
<el-button class="btn" type="primary" @click="submitOrder" :disabled="!orderList.length">
提交采购</el-button
>
</div> </div>
</div> </div>
</template> </template>
@ -267,7 +240,6 @@ onMounted(() => {
} }
.nav-item-btn { .nav-item-btn {
display: flex; display: flex;
flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
@ -278,7 +250,7 @@ onMounted(() => {
height: 2.5rem; height: 2.5rem;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.order-list { .order-lists {
height: calc(100vh - 100px - 10.2rem); height: calc(100vh - 100px - 10.2rem);
overflow-y: auto; overflow-y: auto;
.item { .item {
@ -364,6 +336,13 @@ onMounted(() => {
justify-content: space-between; justify-content: space-between;
font-size: 0.9rem; font-size: 0.9rem;
color: #777; color: #777;
.manage-btn {
color: #fff;
background-color: #e6a23c;
border-radius: 0.2rem;
padding: 0 0.2rem;
margin-left: 0.5rem;
}
} }
} }
.item-active { .item-active {
@ -376,13 +355,23 @@ onMounted(() => {
color: #333; color: #333;
font-size: 0.8rem; font-size: 0.8rem;
} }
} .bottom-btn-fiexd {
.my-order-no-system{ position: absolute;
.header-nav{ bottom: 0;
height: 5.5rem; left: 0;
width: 100%;
box-sizing: border-box;
border-top: 1px solid #eee;
background-color: #fff;
z-index: 100;
height: 5.2rem;
padding: 1rem 1.5rem;
.btn {
width: 100%;
height: 100%;
font-size: 1.2rem;
border-radius: 3rem;
} }
.order-list{
height: calc(100vh - 100px - 12.2rem);
} }
} }
</style> </style>

View File

@ -11,8 +11,8 @@ const sactive = ref(-1);
const show = ref(false); const show = ref(false);
const getCategoryList = () => { const getCategoryList = () => {
merchantCategoryListApi(259).then((res) => { merchantCategoryListApi().then((res) => {
categoryList.value = res.data; categoryList.value = res.data.lists;
active.value = -1; active.value = -1;
}); });
}; };
@ -57,12 +57,12 @@ const changeActive = (index=-1, idnexc=-1) => {
@click="changeActive(index)" @click="changeActive(index)"
@mousemove="sactive=index" @mousemove="sactive=index"
> >
{{ item.cate_name }} {{ item.name }}
</div> </div>
</template> </template>
<div class="active-card" <div class="active-card"
@mouseout="sactive=-1" @mousemove="sactive=index"> @mouseout="sactive=-1" @mousemove="sactive=index">
<div class="title">{{ item.cate_name }}</div> <div class="title">{{ item.name }}</div>
<div class="list"> <div class="list">
<div <div
:class="{ 'list-active': indexc == cactive }" :class="{ 'list-active': indexc == cactive }"
@ -72,7 +72,7 @@ const changeActive = (index=-1, idnexc=-1) => {
:key="indexc" :key="indexc"
@click="changeActive(index, indexc)" @click="changeActive(index, indexc)"
> >
{{ chil.cate_name }} {{ chil.name }}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref, onMounted, onUnmounted, nextTick } from "vue"; import { ref, onMounted, onUnmounted, nextTick } from "vue";
import { cartListApi, cartDeleteApi, cartChangeApi } from "@/api/store.js"; import { cartListApi, cartDeleteApi, cartCreateApi } from "@/api/store.js";
import price from "./price.vue"; import price from "./price.vue";
import mitt from "@/utils/mitt.js"; import mitt from "@/utils/mitt.js";
import { useUserStore } from "@/store/user.js"; import { useUserStore } from "@/store/user.js";
@ -39,17 +39,12 @@ const getList = () => {
allPrice.value = 0; allPrice.value = 0;
costPrice.value = 0; costPrice.value = 0;
discounts.value = 0; discounts.value = 0;
cartListApi({ cartListApi().then((res) => {
// staff_id: userStore.userInfo.service.service_id, if (res.data?.lists?.length > 0) {
sale_type: 2, list.value = res.data.lists;
}).then((res) => { allPrice.value = +res.data.extend.total_price;
// if (res.data?.list?.length > 0) { costPrice.value = allPrice.value;
// list.value = res.data.list[0].list; } else list.value = [];
// list.value.forEach((item) => {
// allPrice.value += item.productAttr.price * item.cart_num;
// });
// costPrice.value = allPrice.value;
// } else list.value = [];
}); });
}; };
getList(); getList();
@ -61,12 +56,14 @@ const goPay = () => {
}; };
const changeCartNum = (val, old) => { const changeCartNum = (val, old) => {
cartChangeApi(val.cart_id, { cartCreateApi({
cart_num: val.cart_num, goods_id: val.goods_id,
is_new: 0,
cart_num: val.cart_num
}).then((res) => { }).then((res) => {
allPrice.value = 0; allPrice.value = 0;
list.value.forEach((item) => { list.value.forEach((item) => {
allPrice.value += item.productAttr.price * item.cart_num; allPrice.value += item.sell*item.cart_num;
}); });
costPrice.value = allPrice.value; costPrice.value = allPrice.value;
}); });
@ -76,11 +73,6 @@ const editAttr = (data) => {
emit("editPupop", data); emit("editPupop", data);
}; };
const editItem = (id, data) => {
cartChangeApi(id, data).then((res) => {
getList();
});
};
const changeAllPrice = (price) => { const changeAllPrice = (price) => {
discounts.value = costPrice.value - price; discounts.value = costPrice.value - price;
@ -101,7 +93,6 @@ const showPrice = (type = true) => {
defineExpose({ defineExpose({
getList, getList,
list, list,
editItem,
discounts, discounts,
allPrice, allPrice,
}); });
@ -129,7 +120,7 @@ onUnmounted(() => {
<div class="my-order"> <div class="my-order">
<div class="header-nav"> <div class="header-nav">
<div class="nav-item"> <div class="nav-item">
已选购 <span>{{ list.length }}</span> 已选购 <span>{{ list.length }}</span>
</div> </div>
<div class="nav-item-clear" @click="clearAll"> <div class="nav-item-clear" @click="clearAll">
<el-icon><Delete /></el-icon> (Delete) <el-icon><Delete /></el-icon> (Delete)
@ -141,27 +132,19 @@ onUnmounted(() => {
<el-image <el-image
loading="lazy" loading="lazy"
class="order-item-img" class="order-item-img"
:src=" :src="item.imgs"
(item.productAttr && item.productAttr.image) || item.product.image
"
></el-image> ></el-image>
<div class="order-item-info"> <div class="order-item-info">
<div class="order-item-title"> <div class="order-item-title">
<div class="title">{{ item.spu.store_name }}</div> <div class="title">{{ item.goods_name }}</div>
<div class="delete" @click="deleteOne(item.cart_id)">删除</div> <div class="delete" @click="deleteOne(item.cart_id)">删除</div>
</div> </div>
<div class="order-item-sku"> <div class="order-item-sku">
<span <span>{{ item.unit_name }}</span>
style="display: flex; align-items: center"
@click="editAttr(item)"
>商品规格: {{ item.productAttr.sku || "默认规格"
}}<el-icon size="16" style="margin-left: 0.2rem"
><ArrowDown /></el-icon
></span>
</div> </div>
<div class="order-item-price"> <div class="order-item-price">
<div> <div>
¥<span>{{ item.productAttr.price }}</span> ¥<span>{{ item.sell }}</span>
</div> </div>
<div> <div>
<el-input-number <el-input-number

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref, onMounted, onUnmounted, nextTick } from "vue"; import { ref, onMounted, onUnmounted, nextTick } from "vue";
import { ElMessageBox } from "element-plus"; import { ElMessage } from "element-plus";
import { getAttrValue } from "@/api/shop.js"; import { getAttrValue } from "@/api/shop.js";
import mitt from "@/utils/mitt.js"; import mitt from "@/utils/mitt.js";
@ -14,21 +14,16 @@ const show = (e) => {
const form = ref({}); const form = ref({});
const loading = ref(false); const loading = ref(false);
const mode = ref("add"); const mode = ref("add");
const editForm = ref({});
const setForm = (data, type = "add") => { const setForm = (data, type = "add") => {
mode.value = type; mode.value = type;
form.value = data; form.value = JSON.parse(JSON.stringify(data));
}; };
const emit = defineEmits(["changeItem"]); const emit = defineEmits(["changeItem"]);
const changeItem = () => { const changeItem = () => {
return console.log(form.value); if(!form.value.cart_num) form.value.cart_num = 1;
if (mode.value == "add") emit("changeItem", form.value); emit("changeItem", form.value);
else
emit("editItem", editForm.value.cart_id, {
cart_num: editForm.value.cart_num,
});
dialogVisible.value = false; dialogVisible.value = false;
}; };
@ -78,7 +73,8 @@ const close = () => {
ref="inputRef" ref="inputRef"
v-model="form.cart_num" v-model="form.cart_num"
step-strictly step-strictly
:min="1" placeholder="请输入数量(默认为1)"
:min="0"
:step="1" :step="1"
style="width: 20rem" style="width: 20rem"
/> />

View File

@ -104,7 +104,8 @@ onUnmounted(() => {
<el-image loading="lazy" :src="item.imgs"></el-image> <el-image loading="lazy" :src="item.imgs"></el-image>
<div class="shop-name">{{ item.name }}</div> <div class="shop-name">{{ item.name }}</div>
<div class="shop-price"> <div class="shop-price">
¥<span>{{ item.sell }}/{{item.unit_name}}</span> ¥<span>{{ item.sell }}</span>
<span style="color: #777;font-size: 0.9rem;">/{{item.unit_name}}</span>
</div> </div>
<div class="no-stock" v-if="item.stock == 0"> <div class="no-stock" v-if="item.stock == 0">
<div> <div>
@ -133,6 +134,8 @@ onUnmounted(() => {
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
display: flex;
flex-direction: column;
.header-nav { .header-nav {
border-radius: 0.8rem; border-radius: 0.8rem;
@ -178,7 +181,8 @@ onUnmounted(() => {
} }
.shop-list { .shop-list {
height: calc(100vh - 9.75rem); /* height: calc(100vh - 9.75rem); */
flex: 1;
width: auto; width: auto;
overflow-y: auto; overflow-y: auto;
box-sizing: border-box; box-sizing: border-box;

View File

@ -62,11 +62,11 @@ function isAllDigits(str) {
} }
const cartAddInfo = (item, change = "") => { const cartAddInfo = (item, change = "") => {
// console.log(item, change); console.log(item, change);
let q = { let q = {
goods_id: item.id, goods_id: item.id,
is_new: 0, is_new: 0,
cart_num: 1 cart_num: item.cart_num
}; };
cartCreateApi(q).then((res) => { cartCreateApi(q).then((res) => {
orderRef.value.getList(); orderRef.value.getList();
@ -74,14 +74,10 @@ const cartAddInfo = (item, change = "") => {
}; };
const changeItem = (item, change) => { const changeItem = (item, change) => {
item.cart_num = 1;
pupopRef.value.setForm(item, "add"); pupopRef.value.setForm(item, "add");
pupopRef.value.show(true); pupopRef.value.show(true);
}; };
const editItem = (id, data) => {
orderRef.value.editItem(id, data);
};
const editPupop = (item) => { const editPupop = (item) => {
pupopRef.value.setForm(item, "edit"); pupopRef.value.setForm(item, "edit");
@ -92,9 +88,6 @@ const editPupop = (item) => {
const checkOut = () => { const checkOut = () => {
let cart_id = orderRef.value.list.map((item) => item.cart_id); let cart_id = orderRef.value.list.map((item) => item.cart_id);
let query = { let query = {
takes: [],
use_coupon: {},
use_integral: false,
cart_id: cart_id, cart_id: cart_id,
}; };
if (orderRef.value.discounts > 0) { if (orderRef.value.discounts > 0) {
@ -103,7 +96,7 @@ const checkOut = () => {
} }
orderCheckApi(query).then((res) => { orderCheckApi(query).then((res) => {
payRef.value.setForm({ payRef.value.setForm({
data: res.data, data: res.data.order,
cart_id: cart_id, cart_id: cart_id,
}); });
}); });
@ -147,9 +140,9 @@ onUnmounted(() => {
@changeItem="changeItem" @changeItem="changeItem"
@loadMore="loadMore" @loadMore="loadMore"
/> />
<pupop ref="pupopRef" @changeItem="changeItem" @editItem="editItem" /> <pupop ref="pupopRef" @changeItem="cartAddInfo" />
<padding /> <!-- <padding />
<classify ref="classifyRef" @getStoreList="getStoreList"/> <classify ref="classifyRef" @getStoreList="getStoreList"/> -->
<pay ref="payRef" @paySuccess="paySuccess" /> <pay ref="payRef" @paySuccess="paySuccess" />
</div> </div>
</template> </template>

View File

@ -1,10 +1,11 @@
<script setup> <script setup>
import { ref } from "vue"; import { onMounted, onUnmounted, ref } from "vue";
import { import {
orderListApi, orderListApi,
orderStatusApi, orderStatusApi,
orderLadingApi, orderLadingApi,
cartListApi, cartListApi,
cashierinfoListApi,
} from "@/api/store.js"; } from "@/api/store.js";
import { useUserStore } from "@/store/user.js"; import { useUserStore } from "@/store/user.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
@ -15,9 +16,8 @@ import pay from "@/components/pay.vue";
const userStore = useUserStore(); const userStore = useUserStore();
const router = useRouter(); const router = useRouter();
const formData = ref({}); const formData = ref({
mitt.on("set-order-detail", (res) => { id: "",
formData.value = res;
}); });
const list = ref([]); const list = ref([]);
@ -39,7 +39,7 @@ const orderLading = () => {
dialogVisible.value = false; dialogVisible.value = false;
orderLadingApi({ orderLadingApi({
order_sn: orderLadingSn.value, order_sn: orderLadingSn.value,
staff_id: userStore.userInfo.service.service_id staff_id: userStore.userInfo.service.service_id,
}).then((res) => { }).then((res) => {
ElMessage({ ElMessage({
message: res.message, message: res.message,
@ -69,7 +69,7 @@ const getOrderStatus = (id) => {
message: res.message, message: res.message,
type: "success", type: "success",
}); });
mitt.emit("update-order-detail", {}); mitt.emit("update-sale-order-detail", {});
formData.value.paid = 1; formData.value.paid = 1;
} else { } else {
ElMessage({ ElMessage({
@ -80,85 +80,78 @@ const getOrderStatus = (id) => {
}) })
.catch((err) => {}); .catch((err) => {});
}; };
const where = ref({
page_no: 1,
page_size: 15,
loadend: false,
loading: false,
});
const goods_list = ref([]);
const getOrderList = () => {
console.log("触底");
if (formData.value.id && !where.value.loadend) {
console.log("加载");
where.value.loading = true;
cashierinfoListApi({
pid: formData.value.id,
page_no: where.value.page_no,
page_size: where.value.page_size,
}).then((res) => {
goods_list.value = [...goods_list.value, ...res.data.lists];
if (res.data.lists.length < where.value.page_size)
where.value.loadend = true;
where.value.loading = false;
where.value.page_no++;
});
}
};
onMounted(() => {
mitt.on("set-sale-order-detail", (res) => {
formData.value = res;
where.value.page_no = 1;
where.value.loadend = false;
where.value.loading = false;
goods_list.value = [];
getOrderList();
});
});
onUnmounted(() => {
mitt.off("set-sale-order-detail");
});
</script> </script>
<template> <template>
<div class="my-order"> <div class="my-order">
<div class="header-nav">
<div
v-for="(item, index) in activeStoreList"
:key="index"
class="nav-item"
:class="{
'nav-item-active': activeStore == index,
'nav-item-radius1': activeStore == index + 1,
'nav-item-radius2': activeStore == index - 1,
}"
@click="activeStore = index"
>
{{ item }}
</div>
<div
class="nav-item"
:class="{
'nav-item-radius2': activeStore == activeStoreList.length - 1,
}"
style="flex: 1"
></div>
</div>
<div class="detail" v-loading="loading"> <div class="detail" v-loading="loading">
<div class="table" v-if="formData.orderProduct && activeStore == 0"> <div
<div style="font-size: 0.9rem"> class="table"
共计 v-loading="loading"
<span style="color: #ff4a00">{{ formData.total_num }}</span> 件商品 v-infinite-scroll="getOrderList"
</div> infinite-scroll-distance="300"
<el-table infinite-scroll-delay="300"
style="height: calc(100vh - 100px - 14rem)" style="overflow: auto"
:data="formData.orderProduct" :infinite-scroll-immediate="false"
> >
<el-table-column prop="cart_info.product.store_name" label="商品信息">
<template #default="{ row }">
<div style="display: flex; align-items: center">
<el-image
style="height: 3rem; width: 3rem"
:src="
row.cart_info.productAttr.image ||
row.cart_info.product.image
"
></el-image>
<span style="margin-left: 0.5rem">{{
row.cart_info.product.store_name
}}</span>
</div>
</template>
</el-table-column>
<el-table-column
prop="cart_info.productAttr.price"
label="单价"
width="150"
/>
<el-table-column prop="product_num" label="数量" width="150" />
<el-table-column prop="total_price" label="总价" width="150" />
</el-table>
</div>
<div class="table" v-if="formData.orderProduct && activeStore == 1">
<div class="table-title">订单信息</div> <div class="table-title">订单信息</div>
<div class="table-info"> <div class="table-info">
<div class="info-item"> <div class="info-item">
<div class="info-item-title">创建时间:</div> <div class="info-item-title">订单编号:</div>
<div class="info-item-info">{{ formData.create_time }}</div> <div class="info-item-info">{{ formData.number }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">商品:</div> <div class="info-item-title">商品款数:</div>
<div class="info-item-info">{{ formData.total_num }}</div> <div class="info-item-info">{{ formData.goods_count }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">商品总价:</div> <div class="info-item-title">商品总价:</div>
<div class="info-item-info">¥{{ formData.total_price }}</div> <div class="info-item-info">¥{{ formData.total }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">支付时间:</div> <div class="info-item-title">创建时间:</div>
<div class="info-item-info">{{ formData.pay_time }}</div> <div class="info-item-info">{{ formData.create_time }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">优惠抵扣:</div> <div class="info-item-title">优惠抵扣:</div>
@ -166,95 +159,44 @@ const getOrderStatus = (id) => {
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">实际支付:</div> <div class="info-item-title">实际支付:</div>
<div class="info-item-info">¥{{ formData.pay_price }}</div> <div class="info-item-info">¥{{ formData.actual }}</div>
</div>
<div class="info-item">
<div class="info-item-title">支付时间:</div>
<div class="info-item-info">{{ formData.update_time }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="info-item-title">支付方式:</div> <div class="info-item-title">支付方式:</div>
<div class="info-item-info"> <div class="info-item-info">
<span v-if="formData.pay_type == 11">微信收款</span> <span v-if="formData.pay_type == 9">微信收款</span>
<span v-if="formData.pay_type == 12">现金支付</span> <span v-if="formData.pay_type == 1">余额支付</span>
<span v-if="formData.pay_type == 13">支付宝收款</span> <span v-if="formData.pay_type == 3">微信支付</span>
<span v-if="formData.pay_type == 0">余额支付</span>
<span v-if="formData.pay_type == 1">微信支付</span>
<span v-if="formData.pay_type == 9">商户余额支付</span>
<span v-if="formData.pay_type == 10">对公转账</span>
</div> </div>
</div> </div>
</div> </div>
<div class="table-title" v-if="formData.service_info">收银员信息</div> <div style="font-size: 0.9rem">
<div 共计
class="table-info" <span style="color: #ff4a00">{{ formData.goods_count }}</span> 款商品
v-if="formData.service_info" </div>
style="flex-direction: column" <el-table :data="goods_list">
> <el-table-column label="商品信息">
<div class="info-item"> <template #default="{ row }">
<div class="info-item-title">头像:</div> <div style="display: flex; align-items: center">
<div class="info-item-info">
<el-image <el-image
style="height: 4rem; width: 4rem; border-radius: 50%" style="height: 3rem; width: 3rem"
:src="formData.service_info.avatar" :src="row.imgs"
></el-image> ></el-image>
</div> <span style="margin-left: 0.5rem">{{ row.goods_name }}</span>
</div>
<div class="info-item">
<div class="info-item-title">昵称:</div>
<div class="info-item-info">
{{ formData.service_info.nickname }}
</div>
</div>
<div class="info-item">
<div class="info-item-title">账号:</div>
<div class="info-item-info">
{{ formData.service_info.account }}
</div>
</div>
</div>
</div>
<div class="footer" v-if="formData.service_info">
<div class="info">
<div class="ser">收银员: {{ formData.service_info.nickname }}</div>
<div class="price">
实付: <span>¥{{ formData.pay_price }}</span>
</div>
</div>
<div class="handle" v-if="!formData.paid">
<el-button class="btn" type="primary" @click="rePay(formData)"
>重新支付</el-button
>
<el-button
class="btn"
type="primary"
@click="getOrderStatus(formData.order_sn)"
>检测状态</el-button
>
<el-button
class="btn"
type="success"
@click="orderLadingComfirm(formData.order_sn)"
>提单</el-button
>
</div>
<div class="handle" v-else>已支付</div>
</div>
</div>
<pay ref="payRef" />
<el-dialog v-model="dialogVisible" title="提示" width="500">
<span
>提单前请清空购物车, 避免提单的商品与购物车商品混合,
请确保购物车内无数据后再进行提单</span
>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-if="cartCount > 0" @click="goHome">
前去清空购物车
</el-button>
<el-button v-else type="primary" @click="orderLading">
确认提单
</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-table-column>
<el-table-column prop="price" label="单价" width="150" />
<el-table-column prop="nums" label="数量" width="150" />
<el-table-column prop="total" label="总价" width="150">
</el-table-column>
</el-table>
</div>
</div>
</div> </div>
</template> </template>
@ -267,36 +209,6 @@ const getOrderStatus = (id) => {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
.header-nav {
display: flex;
background: linear-gradient(
to bottom,
#f5f5f5 50%,
#fff 50%
); /* 创建渐变背景 */
.nav-item {
height: 4rem;
width: 8rem;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
background-color: #f5f5f5;
border-radius: 1rem 1rem 0 0;
}
.nav-item-active {
background-color: #fff;
position: relative;
transition: 300ms;
}
.nav-item-radius1 {
border-radius: 0 0 1rem 0;
}
.nav-item-radius2 {
border-radius: 0 0 0 1rem;
}
}
.detail { .detail {
height: calc(100vh - 100px - 4rem); height: calc(100vh - 100px - 4rem);
box-sizing: border-box; box-sizing: border-box;
@ -305,17 +217,19 @@ const getOrderStatus = (id) => {
.table { .table {
padding: 1rem; padding: 1rem;
padding-bottom: 6rem; padding-bottom: 6rem;
overflow-y: auto;
height: 100%;
.table-title { .table-title {
font-weight: bold; font-weight: bold;
padding-top: 1rem;
} }
.table-info { .table-info {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
color: #777; color: #777;
font-size: 0.9rem; font-size: 0.9rem;
padding-bottom: 2rem; padding-bottom: 1rem;
margin-bottom: 1rem;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
&:last-child { &:last-child {
@ -333,43 +247,6 @@ const getOrderStatus = (id) => {
} }
} }
} }
.footer {
height: 6rem;
box-sizing: border-box;
padding: 0 1.5rem;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
box-shadow: 0 -1px 0.625rem #eee;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
.info {
display: flex;
align-items: flex-end;
.ser {
font-weight: bold;
margin-right: 1rem;
}
.price {
margin-right: 1rem;
span {
color: #ff4a00;
font-size: 1.2rem;
font-weight: bold;
}
}
}
.handle {
.btn {
border-radius: 4rem;
padding: 1.2rem;
}
}
}
} }
} }
</style> </style>

View File

@ -1,11 +1,11 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import { import {
orderListApi, orderListApi,
orderStatusApi, orderStatusApi,
orderLadingApi, orderLadingApi,
cartListApi, cartListApi,
saleOrderListApi saleOrderListApi,
} from "@/api/store.js"; } from "@/api/store.js";
import { useUserStore } from "@/store/user.js"; import { useUserStore } from "@/store/user.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
@ -14,13 +14,17 @@ import mitt from "@/utils/mitt.js";
const userStore = useUserStore(); const userStore = useUserStore();
const props = defineProps({ const props = defineProps({
isSystem:{ isSystem: {
type:Boolean, type: Boolean,
default:false default: false,
} },
}) source: {
type: Number,
default: 1,
},
});
const list = ref([]); const lists = ref([]);
const tabPosition = ref(1); // 1-, 2- const tabPosition = ref(1); // 1-, 2-
const changeTabPosition = (e) => { const changeTabPosition = (e) => {
@ -33,19 +37,18 @@ const changeTabPosition = (e) => {
const payRef = ref(null); const payRef = ref(null);
const date = ref(''); const date = ref("");
const changeDate = ()=>{ const changeDate = () => {
where.value.date = date.value.join('-'); where.value.date = date.value.join("-");
getOrderList(true); getOrderList(true);
} };
const where = ref({ const where = ref({
page_no: 1, page_no: 1,
page_size: 20, page_size: 20,
store_name: "", number: "",
date: "", date: "",
staff_id: 0, source: props.source,
sale_type: 2
}); });
const loading = ref(false); const loading = ref(false);
@ -57,18 +60,17 @@ const orderList = ref([]);
const getOrderList = (reload = false) => { const getOrderList = (reload = false) => {
if (reload) where.value.page_no = 1; if (reload) where.value.page_no = 1;
else if (loadEnd.value || loading.value) return; else if (loadEnd.value || loading.value) return;
if(!props.isSystem) where.value.staff_id = userStore.userInfo.service.service_id;
loading.value = true; loading.value = true;
if (tabPosition.value == 1) where.value.paid = null; if (tabPosition.value == 1) where.value.paid = null;
if (tabPosition.value == 2) where.value.paid = 0; if (tabPosition.value == 2) where.value.paid = 0;
saleOrderListApi(userStore.userInfo.service.mer_id, where.value) saleOrderListApi(where.value)
.then((res) => { .then((res) => {
if (reload) orderList.value = res.data.list; if (reload) orderList.value = res.data.lists;
else orderList.value = [...orderList.value, ...res.data.list]; else orderList.value = [...orderList.value, ...res.data.lists];
if (res.data.list.length < where.value.page_size) loadEnd.value = true; if (res.data.lists.length < where.value.page_size) loadEnd.value = true;
else where.value.page_no++; else where.value.page_no++;
activeStore.value = 0; activeStore.value = 0;
mitt.emit("set-order-detail", orderList.value[0]); mitt.emit("set-sale-order-detail", orderList.value[0]);
total.value = res.data.count; total.value = res.data.count;
loading.value = false; loading.value = false;
}) })
@ -80,14 +82,17 @@ const getOrderList = (reload = false) => {
const setForm = (item, index) => { const setForm = (item, index) => {
activeStore.value = index; activeStore.value = index;
mitt.emit("set-order-detail", item); mitt.emit("set-sale-order-detail", item);
}; };
onMounted(()=>{ onMounted(() => {
mitt.on("update-order-detail", (item) => { mitt.on("update-sale-order-detail", (item) => {
console.log('==='); console.log("===");
orderList.value[activeStore.value].paid = 1; orderList.value[activeStore.value].paid = 1;
}) });
});
onUnmounted(()=>{
mitt.off("update-sale-order-detail");
}) })
</script> </script>
@ -95,7 +100,7 @@ onMounted(()=>{
<div class="my-order"> <div class="my-order">
<div class="header-nav"> <div class="header-nav">
<div class="nav-item"> <div class="nav-item">
{{ isSystem ? '平台订单' : '收银订单' }} {{ "收银订单" }}
</div> </div>
<div class="nav-item-btn"> <div class="nav-item-btn">
<el-radio-group <el-radio-group
@ -103,7 +108,7 @@ onMounted(()=>{
@change="changeTabPosition" @change="changeTabPosition"
size="small" size="small"
> >
<el-radio-button :value="1">已支付</el-radio-button> <el-radio-button :value="1">全部</el-radio-button>
<el-radio-button :value="2">未支付</el-radio-button> <el-radio-button :value="2">未支付</el-radio-button>
</el-radio-group> </el-radio-group>
<el-date-picker <el-date-picker
@ -114,13 +119,13 @@ onMounted(()=>{
size="small" size="small"
value-format="YYYY/MM/DD" value-format="YYYY/MM/DD"
@change="changeDate" @change="changeDate"
style="width: 14rem;margin-left: 1rem;" style="width: 14rem; margin-left: 1rem"
/> />
</div> </div>
</div> </div>
<div class="header-input"> <div class="header-input">
<el-input <el-input
v-model="where.store_name" v-model="where.number"
placeholder="请输入订单编号" placeholder="请输入订单编号"
@keydown.enter="getOrderList(true)" @keydown.enter="getOrderList(true)"
@clear="getOrderList(true)" @clear="getOrderList(true)"
@ -141,7 +146,7 @@ onMounted(()=>{
</el-input> </el-input>
</div> </div>
<div <div
class="order-list" class="order-lists"
v-loading="loading" v-loading="loading"
v-infinite-scroll="getOrderList" v-infinite-scroll="getOrderList"
infinite-scroll-distance="300" infinite-scroll-distance="300"
@ -156,58 +161,41 @@ onMounted(()=>{
@click="setForm(item, index)" @click="setForm(item, index)"
> >
<div class="top"> <div class="top">
<div <div class="sn" :class="'cahier'">单号: {{ item.number }}</div>
class="sn"
:class="
item.pay_type === 11 ||
item.pay_type === 12 ||
item.pay_type === 13
? 'cahier'
: 'cahier2'
"
>
单号: {{ item.order_sn }}
</div>
<div class="create-time">{{ item.create_time }}</div> <div class="create-time">{{ item.create_time }}</div>
</div> </div>
<div class="shop"> <div class="shop">
<div class="left" v-if="item.orderProduct"> <div class="left" v-if="item.goods_list">
<el-image <el-image
v-for="(shop, imgkey) in item.orderProduct.slice(0, 5)" v-for="(shop, imgkey) in item.goods_list.slice(0, 5)"
:key="imgkey" :key="imgkey"
:src=" :src="shop.imgs"
shop.cart_info.productAttr.image || shop.cart_info.product.image
"
class="shop-img" class="shop-img"
></el-image> ></el-image>
<div v-if="item.orderProduct.length == 1" class="shop-name"> <div v-if="item.goods_list.length == 1" class="shop-name">
{{ item.orderProduct[0].cart_info.product.store_name }} {{ item.goods_list[0].class_name }}
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<div class="money">¥{{ item.pay_price }}</div> <div class="money">¥{{ item.total }}</div>
<div class="count">{{ item.total_num }}商品</div> <div class="count">{{ item.goods_count }}商品</div>
</div> </div>
</div> </div>
<div class="bottom"> <div class="bottom">
<div class="pay"> <div class="pay">
<div v-if="item.paid"> <div v-if="item.paid">
已支付 已支付
<span v-if="item.pay_type == 13">(支付宝收款)</span> <span v-if="item.pay_type == 9">(微信收款)</span>
<span v-if="item.pay_type == 12">(现金支付)</span> <span v-if="item.pay_type == 1">(余额支付)</span>
<span v-if="item.pay_type == 11">(微信收款)</span> <span v-if="item.pay_type == 3">(微信支付)</span>
<span v-if="item.pay_type == 0">(余额支付)</span>
<span v-if="item.pay_type == 1">(微信支付)</span>
<span v-if="item.pay_type == 9">(商户余额支付)</span>
<span v-if="item.pay_type == 10">(对公转账)</span>
<!-- <span class="manage-btn">待处理</span> --> <!-- <span class="manage-btn">待处理</span> -->
</div> </div>
<div v-else style="color: #ff4a00">未支付</div> <div v-else style="color: #ff4a00">未支付</div>
</div> </div>
<div class="cashier" v-if="item.service_info"> <!-- <div class="cashier" v-if="item.service_info">
收银员: {{ item.service_info.nickname }} 收银员: {{ item.service_info.nickname }}
</div> </div>
<div class="cashier" v-else>平台订单</div> <div class="cashier" v-else>平台订单</div> -->
</div> </div>
</div> </div>
<div v-if="loadEnd" class="load-end">没有更多了</div> <div v-if="loadEnd" class="load-end">没有更多了</div>
@ -235,7 +223,7 @@ onMounted(()=>{
span { span {
color: #ff4a00; color: #ff4a00;
} }
.nav-item{ .nav-item {
font-weight: bold; font-weight: bold;
} }
.nav-item-btn { .nav-item-btn {
@ -250,7 +238,7 @@ onMounted(()=>{
height: 2.5rem; height: 2.5rem;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.order-list { .order-lists {
height: calc(100vh - 100px - 10.2rem); height: calc(100vh - 100px - 10.2rem);
overflow-y: auto; overflow-y: auto;
.item { .item {
@ -336,7 +324,7 @@ onMounted(()=>{
justify-content: space-between; justify-content: space-between;
font-size: 0.9rem; font-size: 0.9rem;
color: #777; color: #777;
.manage-btn{ .manage-btn {
color: #fff; color: #fff;
background-color: #e6a23c; background-color: #e6a23c;
border-radius: 0.2rem; border-radius: 0.2rem;

View File

@ -9,9 +9,9 @@ import { ref, nextTick } from "vue";
<template> <template>
<div class="my-card"> <div class="my-card">
<order style="flex-shrink: 0;" ref="orderRef" isSystem/> <!-- <order style="flex-shrink: 0;" ref="orderRef" isSystem/>
<padding /> <padding />
<detail ref="detailRef"/> <detail ref="detailRef"/> -->
</div> </div>
</template> </template>

39
src/views/test/test.vue Normal file
View File

@ -0,0 +1,39 @@
<template>
<!-- 小票内容 -->
<div ref="receipt" id="receipt" style="max-width: 200px;">
<h2>小票标题</h2>
<p>商品名称: 商品1</p>
<p>价格: ¥10.00</p>
<p>数量: 1</p>
<p>-------------------</p>
<p>总计: ¥10.00</p>
<p>-------------------</p>
</div>
<el-button type="priamry" @click="onPrint">打印</el-button>
</template>
<script setup>
import print from 'print-js'
import { ref } from 'vue';
const receipt = ref(null);
const onPrint = ()=>{
console.log('开始打印', receipt);
print({
printable: 'receipt',
type: 'html',
maxWidth: '200'
});
}
</script>
<style lang="scss">
#receipt {
padding: 10px;
padding-bottom: 20px;
font-size: 12px;
border: 1px solid #ccc;
width: 200px;
}
</style>